diff --git a/inc/globals.hpp b/inc/globals.hpp index d4a6ad4..bf6d4bb 100644 --- a/inc/globals.hpp +++ b/inc/globals.hpp @@ -1,4 +1,10 @@ #define N 8 +#define timescale 5 + +//function defines, renaming wait and signal +#define wait(x) sem_wait(&x) +#define signal(x) sem_post(&x) + // Shared memory through global variables // Create all of memory extern block memory[N]; @@ -7,6 +13,8 @@ extern list lists[3]; extern list *freelist, *list1, *list2; // count semaphores -extern sem_t semfl, seml1, seml2; +extern sem_t sem_freelist, sem_list1, sem_list2; // binary semaphores -extern sem_t mutfl, mutl1, mutl2; \ No newline at end of file +extern sem_t mut_freelist, mut_list1, mut_list2; +// binary semaphores for reading/writing +extern sem_t mut_take, mut_give; \ No newline at end of file diff --git a/inc/list.hpp b/inc/list.hpp index a5eb338..eb0dcdf 100644 --- a/inc/list.hpp +++ b/inc/list.hpp @@ -14,7 +14,7 @@ struct list { // list operations: // list_unlink: unlinks the last block in the list, and returns a pointer to it -block *list_unlink (list *l); +block* list_unlink (list* l, bool lastblock=0); // list_link: links the block b onto the end of the list void list_link (list *l, block *b); // list_init: links an array of blocks onto the end of a list diff --git a/src/consumer.cpp b/src/consumer.cpp index cd2ed4e..be4a2d2 100644 --- a/src/consumer.cpp +++ b/src/consumer.cpp @@ -1,29 +1,35 @@ #include #include -#include "list.hpp" -#include "globals.hpp" // freelist list1 list2 +#include "list.hpp" // list implementation +#include "globals.hpp" // lists, sems, muts #include "consumer.hpp" +#define unlink(x) list_unlink(x) +#define link(x) list_link(x) + int consume(block* c); void *consumer (void *) { while (true) { - sem_wait(&seml2); // decrease seml2 - sem_wait(&mutl2); + + wait(sem_list2); + wait(mut_list2); block* c = list_unlink(list2); - sem_post(&mutl2); + signal(mut_list2); + //* consume information in block c consume(c); - sem_wait(&mutfl); + + wait(mut_freelist); list_link(freelist, c); - sem_post(&mutfl); - sem_post(&semfl); // increase freelist + signal(mut_freelist); + signal(sem_freelist); + } return nullptr; } int consume(block *c) { - c->data = -c->data; - usleep(75); - return 0; + usleep(75*timescale); + return c->data; } diff --git a/src/list.cpp b/src/list.cpp index 48d74fd..13bb167 100644 --- a/src/list.cpp +++ b/src/list.cpp @@ -1,8 +1,34 @@ #include "list.hpp" #include +// dequeue the first block +block* list_dequeue (list* l) { + // we need a list + if (!l) return nullptr; + block* b = l->start; + // can't unlink from an empty list + if (!b) return nullptr; + // remove b + if (b->next) { + // b is not the only element of the list + // chop of the head + l->start = b->next; + // bandage the wound + l->start->prev = nullptr; + // wrap the severed head + b->next = nullptr; + } else { + // b is the only element of the list + l->start = nullptr; + l->end = nullptr; + } + // if we get here, we've removed element b from the list + l->length--; + return b; +} + // pop the last block -block* list_unlink (list* l) { +block* list_pop (list* l) { // we need a list if (!l) return nullptr; block* b = l->end; @@ -27,6 +53,10 @@ block* list_unlink (list* l) { return b; } +block* list_unlink (list* l, bool lastblock) { + return (lastblock?list_pop:list_dequeue)(l); +} + // push a block void list_link (list* l, block* b) { // can't link to a nonexistent list diff --git a/src/main.cpp b/src/main.cpp index 4102cc1..3f72976 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,21 +16,27 @@ list lists[3] = {0}; list *freelist = &lists[0], *list1 = &lists[1], *list2 = &lists[2]; // count semaphores -sem_t semfl, seml1, seml2; +sem_t sem_freelist, sem_list1, sem_list2; // binary semaphores -sem_t mutfl, mutl1, mutl2; +sem_t mut_freelist, mut_list1, mut_list2; +// binary semaphores for reading/writing +sem_t mut_take, mut_give; int main (int argc, char* argv[]) { // initialize the freelist list_init(freelist, memory, N); //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); + // counting semaphores measure the length + sem_init(&sem_freelist, 0, freelist->length); + sem_init(&sem_list1, 0, 0); + sem_init(&sem_list2, 0, 0); + // binary semaphores create mutual exclusion + sem_init(&mut_freelist, 0, 1); + sem_init(&mut_list1, 0, 1); + sem_init(&mut_list2, 0, 1); + sem_init(&mut_take, 0, 1); + sem_init(&mut_give, 0, 1); //TODO: Use pthreads to split execution // Make some pthreads @@ -46,10 +52,11 @@ int main (int argc, char* argv[]) { pthread_create(&thread3, NULL, consumer, NULL); while (true) { + printf("\033c"); list_print(freelist); list_print(list1); list_print(list2); - sleep(1); + usleep(100*timescale); } // Wait for them to finish pthread_join(thread1, NULL); diff --git a/src/producer.cpp b/src/producer.cpp index 985622f..b5d2849 100644 --- a/src/producer.cpp +++ b/src/producer.cpp @@ -1,32 +1,32 @@ #include #include -#include "list.hpp" -#include "globals.hpp" // freelist list1 list2 +#include "list.hpp" // list implementation +#include "globals.hpp" // lists, sems, muts #include "producer.hpp" -#define wait(x) sem_wait(&x) -#define sgnl(x) sem_post(&x) - void produce(block* b); void *producer (void *) { while (true) { - wait(semfl); // wait for freelist not empty - wait(mutfl); // lock freelist + + wait(sem_freelist); // wait for freelist not empty + wait(mut_freelist); // lock freelist block *b = list_unlink(freelist); - sgnl(mutfl); // unlock freelist + signal(mut_freelist); // unlock freelist + //* Produce information in block b produce(b); - wait(mutl1); // lock l1 + + wait(mut_list1); // lock l1 list_link(list1, b); - sgnl(mutl1); // unlock l1 - sgnl(seml1); + signal(mut_list1); // unlock l1 + signal(sem_list1); + } return nullptr; } void produce(block *b) { - b->data++; - usleep(65); + usleep(65*timescale); return; } diff --git a/src/test.cpp b/src/test.cpp index 8af736d..7f32713 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -16,9 +16,9 @@ list *freelist = &lists[0], *list2 = &lists[2]; // count semaphores -sem_t semfl, seml1, seml2; +sem_t sem_freelist, sem_list1, sem_list2; // binary semaphores -sem_t mutfl, mutl1, mutl2; +sem_t mut_freelist, mut_list1, mut_list2; void producer_test(); void transfer_test(); diff --git a/src/transformer.cpp b/src/transformer.cpp index 64768aa..9b11cbe 100644 --- a/src/transformer.cpp +++ b/src/transformer.cpp @@ -1,7 +1,7 @@ #include #include -#include "list.hpp" -#include "globals.hpp" // freelist list1 list2 +#include "list.hpp" // list implementation +#include "globals.hpp" // lists, sems, muts #include "transformer.hpp" void transform(block* x, block* y); @@ -9,36 +9,35 @@ void transform(block* x, block* y); void *transformer (void *) { block *x, *y; while (true) { - sem_wait(&seml1); // decrease seml1 - sem_wait(&mutl1); - x = list_unlink(list1); - sem_post(&mutl1); - sem_wait(&semfl); // decrease semfl - sem_wait(&mutfl); + wait(sem_list1); + wait(mut_list1); + x = list_unlink(list1); + signal(mut_list1); + + wait(sem_freelist); + wait(mut_freelist); y = list_unlink(freelist); - sem_post(&mutfl); + signal(mut_freelist); //* use block x to produce info in y transform(x, y); - sem_wait(&mutfl); + wait(mut_freelist); list_link(freelist, x); - sem_post(&mutfl); - sem_post(&semfl); + signal(mut_freelist); + signal(sem_freelist); - sem_wait(&mutl2); + wait(mut_list2); list_link(list2, y); - sem_post(&mutl2); - sem_post(&seml2); + signal(mut_list2); + signal(sem_list2); + } return nullptr; } void transform(block *x, block *y) { - x->data ^= y->data; - y->data ^= x->data; - x->data ^= y->data; - usleep(55); + usleep(55*timescale); return; }