Load 57 into trunk.
[nativeclient.git] / tests / threads / thread_test.c
blobdbab1ab0cccd54e24fc0dd4faf7de575cede597e
1 /*
2 * Copyright 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * Testing suite for NativeClient threads
36 #include <pthread.h>
37 #include <semaphore.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
43 * We cannot have more than just shy of 8192 threads running
44 * simultaneously. This is a NaCl architectural limitation.
46 const int kTestLoops = 10000;
47 const int kSmallNumberOfThreads = 5;
49 __thread int tls_var = 5;
50 int ready = 0;
52 int errors = 0;
54 #define PRINT_ERROR { printf("Error on line %d\n", __LINE__); errors++; }
56 #define EXPECT_EQ(A, B) if ((A)!=(B)) PRINT_ERROR
57 #define EXPECT_NE(A, B) if ((A)==(B)) PRINT_ERROR
58 #define EXPECT_GE(A, B) if ((A)<(B)) PRINT_ERROR
59 #define EXPECT_LE(A, B) if ((A)>(B)) PRINT_ERROR
61 #define PRINT_TEST_OK printf("%s - OK\n", __FUNCTION__)
62 #define PRINT_TEST_FAILED printf("%s - FAILED\n", __FUNCTION__)
64 #define TEST_FUNCTION_START int local_error = errors; \
65 printf("%s - running\n", __FUNCTION__);
67 #define TEST_FUNCTION_END if (local_error == errors) \
68 PRINT_TEST_OK; \
69 else \
70 PRINT_TEST_FAILED;
72 struct SYNC_DATA {
73 pthread_mutex_t mutex;
74 pthread_cond_t cv;
77 typedef void* (*ThreadFunction)(void *state);
79 void* FastThread(void *userdata) {
80 // do nothing and immediately exit
81 return 0;
84 /* creates and waits via pthread_join() for thread to exit */
85 void CreateWithJoin(ThreadFunction func, void *state) {
86 pthread_t thread_id;
87 void *thread_ret;
88 int p = pthread_create(&thread_id, NULL, func, state);
89 EXPECT_EQ(0, p);
91 /* wait for thread to exit */
92 p = pthread_join(thread_id, &thread_ret);
93 EXPECT_EQ(0, p);
97 /* creates, but does not wait for thread to exit */
98 void CreateWithoutJoin() {
99 pthread_t thread_id;
100 int p = pthread_create(&thread_id, NULL, FastThread, NULL);
101 EXPECT_EQ(0, p);
102 /* intentionally no pthread_join() */
106 /* creates as detached thread, cannot join */
107 void CreateDetached() {
108 pthread_t thread_id;
109 pthread_attr_t attr;
110 pthread_attr_init(&attr);
111 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
112 int p = pthread_create(&thread_id, &attr, FastThread, NULL);
113 EXPECT_EQ(0, p);
114 /* cannot join on detached thread */
117 void* TlsThread(void* state) {
118 struct SYNC_DATA *sync_data = (struct SYNC_DATA *)state;
119 pthread_mutex_lock(&sync_data->mutex);
120 tls_var = 8;
121 ready = 1;
122 pthread_cond_signal(&sync_data->cv);
123 pthread_mutex_unlock(&sync_data->mutex);
124 return (void*)33;
127 void TestTlsAndSync() {
128 int i = 5;
129 void* thread_rv;
130 pthread_t thread_id;
131 pthread_attr_t attr;
132 TEST_FUNCTION_START;
134 struct SYNC_DATA sync_data;
135 pthread_mutex_init(&sync_data.mutex, NULL);
136 pthread_cond_init(&sync_data.cv, NULL);
137 pthread_attr_init(&attr);
138 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
139 i = pthread_create(&thread_id, &attr, TlsThread, &sync_data);
140 EXPECT_EQ(0, i);
142 EXPECT_EQ(5, tls_var);
143 pthread_mutex_lock(&sync_data.mutex);
145 while (!ready) {
146 pthread_cond_wait(&sync_data.cv, &sync_data.mutex);
148 i = pthread_join(thread_id, &thread_rv);
149 EXPECT_NE(0, i); /* join should fail since the thread was created detached */
150 EXPECT_EQ(5, tls_var);
152 pthread_mutex_unlock(&sync_data.mutex);
153 EXPECT_EQ(5, tls_var);
154 TEST_FUNCTION_END;
157 void TestManyThreadsJoinable() {
158 TEST_FUNCTION_START;
159 int i;
160 for (i = 0; i < kTestLoops; i++) {
161 CreateWithJoin(FastThread, NULL);
163 TEST_FUNCTION_END;
168 /* this test actually consumes all thread ids - no other threads will succeed */
169 #if 0
170 for (i = 0; i < NC_MAX_THREADS-1; i++) {
171 /* without join we are limited by the max number of threads */
172 CreateWithoutJoin();
174 #endif
176 void TestManyThreadsDetached() {
177 TEST_FUNCTION_START;
178 int i;
179 for (i = 0; i < kTestLoops; i++) {
180 CreateDetached();
182 TEST_FUNCTION_END;
185 void* SemaphoresThread(void *state)
187 sem_t* sem = (sem_t*) state;
188 int i = 0, rv;
189 for (i = 0; i < kTestLoops; i++) {
190 rv = sem_wait(&sem[0]);
191 EXPECT_EQ(0, rv);
192 rv = sem_post(&sem[1]);
193 EXPECT_EQ(0, rv);
195 EXPECT_EQ(kTestLoops, i);
196 return 0;
199 void TestSemaphores() {
200 TEST_FUNCTION_START;
201 int i = 5, rv;
202 pthread_t thread_id;
203 pthread_attr_t attr;
205 sem_t sem[2];
206 sem_init(&sem[0], 0, 0);
207 sem_init(&sem[1], 0, 0);
209 pthread_attr_init(&attr);
210 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
212 i = pthread_create(&thread_id, &attr, SemaphoresThread, sem);
213 EXPECT_EQ(0, i);
215 for (i = 0; i < kTestLoops; i++) {
216 rv = sem_post(&sem[0]);
217 EXPECT_EQ(0, rv);
218 rv = sem_wait(&sem[1]);
219 EXPECT_EQ(0, rv);
221 sem_destroy(&sem[0]);
222 sem_destroy(&sem[1]);
223 TEST_FUNCTION_END;
226 pthread_once_t once_control = PTHREAD_ONCE_INIT;
228 void pthread_once_routine() {
229 static AtomicWord count = 0;
230 AtomicWord res;
231 res = AtomicIncrement(&count, 1);
232 EXPECT_LE(res, 1);
235 void* OnceThread(void *userdata) {
236 pthread_once(&once_control, pthread_once_routine);
237 return 0;
241 void TestPthreadOnce() {
242 TEST_FUNCTION_START;
243 int i;
244 for (i = 0; i < kTestLoops; i++) {
245 pthread_t thread_id;
246 pthread_attr_t attr;
247 pthread_attr_init(&attr);
248 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
249 int p = pthread_create(&thread_id, &attr, OnceThread, NULL);
250 EXPECT_EQ(0, p);
252 TEST_FUNCTION_END;
255 void* RecursiveLockThread(void *state) {
256 int rv;
257 int i;
258 pthread_mutex_t *lock = state;
260 for (i = 0; i < kTestLoops; ++i) {
261 rv = pthread_mutex_lock(lock);
262 EXPECT_EQ(0, rv);
265 for (i = 0; i < kTestLoops; ++i) {
266 rv = pthread_mutex_unlock(lock);
267 EXPECT_EQ(0, rv);
269 return 0;
272 void TestRecursiveMutex() {
273 TEST_FUNCTION_START;
274 pthread_mutexattr_t attr;
275 pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
276 int rv;
278 pthread_t tid[kSmallNumberOfThreads];
279 int i = 0;
280 for (i = 0; i < kSmallNumberOfThreads; ++i) {
281 int rv = pthread_create(&tid[i], NULL, RecursiveLockThread, &mutex);
282 EXPECT_EQ(0, rv);
285 for (i = 0; i < kSmallNumberOfThreads; ++i) {
286 pthread_join(tid[i], NULL);
289 rv = pthread_mutex_lock(&mutex);
290 EXPECT_EQ(0, rv);
291 rv = pthread_mutex_trylock(&mutex);
292 EXPECT_EQ(0, rv);
293 rv = pthread_mutex_unlock(&mutex);
294 EXPECT_EQ(0, rv);
295 rv = pthread_mutex_unlock(&mutex);
296 EXPECT_EQ(0, rv);
298 rv = pthread_mutex_destroy(&mutex);
299 EXPECT_EQ(0, rv);
300 memset(&mutex, 0, sizeof(mutex));
302 rv = pthread_mutexattr_init(&attr);
303 EXPECT_EQ(0, rv);
304 rv = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
305 EXPECT_EQ(0, rv);
306 rv = pthread_mutex_init(&mutex, &attr);
307 EXPECT_EQ(0, rv);
309 for (i = 0; i < kSmallNumberOfThreads; ++i) {
310 int rv = pthread_create(&tid[i], NULL, RecursiveLockThread, &mutex);
311 EXPECT_EQ(0, rv);
314 for (i = 0; i < kSmallNumberOfThreads; ++i) {
315 pthread_join(tid[i], NULL);
318 TEST_FUNCTION_END;
321 void TestErrorCheckingMutex() {
322 TEST_FUNCTION_START;
323 pthread_mutexattr_t attr;
324 pthread_mutex_t mutex;
325 int rv;
326 rv = pthread_mutexattr_init(&attr);
327 EXPECT_EQ(0, rv);
328 rv = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
329 EXPECT_EQ(0, rv);
330 rv = pthread_mutex_init(&mutex, &attr);
331 EXPECT_EQ(0, rv);
332 rv = pthread_mutex_unlock(&mutex);
333 EXPECT_NE(0, rv);
334 rv = pthread_mutex_lock(&mutex);
335 EXPECT_EQ(0, rv);
336 rv = pthread_mutex_trylock(&mutex);
337 EXPECT_NE(0, rv);
338 rv = pthread_mutex_unlock(&mutex);
339 EXPECT_EQ(0, rv);
340 rv = pthread_mutex_unlock(&mutex);
341 EXPECT_NE(0, rv);
342 TEST_FUNCTION_END;
345 void tsd_destructor(void *arg) {
346 *(int*)arg += 1;
349 pthread_key_t tsd_key;
351 void* TsdThread(void *state) {
352 int rv;
353 rv = pthread_setspecific(tsd_key, state);
354 EXPECT_EQ(0, rv);
355 pthread_exit((void*) 5);
356 return 0;
359 void TestTSD() {
360 TEST_FUNCTION_START;
361 int rv = pthread_key_create(&tsd_key, tsd_destructor);
362 void* ptr;
363 int destructor_count = 0;
364 EXPECT_EQ(0, rv);
366 rv = pthread_setspecific(tsd_key, &rv);
367 EXPECT_EQ(0, rv);
369 ptr = pthread_getspecific(tsd_key);
370 EXPECT_EQ(ptr, &rv);
372 CreateWithJoin(TsdThread, &destructor_count);
373 EXPECT_EQ(1, destructor_count);
375 rv = pthread_key_delete(tsd_key);
376 EXPECT_EQ(0, rv);
378 TEST_FUNCTION_END;
381 void* MallocThread(void *userdata) {
382 void* ptr;
383 int i;
384 for (i = 0; i < kTestLoops; ++i) {
385 ptr = (void*) malloc(16);
386 EXPECT_NE(NULL, ptr);
388 return ptr;
391 void TestMalloc() {
392 pthread_t tid[kSmallNumberOfThreads];
393 TEST_FUNCTION_START;
394 int i = 0;
395 for (i = 0; i < kSmallNumberOfThreads; ++i) {
396 int rv = pthread_create(&tid[i], NULL, MallocThread, NULL);
397 EXPECT_EQ(0, rv);
400 for (i = 0; i < kSmallNumberOfThreads; ++i) {
401 pthread_join(tid[i], NULL);
404 TEST_FUNCTION_END;
407 void* ReallocThread(void *userdata) {
408 void* ptr;
409 int i;
410 ptr = (void*) malloc(16);
411 for (i = 0; i < kTestLoops; ++i) {
412 ptr = (void*)realloc(ptr, 32);
413 EXPECT_NE(NULL, ptr);
414 ptr = (void*)realloc(ptr, 64000);
415 EXPECT_NE(NULL, ptr);
416 ptr = (void*)realloc(ptr, 64);
417 EXPECT_NE(NULL, ptr);
418 ptr = (void*)realloc(ptr, 32000);
419 EXPECT_NE(NULL, ptr);
420 ptr = (void*)realloc(ptr, 256);
421 EXPECT_NE(NULL, ptr);
424 return ptr;
427 void TestRealloc() {
428 pthread_t tid[kSmallNumberOfThreads];
429 TEST_FUNCTION_START;
430 int i = 0;
431 for (i = 0; i <kSmallNumberOfThreads; ++i) {
432 int rv = pthread_create(&tid[i], NULL, ReallocThread, NULL);
433 EXPECT_EQ(0, rv);
436 for (i = 0; i <kSmallNumberOfThreads; ++i) {
437 pthread_join(tid[i], NULL);
440 TEST_FUNCTION_END;
443 int main(int argc, char **argv) {
444 TestTlsAndSync();
445 TestManyThreadsJoinable();
446 TestManyThreadsDetached();
447 TestSemaphores();
448 TestPthreadOnce();
449 TestRecursiveMutex();
450 TestErrorCheckingMutex();
451 TestTSD();
452 TestMalloc();
453 TestRealloc();
454 return errors;