Start semaphoring out
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -4,7 +4,7 @@ CFLAGS = -Iinc -pthread -lrt
 | 
				
			|||||||
VPATH = src
 | 
					VPATH = src
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OBJECTS := %.o list.o producer.o transformer.o consumer.o
 | 
					OBJECTS := %.o list.o producer.o transformer.o consumer.o
 | 
				
			||||||
EXECUTE := main.out test.out
 | 
					EXECUTE := main.out #test.out
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: all clean
 | 
					.PHONY: all clean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,2 +1,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void consumer ();
 | 
					/*
 | 
				
			||||||
 | 
					   consumer:
 | 
				
			||||||
 | 
					      Unlinks blocks from list2,
 | 
				
			||||||
 | 
					      Consumes them,
 | 
				
			||||||
 | 
					      Links them to freelist
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					void *consumer (void *);
 | 
				
			||||||
@@ -5,3 +5,8 @@ extern block memory[N];
 | 
				
			|||||||
// create the three lists
 | 
					// create the three lists
 | 
				
			||||||
extern list lists[3];
 | 
					extern list lists[3];
 | 
				
			||||||
extern list *freelist, *list1, *list2;
 | 
					extern list *freelist, *list1, *list2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// count semaphores
 | 
				
			||||||
 | 
					extern sem_t semfl, seml1, seml2;
 | 
				
			||||||
 | 
					// binary semaphores
 | 
				
			||||||
 | 
					extern sem_t mutfl, mutl1, mutl2;
 | 
				
			||||||
@@ -20,5 +20,4 @@ void   list_link   (list *l, block *b);
 | 
				
			|||||||
//   list_init:   links an array of blocks onto the end of a list
 | 
					//   list_init:   links an array of blocks onto the end of a list
 | 
				
			||||||
void   list_init   (list *l, block *m, int size);
 | 
					void   list_init   (list *l, block *m, int size);
 | 
				
			||||||
//   list_print:  prints a list
 | 
					//   list_print:  prints a list
 | 
				
			||||||
void   list_print  (list *l);
 | 
					void   list_print(list *l, bool verbose = false);
 | 
				
			||||||
void   list_concise(list *l);
 | 
					 | 
				
			||||||
@@ -1,2 +1,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void producer ();
 | 
					/*
 | 
				
			||||||
 | 
					   producer:
 | 
				
			||||||
 | 
					      Unlinks blocks from freelist,
 | 
				
			||||||
 | 
					      Produces them,
 | 
				
			||||||
 | 
					      Links them to list1
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					void *producer (void *);
 | 
				
			||||||
@@ -1,2 +1,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void transformer ();
 | 
					/*
 | 
				
			||||||
 | 
					   transformer:
 | 
				
			||||||
 | 
					      Unlinks block x from list1
 | 
				
			||||||
 | 
					      Unlinks block y from freelist
 | 
				
			||||||
 | 
					      Uses block x to generate block y's data
 | 
				
			||||||
 | 
					      Links block x to freelist
 | 
				
			||||||
 | 
					      Links block y to list2
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					void *transformer (void *);
 | 
				
			||||||
@@ -1,9 +1,29 @@
 | 
				
			|||||||
 | 
					#include <semaphore.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
#include "list.hpp"
 | 
					#include "list.hpp"
 | 
				
			||||||
#include "globals.hpp"
 | 
					#include "globals.hpp" // freelist list1 list2
 | 
				
			||||||
#include "consumer.hpp"
 | 
					#include "consumer.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void consumer () {
 | 
					int consume(block* c);
 | 
				
			||||||
   block* c = list_unlink(list2);
 | 
					
 | 
				
			||||||
   //TODO: consume information in block c
 | 
					void *consumer (void *) {
 | 
				
			||||||
   list_link(freelist, c);
 | 
					   while (true) {
 | 
				
			||||||
 | 
					      sem_wait(&seml2); // decrease seml2
 | 
				
			||||||
 | 
					      sem_wait(&mutl2);
 | 
				
			||||||
 | 
					      block* c = list_unlink(list2);
 | 
				
			||||||
 | 
					      sem_post(&mutl2);
 | 
				
			||||||
 | 
					      //* consume information in block c
 | 
				
			||||||
 | 
					      consume(c);
 | 
				
			||||||
 | 
					      sem_wait(&mutfl);
 | 
				
			||||||
 | 
					      list_link(freelist, c);
 | 
				
			||||||
 | 
					      sem_post(&mutfl);
 | 
				
			||||||
 | 
					      sem_post(&semfl); // increase freelist
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
 | 
					   return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int consume(block *c) {
 | 
				
			||||||
 | 
					   c->data = -c->data;
 | 
				
			||||||
 | 
					   usleep(75);
 | 
				
			||||||
 | 
					   return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								src/list.cpp
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								src/list.cpp
									
									
									
									
									
								
							@@ -60,7 +60,8 @@ void list_init (list *l, block *m, int size) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// YAML-like, because I like YAML
 | 
					// YAML-like, because I like YAML
 | 
				
			||||||
void list_print(list *l) {
 | 
					
 | 
				
			||||||
 | 
					void print_verbose(list *l) {
 | 
				
			||||||
   if (!l) return;
 | 
					   if (!l) return;
 | 
				
			||||||
   std::printf("l_%p:\n  - start:  '%p',\n  - end:    '%p',\n  - length: '%d',\n  - blocks:",l,l->start,l->end,l->length);
 | 
					   std::printf("l_%p:\n  - start:  '%p',\n  - end:    '%p',\n  - length: '%d',\n  - blocks:",l,l->start,l->end,l->length);
 | 
				
			||||||
   block* b = l->start;
 | 
					   block* b = l->start;
 | 
				
			||||||
@@ -73,17 +74,21 @@ void list_print(list *l) {
 | 
				
			|||||||
      std::printf(" []\n");
 | 
					      std::printf(" []\n");
 | 
				
			||||||
   }
 | 
					   }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					// l_[addr]{size}: {element:value, ...}
 | 
				
			||||||
void list_concise (list *l) {
 | 
					void print_concise(list *l) {
 | 
				
			||||||
   if (!l) return;
 | 
					   if (!l) return;
 | 
				
			||||||
   std::printf("%lx: {", (__uint64_t)l&0xffff);
 | 
					   std::printf("l_%lx{%d}: {", (long int)l&0xffff, l->length);
 | 
				
			||||||
   block *b = l->start;
 | 
					   block *b = l->start;
 | 
				
			||||||
   if (b) {
 | 
					   if (b) {
 | 
				
			||||||
      do {
 | 
					      do {
 | 
				
			||||||
         std::printf("%lx:%d, ", (__uint64_t)b&0xfff, b->data);
 | 
					         std::printf("%lx:%d, ", (long int)b&0xfff, b->data);
 | 
				
			||||||
      } while (b = b->next);
 | 
					      } while (b = b->next);
 | 
				
			||||||
      std::printf("\b\b} \n");
 | 
					      std::printf("\b\b} \n");
 | 
				
			||||||
   } else {
 | 
					   } else {
 | 
				
			||||||
      std::printf("}\n");
 | 
					      std::printf("}\n");
 | 
				
			||||||
   }
 | 
					   }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void list_print(list *l, bool verbose) {
 | 
				
			||||||
 | 
					   (verbose?print_verbose:print_concise)(l);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										47
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								src/main.cpp
									
									
									
									
									
								
							@@ -1,8 +1,13 @@
 | 
				
			|||||||
#include <cstdint>
 | 
					#include <semaphore.h>
 | 
				
			||||||
#include <cstdio>
 | 
					#include <pthread.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
#include "list.hpp"
 | 
					#include "list.hpp"
 | 
				
			||||||
#include "globals.hpp"
 | 
					#include "globals.hpp"
 | 
				
			||||||
#include "producer.hpp"
 | 
					#include "producer.hpp"
 | 
				
			||||||
 | 
					#include "consumer.hpp"
 | 
				
			||||||
 | 
					#include "transformer.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create all of memory
 | 
					// Create all of memory
 | 
				
			||||||
block memory[N] = {0};
 | 
					block memory[N] = {0};
 | 
				
			||||||
@@ -10,9 +15,45 @@ block memory[N] = {0};
 | 
				
			|||||||
list lists[3] = {0};
 | 
					list lists[3] = {0};
 | 
				
			||||||
list *freelist = &lists[0], *list1 = &lists[1], *list2 = &lists[2];
 | 
					list *freelist = &lists[0], *list1 = &lists[1], *list2 = &lists[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// count semaphores
 | 
				
			||||||
 | 
					sem_t semfl, seml1, seml2;
 | 
				
			||||||
 | 
					// binary semaphores
 | 
				
			||||||
 | 
					sem_t mutfl, mutl1, mutl2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main (int argc, char* argv[]) {
 | 
					int main (int argc, char* argv[]) {
 | 
				
			||||||
   // initialize the freelist
 | 
					   // initialize the freelist
 | 
				
			||||||
   list_init(freelist, memory, N);
 | 
					   list_init(freelist, memory, N);
 | 
				
			||||||
   //TODO: Use pthreads to split execution
 | 
					
 | 
				
			||||||
   //TODO: Implement a semaphore solution to the problem
 | 
					   //TODO: Implement a semaphore solution to the problem
 | 
				
			||||||
 | 
					   sem_init(&semfl, 0, freelist->length);
 | 
				
			||||||
 | 
					   sem_init(&seml1, 0, 0);
 | 
				
			||||||
 | 
					   sem_init(&seml2, 0, 0);
 | 
				
			||||||
 | 
					   sem_init(&mutfl, 0, 1);
 | 
				
			||||||
 | 
					   sem_init(&mutl1, 0, 1);
 | 
				
			||||||
 | 
					   sem_init(&mutl2, 0, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   //TODO: Use pthreads to split execution
 | 
				
			||||||
 | 
					   // Make some pthreads
 | 
				
			||||||
 | 
					   pthread_t thread1, thread2, thread3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   // Create thread1 as producer
 | 
				
			||||||
 | 
					   pthread_create(&thread1, NULL, producer, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   // Create thread2 as transformer
 | 
				
			||||||
 | 
					   pthread_create(&thread2, NULL, transformer, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   // Create thread3 as consumer
 | 
				
			||||||
 | 
					   pthread_create(&thread3, NULL, consumer, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   while (true) {
 | 
				
			||||||
 | 
					      list_print(freelist);
 | 
				
			||||||
 | 
					      list_print(list1);
 | 
				
			||||||
 | 
					      list_print(list2);
 | 
				
			||||||
 | 
					      sleep(1);
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
 | 
					   // Wait for them to finish
 | 
				
			||||||
 | 
					   pthread_join(thread1, NULL);
 | 
				
			||||||
 | 
					   pthread_join(thread2, NULL);
 | 
				
			||||||
 | 
					   pthread_join(thread3, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,32 @@
 | 
				
			|||||||
 | 
					#include <semaphore.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
#include "list.hpp"
 | 
					#include "list.hpp"
 | 
				
			||||||
#include "globals.hpp"
 | 
					#include "globals.hpp" // freelist list1 list2
 | 
				
			||||||
#include "producer.hpp"
 | 
					#include "producer.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void producer () {
 | 
					#define wait(x) sem_wait(&x)
 | 
				
			||||||
   block* b = list_unlink(freelist);
 | 
					#define sgnl(x) sem_post(&x)
 | 
				
			||||||
   //TODO: Produce information in block b
 | 
					
 | 
				
			||||||
   list_link(list1, b);
 | 
					void produce(block* b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *producer (void *) {
 | 
				
			||||||
 | 
					   while (true) {
 | 
				
			||||||
 | 
					      wait(semfl); // wait for freelist not empty
 | 
				
			||||||
 | 
					      wait(mutfl); // lock freelist
 | 
				
			||||||
 | 
					      block *b = list_unlink(freelist);
 | 
				
			||||||
 | 
					      sgnl(mutfl); // unlock freelist
 | 
				
			||||||
 | 
					      //* Produce information in block b
 | 
				
			||||||
 | 
					      produce(b);
 | 
				
			||||||
 | 
					      wait(mutl1); // lock l1
 | 
				
			||||||
 | 
					      list_link(list1, b);
 | 
				
			||||||
 | 
					      sgnl(mutl1); // unlock l1
 | 
				
			||||||
 | 
					      sgnl(seml1);
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
 | 
					   return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void produce(block *b) {
 | 
				
			||||||
 | 
					   b->data++;
 | 
				
			||||||
 | 
					   usleep(65);
 | 
				
			||||||
 | 
					   return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										42
									
								
								src/test.cpp
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								src/test.cpp
									
									
									
									
									
								
							@@ -1,5 +1,6 @@
 | 
				
			|||||||
#include <cstdint>
 | 
					#include <semaphore.h>
 | 
				
			||||||
#include <cstdio>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
#include "list.hpp"
 | 
					#include "list.hpp"
 | 
				
			||||||
#include "globals.hpp"
 | 
					#include "globals.hpp"
 | 
				
			||||||
#include "producer.hpp"
 | 
					#include "producer.hpp"
 | 
				
			||||||
@@ -14,42 +15,47 @@ list *freelist = &lists[0],
 | 
				
			|||||||
     *list1 = &lists[1],
 | 
					     *list1 = &lists[1],
 | 
				
			||||||
     *list2 = &lists[2];
 | 
					     *list2 = &lists[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// count semaphores
 | 
				
			||||||
 | 
					sem_t semfl, seml1, seml2;
 | 
				
			||||||
 | 
					// binary semaphores
 | 
				
			||||||
 | 
					sem_t mutfl, mutl1, mutl2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void producer_test();
 | 
					void producer_test();
 | 
				
			||||||
void transfer_test();
 | 
					void transfer_test();
 | 
				
			||||||
void consumer_test();
 | 
					void consumer_test();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char *argv[]) {
 | 
					int main(int argc, char *argv[]) {
 | 
				
			||||||
   list_init(freelist, memory, N);
 | 
					   list_init(freelist, memory, N);
 | 
				
			||||||
   list_concise(freelist);
 | 
					   list_print(freelist);
 | 
				
			||||||
   producer_test();
 | 
					   //producer_test();
 | 
				
			||||||
   transfer_test();
 | 
					   //transfer_test();
 | 
				
			||||||
   consumer_test();
 | 
					   //consumer_test();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void producer_test() {
 | 
					void producer_test() {
 | 
				
			||||||
   printf("Starting producer_test:\n");\
 | 
					   printf("Starting producer_test:\n");\
 | 
				
			||||||
   producer();
 | 
					   producer(NULL);
 | 
				
			||||||
   list_concise(freelist);
 | 
					   list_print(freelist);
 | 
				
			||||||
   list_concise(list1);
 | 
					   list_print(list1);
 | 
				
			||||||
   list_concise(list2);
 | 
					   list_print(list2);
 | 
				
			||||||
   printf("Ending producer_test\n");
 | 
					   printf("Ending producer_test\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void transfer_test() {
 | 
					void transfer_test() {
 | 
				
			||||||
   printf("Starting transfer_test:\n");
 | 
					   printf("Starting transfer_test:\n");
 | 
				
			||||||
   transformer();
 | 
					   transformer(NULL);
 | 
				
			||||||
   list_concise(freelist);
 | 
					   list_print(freelist);
 | 
				
			||||||
   list_concise(list1);
 | 
					   list_print(list1);
 | 
				
			||||||
   list_concise(list2);
 | 
					   list_print(list2);
 | 
				
			||||||
   printf("Ending transfer_test\n");
 | 
					   printf("Ending transfer_test\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void consumer_test() {
 | 
					void consumer_test() {
 | 
				
			||||||
   printf("Starting consumer_test:\n");
 | 
					   printf("Starting consumer_test:\n");
 | 
				
			||||||
   consumer();
 | 
					   consumer(NULL);
 | 
				
			||||||
   list_concise(freelist);
 | 
					   list_print(freelist);
 | 
				
			||||||
   list_concise(list1);
 | 
					   list_print(list1);
 | 
				
			||||||
   list_concise(list2);
 | 
					   list_print(list2);
 | 
				
			||||||
   printf("Ending consumer_test\n");
 | 
					   printf("Ending consumer_test\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,44 @@
 | 
				
			|||||||
 | 
					#include <semaphore.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
#include "list.hpp"
 | 
					#include "list.hpp"
 | 
				
			||||||
#include "globals.hpp"
 | 
					#include "globals.hpp" // freelist list1 list2
 | 
				
			||||||
#include "transformer.hpp"
 | 
					#include "transformer.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void transformer () {
 | 
					void transform(block* x, block* y);
 | 
				
			||||||
   block* x = list_unlink(list1);
 | 
					
 | 
				
			||||||
   block* y = list_unlink(freelist);
 | 
					void *transformer (void *) {
 | 
				
			||||||
   //TODO: use block x to produce info in y
 | 
					   block *x, *y;
 | 
				
			||||||
   list_link(freelist, x);
 | 
					   while (true) {
 | 
				
			||||||
   list_link(list2, y);
 | 
					      sem_wait(&seml1); // decrease seml1
 | 
				
			||||||
 | 
					      sem_wait(&mutl1);
 | 
				
			||||||
 | 
					      x = list_unlink(list1);
 | 
				
			||||||
 | 
					      sem_post(&mutl1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      sem_wait(&semfl); // decrease semfl
 | 
				
			||||||
 | 
					      sem_wait(&mutfl);
 | 
				
			||||||
 | 
					      y = list_unlink(freelist);
 | 
				
			||||||
 | 
					      sem_post(&mutfl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      //* use block x to produce info in y
 | 
				
			||||||
 | 
					      transform(x, y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      sem_wait(&mutfl);
 | 
				
			||||||
 | 
					      list_link(freelist, x);
 | 
				
			||||||
 | 
					      sem_post(&mutfl);
 | 
				
			||||||
 | 
					      sem_post(&semfl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      sem_wait(&mutl2);
 | 
				
			||||||
 | 
					      list_link(list2, y);
 | 
				
			||||||
 | 
					      sem_post(&mutl2);
 | 
				
			||||||
 | 
					      sem_post(&seml2);
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
 | 
					   return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void transform(block *x, block *y) {
 | 
				
			||||||
 | 
					   x->data ^= y->data;
 | 
				
			||||||
 | 
					   y->data ^= x->data;
 | 
				
			||||||
 | 
					   x->data ^= y->data;
 | 
				
			||||||
 | 
					   usleep(55);
 | 
				
			||||||
 | 
					   return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user