]> git.saurik.com Git - apple/libpthread.git/blame - tests/cond.c
libpthread-301.20.1.tar.gz
[apple/libpthread.git] / tests / cond.c
CommitLineData
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
14struct 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 25static 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 56T_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}