]>
Commit | Line | Data |
---|---|---|
964d3577 A |
1 | #include <assert.h> |
2 | #include <pthread.h> | |
3 | #include <stdio.h> | |
4 | #include <stdlib.h> | |
5 | #include <string.h> | |
6 | #include <unistd.h> | |
7 | #include <stdbool.h> | |
8 | #include <errno.h> | |
9 | #include <libkern/OSAtomic.h> | |
10 | ||
a0619f9c | 11 | #include "darwintest_defaults.h" |
2546420a A |
12 | #include <darwintest_utils.h> |
13 | ||
964d3577 A |
14 | struct context { |
15 | pthread_cond_t cond; | |
16 | pthread_mutex_t mutex; | |
a0619f9c | 17 | pthread_cond_t ready_cond; |
964d3577 A |
18 | long waiters; |
19 | long count; | |
a0619f9c A |
20 | bool ready; |
21 | char _padding[7]; | |
964d3577 A |
22 | }; |
23 | ||
a0619f9c | 24 | |
2546420a | 25 | static void *wait_thread(void *ptr) { |
964d3577 A |
26 | struct context *context = ptr; |
27 | ||
a0619f9c A |
28 | // tell producer thread that we are ready |
29 | T_QUIET; | |
30 | T_ASSERT_POSIX_ZERO(pthread_mutex_lock(&context->mutex), "pthread_mutex_lock"); | |
31 | context->ready = true; | |
32 | T_QUIET; | |
33 | T_ASSERT_POSIX_ZERO(pthread_cond_signal(&context->ready_cond), "pthread_cond_signal"); | |
34 | ||
964d3577 A |
35 | bool loop = true; |
36 | while (loop) { | |
a0619f9c | 37 | |
964d3577 A |
38 | if (context->count > 0) { |
39 | ++context->waiters; | |
a0619f9c A |
40 | T_QUIET; |
41 | T_ASSERT_POSIX_ZERO(pthread_cond_wait(&context->cond, &context->mutex), "[%ld] pthread_rwlock_unlock", context->count); | |
964d3577 A |
42 | --context->waiters; |
43 | --context->count; | |
44 | } else { | |
45 | loop = false; | |
46 | } | |
a0619f9c | 47 | |
964d3577 A |
48 | } |
49 | ||
a0619f9c A |
50 | T_QUIET; |
51 | T_ASSERT_POSIX_ZERO(pthread_mutex_unlock(&context->mutex), "[%ld] pthread_mutex_unlock", context->count); | |
52 | ||
964d3577 A |
53 | return NULL; |
54 | } | |
55 | ||
2546420a | 56 | T_DECL(cond, "pthread_cond", |
a0619f9c | 57 | T_META_ALL_VALID_ARCHS(YES), T_META_TIMEOUT(120), T_META_CHECK_LEAKS(NO)) |
964d3577 A |
58 | { |
59 | struct context context = { | |
60 | .cond = PTHREAD_COND_INITIALIZER, | |
61 | .mutex = PTHREAD_MUTEX_INITIALIZER, | |
a0619f9c | 62 | .ready_cond = PTHREAD_COND_INITIALIZER, |
964d3577 | 63 | .waiters = 0, |
a0619f9c A |
64 | .count = 50000 * dt_ncpu(), |
65 | .ready = false, | |
964d3577 A |
66 | }; |
67 | int i; | |
68 | int res; | |
69 | int threads = 2; | |
70 | pthread_t p[threads]; | |
71 | for (i = 0; i < threads; ++i) { | |
a0619f9c A |
72 | T_QUIET; |
73 | T_ASSERT_POSIX_ZERO(pthread_mutex_lock(&context.mutex), "pthread_mutex_lock"); | |
74 | ||
75 | context.ready = false; | |
76 | ||
77 | T_QUIET; | |
78 | T_ASSERT_POSIX_ZERO(pthread_create(&p[i], NULL, wait_thread, &context), "pthread_create"); | |
79 | ||
80 | do { | |
81 | // mutex will be dropped and allow consumer thread to acquire | |
82 | T_QUIET; | |
83 | T_ASSERT_POSIX_ZERO(pthread_cond_wait(&context.ready_cond, &context.mutex), "pthread_cond_wait"); | |
84 | } while (context.ready == false); | |
85 | ||
86 | T_QUIET; | |
87 | T_ASSERT_POSIX_ZERO(pthread_mutex_unlock(&context.mutex), "pthread_mutex_lock"); | |
88 | ||
89 | T_LOG("Thread %d ready.", i); | |
964d3577 A |
90 | } |
91 | ||
a0619f9c A |
92 | T_LOG("All threads ready."); |
93 | ||
964d3577 A |
94 | long half = context.count / 2; |
95 | ||
96 | bool loop = true; | |
97 | while (loop) { | |
a0619f9c A |
98 | T_QUIET; |
99 | T_ASSERT_POSIX_ZERO(pthread_mutex_lock(&context.mutex), "[%ld] pthread_mutex_lock", context.count); | |
964d3577 A |
100 | if (context.waiters) { |
101 | char *str; | |
102 | if (context.count > half) { | |
103 | str = "pthread_cond_broadcast"; | |
104 | res = pthread_cond_broadcast(&context.cond); | |
105 | } else { | |
106 | str = "pthread_cond_signal"; | |
107 | res = pthread_cond_signal(&context.cond); | |
108 | } | |
a0619f9c A |
109 | T_QUIET; |
110 | T_ASSERT_POSIX_ZERO(res, "[%ld] %s", context.count, str); | |
964d3577 A |
111 | } |
112 | if (context.count <= 0) { | |
113 | loop = false; | |
2546420a | 114 | T_PASS("Completed stres test successfully."); |
964d3577 | 115 | } |
a0619f9c A |
116 | |
117 | T_QUIET; | |
118 | T_ASSERT_POSIX_ZERO(pthread_mutex_unlock(&context.mutex), | |
119 | "[%ld] pthread_mutex_unlock", context.count); | |
964d3577 | 120 | } |
a0619f9c | 121 | |
964d3577 | 122 | for (i = 0; i < threads; ++i) { |
2546420a | 123 | T_ASSERT_POSIX_ZERO(pthread_join(p[i], NULL), NULL); |
964d3577 | 124 | } |
964d3577 | 125 | } |