7 #include <TargetConditionals.h>
9 #include <pthread/pthread_spis.h>
11 #include <sys/sysctl.h>
13 #include "darwintest_defaults.h"
14 #include <darwintest_multiprocess.h>
18 pthread_mutex_t mutex
;
21 pthread_mutex_t mutex2
;
26 static void *test_cond(void *ptr
) {
27 struct context
*context
= ptr
;
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");
37 static void *test_cond_wake(void *ptr
) {
38 struct context
*context
= ptr
;
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");
51 static void *test_thread(void *ptr
) {
54 struct context
*context
= ptr
;
63 str
= "pthread_mutex_lock";
64 res
= pthread_mutex_lock(&context
->mutex
);
66 str
= "pthread_mutex_trylock";
67 res
= pthread_mutex_trylock(&context
->mutex
);
70 if (try && res
== EBUSY
) {
73 T_ASSERT_POSIX_ZERO(res
, "[%ld] %s", context
->count
, str
);
76 old
= __sync_fetch_and_or(&context
->value
, 1);
78 T_FAIL("[%ld] OR %lx\n", context
->count
, old
);
81 old
= __sync_fetch_and_and(&context
->value
, 0);
83 T_FAIL("[%ld] AND %lx\n", context
->count
, old
);
86 res
= pthread_mutex_unlock(&context
->mutex
);
88 T_ASSERT_POSIX_ZERO(res
, "[%ld] pthread_mutex_lock", context
->count
);
90 } while (__sync_fetch_and_sub(&context
->count
, 1) > 0);
96 _test_condvar_prepost_race(void)
98 struct context context
= {
99 .mutex
= PTHREAD_MUTEX_INITIALIZER
,
100 .mutex2
= PTHREAD_MUTEX_INITIALIZER
,
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()");
112 for (i
= 0; i
< threads
; ++i
) {
113 res
= pthread_join(p
[i
], NULL
);
114 T_ASSERT_POSIX_ZERO(res
, "pthread_join()");
117 T_PASS("initial pthread mutex storm completed");
119 pthread_mutex_destroy(&context
.mutex
);
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()");
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()");
134 pthread_cond_destroy(&context
.cond
);
137 T_DECL(mutex_prepost_fairshare
, "pthread_mutex_prepost (fairshare)",
138 T_META_ALL_VALID_ARCHS(YES
),
139 T_META_ENVVAR("PTHREAD_MUTEX_DEFAULT_POLICY=1"))
143 for (i
=0; i
< count
; i
++) {
144 _test_condvar_prepost_race();
148 T_DECL(mutex_prepost_firstfit
, "pthread_mutex_prepost (firstfit)",
149 T_META_ALL_VALID_ARCHS(YES
),
150 T_META_ENVVAR("PTHREAD_MUTEX_DEFAULT_POLICY=3"))
154 for (i
=0; i
< count
; i
++) {
155 _test_condvar_prepost_race();