-
Notifications
You must be signed in to change notification settings - Fork 0
/
test_wait.c
103 lines (82 loc) · 2.34 KB
/
test_wait.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
100
101
102
103
#include <emmintrin.h>
#include <pthread.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
atomic_int n_wait;
atomic_int n_waiting;
int64_t inline time_us(void) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (int64_t)ts.tv_sec * 1000000 + (int64_t)ts.tv_nsec / 1000;
}
int64_t inline time_ns(void) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (int64_t)ts.tv_sec * 1000000000 + (int64_t)ts.tv_nsec;
}
void *thread_runner(void *arg) {
int id = *(int *)arg;
while (n_wait >= 0) {
if (id < n_wait) {
pthread_mutex_lock(&mutex);
n_waiting++;
// printf("#-%d: waiting\n", id);
pthread_cond_wait(&cond, &mutex);
// printf("#-%d: wakeup\n", id);
n_waiting--;
pthread_mutex_unlock(&mutex);
if (n_wait < 0) {
return 0;
}
}
}
return 0;
}
// gcc -O3 -std=c11 test_wait.c -o test_wait && ./test_wait
int main() {
const int n_threads = 6; // 3
const int n_loops = 1; // 10
pthread_t pids[n_threads];
int ids[n_threads];
n_wait = 0;
for (int i = 0; i < n_threads; i++) {
ids[i] = i;
pthread_create(&pids[i], NULL, thread_runner, &ids[i]);
}
int64_t total_0 = 0;
int64_t total_1 = 0;
for (int i = 0; i < n_loops; i++) {
int64_t t0 = time_ns();
// wait.
{
n_wait = n_threads;
while (n_waiting != n_wait) {
}
}
int64_t t1 = time_ns();
total_0 += (t1 - t0);
// wake up.
{
pthread_mutex_lock(&mutex);
n_wait = 0;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
while (n_waiting != n_wait) {
}
}
total_1 += (time_ns() - t1);
}
printf("n_threads: %d, n_loops: %d\n", n_threads, n_loops);
printf(" avg_wait: %6.3f us\n", 1.0 * total_0 / (1000 * n_loops));
printf(" avg_wakeup: %6.3f us\n", 1.0 * total_1 / (1000 * n_loops));
n_wait = -1;
for (int i = 0; i < n_threads; i++) {
pthread_join(pids[i], NULL);
}
return 0;
}