]> git.saurik.com Git - apple/libpthread.git/blob - tests/mutex.c
libpthread-218.30.1.tar.gz
[apple/libpthread.git] / tests / mutex.c
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
8 #include <darwintest.h>
9
10 struct context {
11 pthread_mutex_t mutex;
12 long value;
13 long count;
14 };
15
16 static void *test_thread(void *ptr) {
17 int res;
18 long old;
19 struct context *context = ptr;
20
21 int i = 0;
22 char *str;
23
24 do {
25 bool try = i++ & 1;
26
27 if (!try){
28 str = "pthread_mutex_lock";
29 res = pthread_mutex_lock(&context->mutex);
30 } else {
31 str = "pthread_mutex_trylock";
32 res = pthread_mutex_trylock(&context->mutex);
33 }
34 if (res != 0) {
35 if (try && res == EBUSY) {
36 continue;
37 }
38 T_ASSERT_POSIX_ZERO(res, "[%ld] %s", context->count, str);
39 }
40
41 old = __sync_fetch_and_or(&context->value, 1);
42 if ((old & 1) != 0) {
43 T_FAIL("[%ld] OR %lx\n", context->count, old);
44 }
45
46 old = __sync_fetch_and_and(&context->value, 0);
47 if ((old & 1) == 0) {
48 T_FAIL("[%ld] AND %lx\n", context->count, old);
49 }
50
51 res = pthread_mutex_unlock(&context->mutex);
52 if (res) {
53 T_ASSERT_POSIX_ZERO(res, "[%ld] pthread_mutex_lock", context->count);
54 }
55 } while (__sync_fetch_and_sub(&context->count, 1) > 0);
56
57 T_PASS("thread completed successfully");
58
59 return NULL;
60 }
61
62 T_DECL(mutex, "pthread_mutex",
63 T_META_ALL_VALID_ARCHS(YES))
64 {
65 struct context context = {
66 .mutex = PTHREAD_MUTEX_INITIALIZER,
67 .value = 0,
68 .count = 1000000,
69 };
70 int i;
71 int res;
72 int threads = 8;
73 pthread_t p[threads];
74 for (i = 0; i < threads; ++i) {
75 res = pthread_create(&p[i], NULL, test_thread, &context);
76 T_ASSERT_POSIX_ZERO(res, "pthread_create()");
77 }
78 for (i = 0; i < threads; ++i) {
79 res = pthread_join(p[i], NULL);
80 T_ASSERT_POSIX_ZERO(res, "pthread_join()");
81 }
82 }