]> git.saurik.com Git - apple/libpthread.git/blame - tests/mutex_prepost.c
libpthread-330.230.1.tar.gz
[apple/libpthread.git] / tests / mutex_prepost.c
CommitLineData
214d78a2
A
1#include <pthread.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <stdbool.h>
6#include <errno.h>
7#include <TargetConditionals.h>
8
9#include <pthread/pthread_spis.h>
10
11#include <sys/sysctl.h>
12
13#include "darwintest_defaults.h"
14#include <darwintest_multiprocess.h>
15
16struct context {
17 union {
18 pthread_mutex_t mutex;
19 pthread_cond_t cond;
20 };
21 pthread_mutex_t mutex2;
22 long value;
23 long count;
24};
25
26static void *test_cond(void *ptr) {
27 struct context *context = ptr;
28 int res;
29
30 res = pthread_cond_wait(&context->cond, &context->mutex2);
31 T_ASSERT_POSIX_ZERO(res, "condition wait on condvar completed");
32 res = pthread_mutex_unlock(&context->mutex2);
33 T_ASSERT_POSIX_ZERO(res, "unlock condvar mutex");
34 return NULL;
35}
36
37static void *test_cond_wake(void *ptr) {
38 struct context *context = ptr;
39 int res;
40
41 res = pthread_mutex_lock(&context->mutex2);
42 T_ASSERT_POSIX_ZERO(res, "locked condvar mutex");
43 res = pthread_cond_signal(&context->cond);
44 T_ASSERT_POSIX_ZERO(res, "condvar signalled");
45 res = pthread_mutex_unlock(&context->mutex2);
46 T_ASSERT_POSIX_ZERO(res, "dropped condvar mutex");
47
48 return NULL;
49}
50
51static void *test_thread(void *ptr) {
52 int res;
53 long old;
54 struct context *context = ptr;
55
56 int i = 0;
57 char *str;
58
59 do {
60 bool try = i++ & 1;
61
62 if (!try){
63 str = "pthread_mutex_lock";
64 res = pthread_mutex_lock(&context->mutex);
65 } else {
66 str = "pthread_mutex_trylock";
67 res = pthread_mutex_trylock(&context->mutex);
68 }
69 if (res != 0) {
70 if (try && res == EBUSY) {
71 continue;
72 }
73 T_ASSERT_POSIX_ZERO(res, "[%ld] %s", context->count, str);
74 }
75
76 old = __sync_fetch_and_or(&context->value, 1);
77 if ((old & 1) != 0) {
78 T_FAIL("[%ld] OR %lx\n", context->count, old);
79 }
80
81 old = __sync_fetch_and_and(&context->value, 0);
82 if ((old & 1) == 0) {
83 T_FAIL("[%ld] AND %lx\n", context->count, old);
84 }
85
86 res = pthread_mutex_unlock(&context->mutex);
87 if (res) {
88 T_ASSERT_POSIX_ZERO(res, "[%ld] pthread_mutex_lock", context->count);
89 }
90 } while (__sync_fetch_and_sub(&context->count, 1) > 0);
91 return NULL;
92}
93
94
95static void
96_test_condvar_prepost_race(void)
97{
98 struct context context = {
99 .mutex = PTHREAD_MUTEX_INITIALIZER,
100 .mutex2 = PTHREAD_MUTEX_INITIALIZER,
101 .value = 0,
102 .count = 1000,
103 };
104 int i;
105 int res;
106 int threads = 8;
107 pthread_t p[threads];
108 for (i = 0; i < threads; ++i) {
109 res = pthread_create(&p[i], NULL, test_thread, &context);
110 T_ASSERT_POSIX_ZERO(res, "pthread_create()");
111 }
112 for (i = 0; i < threads; ++i) {
113 res = pthread_join(p[i], NULL);
114 T_ASSERT_POSIX_ZERO(res, "pthread_join()");
115 }
116
117 T_PASS("initial pthread mutex storm completed");
118
119 pthread_mutex_destroy(&context.mutex);
120
121 pthread_cond_init(&context.cond, NULL);
122 res = pthread_mutex_lock(&context.mutex2);
123 T_ASSERT_POSIX_ZERO(res, "mutex lock for condition wait");
124 res = pthread_create(&p[0], NULL, test_cond, &context);
125 T_QUIET; T_ASSERT_POSIX_ZERO(res, "pthread_create()");
126 res = pthread_create(&p[1], NULL, test_cond_wake, &context);
127 T_QUIET; T_ASSERT_POSIX_ZERO(res, "pthread_create()");
128
129 res = pthread_join(p[0], NULL);
130 T_QUIET; T_ASSERT_POSIX_ZERO(res, "pthread_join()");
131 res = pthread_join(p[1], NULL);
132 T_QUIET; T_ASSERT_POSIX_ZERO(res, "pthread_join()");
133
134 pthread_cond_destroy(&context.cond);
135}
136
137T_DECL(mutex_prepost_fairshare, "pthread_mutex_prepost (fairshare)",
138 T_META_ALL_VALID_ARCHS(YES),
139 T_META_ENVVAR("PTHREAD_MUTEX_DEFAULT_POLICY=1"))
140{
141 int i;
142 int count = 100;
143 for (i=0; i < count; i++) {
144 _test_condvar_prepost_race();
145 }
146}
147
148T_DECL(mutex_prepost_firstfit, "pthread_mutex_prepost (firstfit)",
149 T_META_ALL_VALID_ARCHS(YES),
150 T_META_ENVVAR("PTHREAD_MUTEX_DEFAULT_POLICY=3"))
151{
152 int i;
153 int count = 100;
154 for (i=0; i < count; i++) {
155 _test_condvar_prepost_race();
156 }
157}