Let us consider an alternate barrier implementation in which there are
condition variable-mutex pairs for implementing a barrier for
threads.
- The barrier works as follows: at the first level, threads are paired up and each pair of threads shares a single condition variable-mutex pair.
- A designated member of the pair waits for both threads to arrive at the pairwise barrier. Once this happens, all the designated members are organized into pairs, and this process continues until there is only one thread.
- At this point, we know that all threads have reached the barrier point. We must release all threads at this point. However, releasing them requires signaling all
condition variables. We use the same hierarchical strategy for doing this. The designated thread in a pair signals the respective condition variables.
1 typedef struct barrier_node {
2 pthread_mutex_t count_lock;
3 pthread_cond_t ok_to_proceed_up;
4 pthread_cond_t ok_to_proceed_down;
5 int count;
6 } mylib_barrier_t_internal;
7
8 typedef struct barrier_node mylog_logbarrier_t[MAX_THREADS];
9 pthread_t p_threads[MAX_THREADS];
10 pthread_attr_t attr;
11
12 void mylib_init_barrier(mylog_logbarrier_t b) {
13 int i;
14 for (i = 0; i < MAX_THREADS; i++) {
15 b[i].count = 0;
16 pthread_mutex_init(&(b[i].count_lock), NULL);
17 pthread_cond_init(&(b[i].ok_to_proceed_up), NULL);
18 pthread_cond_init(&(b[i].ok_to_proceed_down), NULL);
19 }
20 }
21
22 void mylib_logbarrier (mylog_logbarrier_t b, int num_threads,
23 int thread_id) {
24 int i, base, index;
25 i=2;
26 base = 0;
27
28 do {
29 index = base + thread_id / i;
30 if (thread_id % i == 0) {
31 pthread_mutex_lock(&(b[index].count_lock));
32 b[index].count ++;
33 while (b[index].count < 2)
34 pthread_cond_wait(&(b[index].ok_to_proceed_up),
35 &(b[index].count_lock));
36 pthread_mutex_unlock(&(b[index].count_lock));
37 }
38 else {
39 pthread_mutex_lock(&(b[index].count_lock));
40 b[index].count ++;
41 if (b[index].count == 2)
42 pthread_cond_signal(&(b[index].ok_to_proceed_up));
43 while (pthread_cond_wait(&(b[index].ok_to_proceed_down),
44 &(b[index].count_lock)) != 0);
45 pthread_mutex_unlock(&(b[index].count_lock));
46 break;
47 }
48 base = base + num_threads/i;
49 i=i*2;
50 } while (i <= num_threads);
51 i=i/2;
52 for (; i > 1; i = i / 2) {
53 base = base - num_threads/i;
54 index = base + thread_id / i;
55 pthread_mutex_lock(&(b[index].count_lock));
56 b[index].count = 0;
57 pthread_cond_signal(&(b[index].ok_to_proceed_down));
58 pthread_mutex_unlock(&(b[index].count_lock));
59 }
60 }