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