]> git.saurik.com Git - apple/libpthread.git/blob - tests/rwlock.c
libpthread-218.1.3.tar.gz
[apple/libpthread.git] / tests / rwlock.c
1 #include <assert.h>
2 #include <pthread.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <stdbool.h>
8 #include <errno.h>
9
10 struct context {
11 pthread_rwlock_t rwlock;
12 long value;
13 long count;
14 };
15
16 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 bool exclusive = i & 2;
27 switch (i++ & 3) {
28 case 0:
29 str = "pthread_rwlock_rdlock";
30 res = pthread_rwlock_rdlock(&context->rwlock);
31 break;
32 case 1:
33 str = "pthread_rwlock_tryrdlock";
34 res = pthread_rwlock_tryrdlock(&context->rwlock);
35 break;
36 case 2:
37 str = "pthread_rwlock_wrlock";
38 res = pthread_rwlock_wrlock(&context->rwlock);
39 break;
40 case 3:
41 str = "pthread_rwlock_trywrlock";
42 res = pthread_rwlock_trywrlock(&context->rwlock);
43 break;
44 }
45 if (res != 0) {
46 if (try && res == EBUSY) {
47 continue;
48 }
49 fprintf(stderr, "[%ld] %s: %s\n", context->count, str, strerror(res));
50 abort();
51 }
52
53 if (exclusive) {
54 old = __sync_fetch_and_or(&context->value, 1);
55 if ((old & 1) != 0) {
56 fprintf(stderr, "[%ld] OR %lx\n", context->count, old);
57 abort();
58 }
59 }
60
61 old = __sync_fetch_and_and(&context->value, 0);
62 if ((old & 1) != (exclusive ? 1 : 0)) {
63 fprintf(stderr, "[%ld] AND %lx\n", context->count, old);
64 abort();
65 }
66
67 res = pthread_rwlock_unlock(&context->rwlock);
68 if (res) {
69 fprintf(stderr, "[%ld] pthread_rwlock_unlock: %s\n", context->count, strerror(res));
70 abort();
71 }
72 } while (__sync_fetch_and_sub(&context->count, 1) > 0);
73
74 return NULL;
75 }
76
77 int main(int argc, char *argv[])
78 {
79 struct context context = {
80 .rwlock = PTHREAD_RWLOCK_INITIALIZER,
81 .value = 0,
82 .count = 5000000,
83 };
84 int i;
85 int res;
86 int threads = 16;
87 pthread_t p[threads];
88 for (i = 0; i < threads; ++i) {
89 res = pthread_create(&p[i], NULL, test_thread, &context);
90 assert(res == 0);
91 }
92 for (i = 0; i < threads; ++i) {
93 res = pthread_join(p[i], NULL);
94 assert(res == 0);
95 }
96
97 return 0;
98 }