]> git.saurik.com Git - apple/libpthread.git/blob - tests/cond_stress.c
libpthread-454.100.8.tar.gz
[apple/libpthread.git] / tests / cond_stress.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <pthread.h>
4 #include <string.h>
5
6 typedef struct _ConditionLock {
7 pthread_mutex_t _mutex;
8 pthread_cond_t _condition;
9 int _owner;
10 int _last_owner;
11 volatile int _state;
12 } ConditionLock;
13
14 typedef struct _log {
15 int thread;
16 const char * op;
17 } log_t;
18
19 static int initConditionLockWithCondition(ConditionLock *, int);
20 static int lockConditionLock(ConditionLock *, int);
21 static int lockConditionLockWhenCondition(ConditionLock *, int, int);
22 static int unlockConditionLockWithCondition(ConditionLock *, int, int);
23 static int destroyConditionLock(ConditionLock *);
24 static void * testThread(void *);
25 static void log(int, const char *, ConditionLock *);
26
27 static ConditionLock * lock;
28 static volatile int count = 0;
29 static volatile int logcount = 0;
30 static log_t * tracelog;
31 #define TRACE_MAX_COUNT (4 * 1024 * 1024)
32 long iterations = 999000L;
33
34 static void
35 log(int self, const char * op, ConditionLock * cl)
36 {
37 tracelog[logcount].thread = self;
38 tracelog[logcount++].op = op;
39 if (logcount == TRACE_MAX_COUNT)
40 logcount = 0;
41 }
42
43 int
44 main(int argc, char * argv[])
45 {
46 pthread_t thread[4];
47
48 lock = (ConditionLock *)calloc(sizeof(ConditionLock), 1);
49 if (initConditionLockWithCondition(lock, 0))
50 abort();
51 tracelog = (log_t *)calloc(sizeof(log_t), TRACE_MAX_COUNT);
52
53 pthread_create(&thread[0], NULL, testThread, (void *)1);
54 pthread_create(&thread[1], NULL, testThread, (void *)2);
55 pthread_create(&thread[2], NULL, testThread, (void *)3);
56 pthread_create(&thread[3], NULL, testThread, (void *)4);
57
58 while (iterations > -100) {
59 if (lockConditionLock(lock, 0))
60 abort();
61 count = 1;
62 iterations--;
63 if (unlockConditionLockWithCondition(lock, 1, 0))
64 abort();
65 }
66
67 destroyConditionLock(lock);
68 free(lock);
69 free(tracelog);
70
71 return 0;
72 }
73
74 static void *
75 testThread(void * arg)
76 {
77 int self = (int)arg;
78 while (iterations > 0) {
79 if (lockConditionLockWhenCondition(lock, 1, self))
80 abort();
81 count = 0;
82 if (unlockConditionLockWithCondition(lock, 0, self))
83 abort();
84 }
85 return arg;
86 }
87
88 static int
89 initConditionLockWithCondition(ConditionLock * cl, int condition)
90 {
91 int rc;
92
93 if ((rc = pthread_mutex_init(&cl->_mutex, NULL))) {
94 fprintf(stderr, "pthread_mutex_init returned %d, %s\n", rc, strerror(rc));
95 return 1;
96 }
97
98 if ((rc = pthread_cond_init(&cl->_condition, NULL))) {
99 fprintf(stderr, "pthread_cond_init returned %d, %s\n", rc, strerror(rc));
100 return 1;
101 }
102
103 cl->_state = condition;
104
105 return 0;
106 }
107
108 static int
109 destroyConditionLock(ConditionLock * cl)
110 {
111 int rc;
112
113 if ((rc = pthread_mutex_destroy(&cl->_mutex))) {
114 fprintf(stderr, "pthread_mutex_destroy returned %d, %s\n", rc, strerror(rc));
115 return 1;
116 }
117 if ((rc = pthread_cond_destroy(&cl->_condition))) {
118 fprintf(stderr, "pthread_cond_destroy returned %d, %s\n", rc, strerror(rc));
119 return 1;
120 }
121 return 0;
122 }
123
124 static int
125 lockConditionLock(ConditionLock * cl, int self)
126 {
127 int rc;
128
129 if ((rc = pthread_mutex_lock(&cl->_mutex))) {
130 fprintf(stderr, "pthread_mutex_lock() returned %d, %s\n", rc, strerror(rc));
131 return 1;
132 }
133 cl->_owner = self;
134 log(self, "Got lock", cl);
135 return 0;
136 }
137
138 static int
139 lockConditionLockWhenCondition(ConditionLock * cl, int condition, int self)
140 {
141 int rc;
142
143 if ((rc = pthread_mutex_lock(&cl->_mutex))) {
144 fprintf(stderr, "pthread_mutex_lock() returned %d, %s\n", rc, strerror(rc));
145 return 1;
146 }
147 log(self, "Waiting for condition", cl);
148 while (cl->_state != condition) {
149 if ((rc = pthread_cond_wait(&cl->_condition, &cl->_mutex))) {
150 fprintf(stderr, "pthread_cond_wait() returned %d, %s\n", rc, strerror(rc));
151 return 1;
152 }
153 if (cl->_state != condition) {
154 log(self, "condition lock wakeup with wrong condition", cl);
155 }
156 }
157 cl->_owner = self;
158 log(self, "Got condition", cl);
159 return 0;
160 }
161
162 static int
163 unlockConditionLockWithCondition(ConditionLock * cl, int condition, int self)
164 {
165 int rc;
166
167 if (cl->_owner != self) {
168 fprintf(stderr, "%d: trying to unlock a lock owned by %d\n", self, cl->_owner);
169 abort();
170 }
171 log(self, condition ? "Unlocking with condition set" : "Unlocking with condition cleared", cl);
172 cl->_last_owner = cl->_owner;
173 cl->_owner = 0;
174 cl->_state = condition;
175 if ((rc = pthread_cond_signal(&cl->_condition))) {
176 fprintf(stderr, "pthread_cond_broadcast() returned %d, %s\n", rc, strerror(rc));
177 return 1;
178 }
179 log(self, "Sent broadcast", cl);
180 if ((rc = pthread_mutex_unlock(&cl->_mutex))) {
181 fprintf(stderr, "pthread_mutex_unlock() returned %d, %s\n", rc, strerror(rc));
182 return 1;
183 }
184 return 0;
185 }
186