X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=course%2Fsemester2%2Fpprog%2Fassignment1%2Fmthread%2Ftest_barrier.c;fp=course%2Fsemester2%2Fpprog%2Fassignment1%2Fmthread%2Ftest_barrier.c;h=d2efebb16058d2b2b61e33651d1d6a5bd9995620;hb=20979b1c07eda73b7f86b2fe8cb66eb58d959e04;hp=0000000000000000000000000000000000000000;hpb=47b0dba32b8e0e0deedfbfc6db49b65b930e2889;p=matches%2Fhonours.git diff --git a/course/semester2/pprog/assignment1/mthread/test_barrier.c b/course/semester2/pprog/assignment1/mthread/test_barrier.c new file mode 100644 index 00000000..d2efebb1 --- /dev/null +++ b/course/semester2/pprog/assignment1/mthread/test_barrier.c @@ -0,0 +1,90 @@ +#include "barrier.h" +#include +#include +#include +#include + +#include "barrier.c" + +/** + * @file test_barrier.c + * @purpose Test the barrier! + * @author Sam Moore (20503628) 2012 + */ + +// Compile with gcc --std=c99 -o test_barrier test_barrier.c -lpthread +// Run with ./test_barrier +// Expected output: +// All worker threads print "Hello" before all worker threads print "Goodbye" +// At any point, the "Boss" reports that it is waiting for "Hello" to be said, and goes to sleep. +// At some point whilst worker threads say "Goodbye", the "Boss" wakes up and reports that "Hello" has been said. +// The Boss should *never* report that "Hello" has been said until all workers say "Hello". +// But it may report that it is waiting for "Hello" to be said at any time. +// Confused yet? I am, and I wrote this! +// NOTE: Two barriers are required to prevent deadlocking! + + +pthread_mutex_t mutex_printf; // Printing is not thread safe! Mutex needed! +Barrier worker_barrier[2]; + +void * Worker(void * args) +{ + + //while (true) // Comment out to only test one step + { + Barrier_Enter(&worker_barrier[0]); // Workers are now printing "Hello" + + pthread_mutex_lock(&mutex_printf); + printf("Worker %p: Hello\n", (args)); // Only one thread can print at a time + pthread_mutex_unlock(&mutex_printf); + + sleep(1); + Barrier_Join(&worker_barrier[0]); + + pthread_mutex_lock(&mutex_printf); + printf("\tWorker %p: Goodbye\n", (args)); // Only one thread can print at a time + pthread_mutex_unlock(&mutex_printf); + + + Barrier_Join(&worker_barrier[1]); // If we replace this with: + //Barrier_Join(&worker_barrier[0]); + // Then there is (usually) a deadlock, because the first thread to leave the barrier + // immediately reactivates it, and other threads are unable to leave. + + } +} + +void * Boss(void * args) +{ + //while (true) + { + pthread_mutex_lock(&mutex_printf); + printf("Boss is waiting for \"Hello\" to be said.\n", (args)); // Only one thread can print at a time + pthread_mutex_unlock(&mutex_printf); + Barrier_Wait(&worker_barrier[0]); + pthread_mutex_lock(&mutex_printf); + printf("Boss continues now that workers have said \"Hello\".\n", (args)); // Only one thread can print at a time + pthread_mutex_unlock(&mutex_printf); + sleep(2); + + } +} + +int main(int argc, char ** argv) +{ + #define NUM_THREADS 4 + pthread_t worker[NUM_THREADS]; + pthread_t boss; + + Barrier_Init(&worker_barrier[0], NUM_THREADS); // Initialise barriers with number of contributing threads + Barrier_Init(&worker_barrier[1], NUM_THREADS); + + pthread_create(&boss, NULL, Boss, NULL); //Start boss + + for (long i = 0; i < NUM_THREADS; ++i) + pthread_create(worker+i, NULL, Worker, (void*)(i)); // Start all threads + + for (int i = 0; i < NUM_THREADS; ++i) // Join threads + pthread_join(worker[i], NULL); + return 0; +}