]> git.saurik.com Git - apple/libpthread.git/blame - tests/mutex.c
libpthread-454.100.8.tar.gz
[apple/libpthread.git] / tests / mutex.c
CommitLineData
964d3577 1#include <pthread.h>
964d3577
A
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <stdbool.h>
6#include <errno.h>
214d78a2 7#include <TargetConditionals.h>
964d3577 8
76b7b9a2
A
9#include <pthread/pthread_spis.h>
10
11#include <sys/sysctl.h>
12
a0619f9c 13#include "darwintest_defaults.h"
76b7b9a2 14#include <darwintest_multiprocess.h>
2546420a 15
964d3577
A
16struct context {
17 pthread_mutex_t mutex;
18 long value;
19 long count;
20};
21
2546420a 22static void *test_thread(void *ptr) {
964d3577
A
23 int res;
24 long old;
25 struct context *context = ptr;
26
27 int i = 0;
28 char *str;
29
30 do {
2546420a 31 bool try = i++ & 1;
964d3577 32
2546420a
A
33 if (!try){
34 str = "pthread_mutex_lock";
35 res = pthread_mutex_lock(&context->mutex);
36 } else {
37 str = "pthread_mutex_trylock";
38 res = pthread_mutex_trylock(&context->mutex);
964d3577
A
39 }
40 if (res != 0) {
41 if (try && res == EBUSY) {
42 continue;
43 }
2546420a 44 T_ASSERT_POSIX_ZERO(res, "[%ld] %s", context->count, str);
964d3577
A
45 }
46
47 old = __sync_fetch_and_or(&context->value, 1);
48 if ((old & 1) != 0) {
2546420a 49 T_FAIL("[%ld] OR %lx\n", context->count, old);
964d3577
A
50 }
51
52 old = __sync_fetch_and_and(&context->value, 0);
53 if ((old & 1) == 0) {
2546420a 54 T_FAIL("[%ld] AND %lx\n", context->count, old);
964d3577
A
55 }
56
57 res = pthread_mutex_unlock(&context->mutex);
58 if (res) {
2546420a 59 T_ASSERT_POSIX_ZERO(res, "[%ld] pthread_mutex_lock", context->count);
964d3577
A
60 }
61 } while (__sync_fetch_and_sub(&context->count, 1) > 0);
2546420a
A
62
63 T_PASS("thread completed successfully");
64
65 return NULL;
964d3577
A
66}
67
2546420a
A
68T_DECL(mutex, "pthread_mutex",
69 T_META_ALL_VALID_ARCHS(YES))
964d3577
A
70{
71 struct context context = {
72 .mutex = PTHREAD_MUTEX_INITIALIZER,
73 .value = 0,
2546420a 74 .count = 1000000,
964d3577
A
75 };
76 int i;
77 int res;
2546420a 78 int threads = 8;
964d3577
A
79 pthread_t p[threads];
80 for (i = 0; i < threads; ++i) {
81 res = pthread_create(&p[i], NULL, test_thread, &context);
2546420a 82 T_ASSERT_POSIX_ZERO(res, "pthread_create()");
964d3577
A
83 }
84 for (i = 0; i < threads; ++i) {
85 res = pthread_join(p[i], NULL);
2546420a 86 T_ASSERT_POSIX_ZERO(res, "pthread_join()");
964d3577 87 }
964d3577 88}
76b7b9a2
A
89
90static void
91check_process_default_mutex_policy(int expected_policy)
92{
93 pthread_mutexattr_t mattr;
94 T_EXPECT_POSIX_ZERO(pthread_mutexattr_init(&mattr), "pthread_mutexattr_init()");
95
96 int policy;
97 T_EXPECT_POSIX_ZERO(pthread_mutexattr_getpolicy_np(&mattr, &policy),
98 "pthread_mutexattr_getpolicy_np()");
99 T_LOG("policy was %d", policy);
100 T_EXPECT_EQ(policy, expected_policy, "Saw the expected default policy");
101
102 T_EXPECT_POSIX_ZERO(pthread_mutexattr_destroy(&mattr), "pthread_mutexattr_destroy()");
103}
104
105T_DECL(mutex_default_policy,
c1f56ec9 106 "Tests that the default mutex policy is firstfit")
76b7b9a2 107{
214d78a2 108 check_process_default_mutex_policy(_PTHREAD_MUTEX_POLICY_FIRSTFIT);
76b7b9a2
A
109}
110
111T_DECL(mutex_default_policy_sysctl,
112 "Tests that setting the policy sysctl changes the default policy")
113{
c1f56ec9 114 int fairshare_default = _PTHREAD_MUTEX_POLICY_FAIRSHARE;
76b7b9a2 115 T_EXPECT_POSIX_ZERO(
c1f56ec9
A
116 sysctlbyname("kern.pthread_mutex_default_policy", NULL, NULL, &fairshare_default, sizeof(fairshare_default)),
117 "Changed the default policy sysctl to fairshare");
76b7b9a2
A
118
119 dt_helper_t helper = dt_child_helper("mutex_default_policy_sysctl_helper");
120 dt_run_helpers(&helper, 1, 5);
121}
122
123T_HELPER_DECL(mutex_default_policy_sysctl_helper, "sysctl helper")
124{
c1f56ec9 125 check_process_default_mutex_policy(_PTHREAD_MUTEX_POLICY_FAIRSHARE);
76b7b9a2 126
c1f56ec9 127 int default_default = _PTHREAD_MUTEX_POLICY_FIRSTFIT;
76b7b9a2
A
128 T_EXPECT_POSIX_ZERO(
129 sysctlbyname("kern.pthread_mutex_default_policy", NULL, NULL, &default_default, sizeof(default_default)),
c1f56ec9 130 "Restored the default policy to firstfit");
76b7b9a2
A
131
132 T_END;
133}
134
135T_DECL(mutex_default_policy_envvar,
136 "Tests that setting the policy environment variable changes the default policy",
c1f56ec9 137 T_META_ENVVAR("PTHREAD_MUTEX_DEFAULT_POLICY=1"))
76b7b9a2 138{
c1f56ec9
A
139 check_process_default_mutex_policy(_PTHREAD_MUTEX_POLICY_FAIRSHARE);
140}
141
142static void *
143mutex_as_semaphore_signaller(void *arg)
144{
145 pthread_mutex_t *mtx = arg;
146 int rc = pthread_mutex_unlock(mtx);
147 T_ASSERT_POSIX_ZERO(rc, "unlock");
148
149 return NULL;
150}
151
152T_DECL(mutex_as_semaphore_lock_owned, "Recursively lock a normal mutex to use as a semaphore")
153{
154 pthread_t signaller;
155 pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
156 int rc = pthread_mutex_lock(&mtx);
157 T_ASSERT_POSIX_ZERO(rc, "lock");
158
159 rc = pthread_create(&signaller, NULL, mutex_as_semaphore_signaller, &mtx);
160 T_ASSERT_POSIX_ZERO(rc, "create");
161
162 rc = pthread_mutex_lock(&mtx);
163 T_ASSERT_POSIX_ZERO(rc, "recursive lock");
164
165 rc = pthread_join(signaller, NULL);
166 T_ASSERT_POSIX_ZERO(rc, "join");
167
168 T_END;
76b7b9a2 169}