Parallel Programming - Finished OpenMP
[matches/honours.git] / course / semester2 / pprog / assignment1 / mthread / test_barrier.c
1 #include "barrier.h"
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <stdbool.h>
6
7 #include "barrier.c"
8
9 /**
10  * @file test_barrier.c
11  * @purpose Test the barrier!
12  * @author Sam Moore (20503628) 2012
13  */
14
15 // Compile with gcc --std=c99 -o test_barrier test_barrier.c -lpthread
16 // Run with ./test_barrier
17 // Expected output:
18 //      All worker threads print "Hello" before all worker threads print "Goodbye"
19 //      At any point, the "Boss" reports that it is waiting for "Hello" to be said, and goes to sleep.
20 //      At some point whilst worker threads say "Goodbye", the "Boss" wakes up and reports that "Hello" has been said.
21 //      The Boss should *never* report that "Hello" has been said until all workers say "Hello". 
22 //      But it may report that it is waiting for "Hello" to be said at any time.
23 //      Confused yet? I am, and I wrote this!
24 //      NOTE: Two barriers are required to prevent deadlocking!
25
26
27 pthread_mutex_t mutex_printf; // Printing is not thread safe! Mutex needed!
28 Barrier worker_barrier[2];
29
30 void * Worker(void * args)
31 {
32         
33         //while (true) // Comment out to only test one step
34         {
35                 Barrier_Enter(&worker_barrier[0]); //  Workers are now printing "Hello"
36
37                 pthread_mutex_lock(&mutex_printf);
38                 printf("Worker %p: Hello\n", (args)); // Only one thread can print at a time
39                 pthread_mutex_unlock(&mutex_printf);
40
41                 sleep(1);
42                 Barrier_Join(&worker_barrier[0]);
43
44                 pthread_mutex_lock(&mutex_printf);
45                 printf("\tWorker %p: Goodbye\n", (args)); // Only one thread can print at a time
46                 pthread_mutex_unlock(&mutex_printf);
47                 
48
49                 Barrier_Join(&worker_barrier[1]); // If we replace this with:
50                 //Barrier_Join(&worker_barrier[0]); 
51                 // Then there is (usually) a deadlock, because the first thread to leave the barrier 
52                 // immediately reactivates it, and other threads are unable to leave.
53         
54         }
55 }
56
57 void * Boss(void * args)
58 {
59         //while (true)
60         {
61                 pthread_mutex_lock(&mutex_printf);
62                 printf("Boss is waiting for \"Hello\" to be said.\n", (args)); // Only one thread can print at a time
63                 pthread_mutex_unlock(&mutex_printf);            
64                 Barrier_Wait(&worker_barrier[0]);
65                 pthread_mutex_lock(&mutex_printf);
66                 printf("Boss continues now that workers have said \"Hello\".\n", (args)); // Only one thread can print at a time
67                 pthread_mutex_unlock(&mutex_printf);
68                 sleep(2);
69                 
70         }
71 }
72
73 int main(int argc, char ** argv)
74 {
75         #define NUM_THREADS 4
76         pthread_t worker[NUM_THREADS];
77         pthread_t boss;
78         
79         Barrier_Init(&worker_barrier[0], NUM_THREADS); // Initialise barriers with number of contributing threads
80         Barrier_Init(&worker_barrier[1], NUM_THREADS);
81
82         pthread_create(&boss, NULL, Boss, NULL); //Start boss
83
84         for (long i = 0; i < NUM_THREADS; ++i)
85                 pthread_create(worker+i, NULL, Worker, (void*)(i)); // Start all threads
86
87         for (int i = 0; i < NUM_THREADS; ++i) // Join threads
88                 pthread_join(worker[i], NULL);
89         return 0;
90 }

UCC git Repository :: git.ucc.asn.au