Start semaphoring out

This commit is contained in:
John 2022-04-04 20:12:40 -05:00
parent 31a7583074
commit 927b209cef
12 changed files with 205 additions and 53 deletions

View File

@ -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

View File

@ -1,2 +1,8 @@
void consumer (); /*
consumer:
Unlinks blocks from list2,
Consumes them,
Links them to freelist
*/
void *consumer (void *);

View File

@ -4,4 +4,9 @@
extern block memory[N]; 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;

View File

@ -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);

View File

@ -1,2 +1,8 @@
void producer (); /*
producer:
Unlinks blocks from freelist,
Produces them,
Links them to list1
*/
void *producer (void *);

View File

@ -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 *);

View File

@ -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;
}

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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;
}

View File

@ -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");
} }

View File

@ -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;
}