-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathbarrier.c
99 lines (85 loc) · 3.01 KB
/
barrier.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include "message.h"
#include "ruler.h"
#include <inttypes.h>
#include <string.h>
void init_barrier (struct barrier *barrier, const char *name,
unsigned size) {
barrier->name = name;
barrier->size = size;
assert (!barrier->disabled);
if (size < 2)
return;
pthread_mutex_init (&barrier->mutex, 0);
pthread_cond_init (&barrier->condition, 0);
}
void abort_waiting_and_disable_barrier (struct barrier *barrier) {
if (barrier->size < 2)
return;
if (pthread_mutex_lock (&barrier->mutex))
fatal_error ("failed to acquire '%s[%" PRIu64 "]' barrier lock "
"to abort waiting",
barrier->name, barrier->met);
uint64_t met = barrier->met;
if (!barrier->disabled) {
very_verbose (0, "disabling '%s[%" PRIu64 "]' barrier", barrier->name,
barrier->met);
barrier->disabled = true;
if (barrier->waiting) {
very_verbose (
0, "aborting %u waiting threads in '%s[%" PRIu64 "]' barrier",
barrier->waiting, barrier->name, barrier->met);
barrier->waiting = 0;
barrier->met++;
pthread_cond_broadcast (&barrier->condition);
}
}
if (pthread_mutex_unlock (&barrier->mutex))
fatal_error ("failed to release '%s[%" PRIu64 "]' barrier lock "
"to abort waiting",
barrier->name, met);
}
bool rendezvous (struct barrier *barrier, struct ring *ring,
bool expected_enabled) {
if (barrier->size < 2)
return true;
#ifndef NFASTPATH
if (barrier->disabled)
return false;
#endif
if (pthread_mutex_lock (&barrier->mutex))
fatal_error ("failed to acquire '%s[%" PRIu64 "]' barrier lock "
"during rendezvous of 'ring[%u}'",
barrier->name, barrier->met, ring->id);
uint64_t met = barrier->met;
bool res;
if (barrier->disabled)
res = false;
else {
assert (barrier->waiting < barrier->size);
barrier->waiting++;
very_verbose (ring, "entered '%s[%" PRIu64 "]' barrier (%u waiting)",
barrier->name, met, barrier->waiting);
if (barrier->waiting == barrier->size) {
barrier->met++;
barrier->waiting = 0;
pthread_cond_broadcast (&barrier->condition);
} else
while (!barrier->disabled && met == barrier->met)
pthread_cond_wait (&barrier->condition, &barrier->mutex);
barrier->left++;
very_verbose (ring, "leaving '%s[%" PRIu64 "]' barrier (%u left)",
barrier->name, met, barrier->left);
if (barrier->left == barrier->size)
barrier->left = 0;
res = !barrier->disabled;
}
if (pthread_mutex_unlock (&barrier->mutex))
fatal_error ("failed to release '%s[%" PRIu64 "]' barrier lock "
"during rendezvous of 'ring[%u}'",
barrier->name, met, ring->id);
if (expected_enabled && !res)
fatal_error ("unexpected disabled '%s[%" PRIu64 "]' barrier "
"(%u waiting) in rendezvous of 'ring[%u]'",
barrier->name, met, barrier->waiting, ring->id);
return res;
}