2 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
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
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
37 #include <semaphore.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;
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) \
73 pthread_mutex_t mutex
;
77 typedef void* (*ThreadFunction
)(void *state
);
79 void* FastThread(void *userdata
) {
80 // do nothing and immediately exit
84 /* creates and waits via pthread_join() for thread to exit */
85 void CreateWithJoin(ThreadFunction func
, void *state
) {
88 int p
= pthread_create(&thread_id
, NULL
, func
, state
);
91 /* wait for thread to exit */
92 p
= pthread_join(thread_id
, &thread_ret
);
97 /* creates, but does not wait for thread to exit */
98 void CreateWithoutJoin() {
100 int p
= pthread_create(&thread_id
, NULL
, FastThread
, NULL
);
102 /* intentionally no pthread_join() */
106 /* creates as detached thread, cannot join */
107 void CreateDetached() {
110 pthread_attr_init(&attr
);
111 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
112 int p
= pthread_create(&thread_id
, &attr
, FastThread
, NULL
);
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
);
122 pthread_cond_signal(&sync_data
->cv
);
123 pthread_mutex_unlock(&sync_data
->mutex
);
127 void TestTlsAndSync() {
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
);
142 EXPECT_EQ(5, tls_var
);
143 pthread_mutex_lock(&sync_data
.mutex
);
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
);
157 void TestManyThreadsJoinable() {
160 for (i
= 0; i
< kTestLoops
; i
++) {
161 CreateWithJoin(FastThread
, NULL
);
168 /* this test actually consumes all thread ids - no other threads will succeed */
170 for (i
= 0; i
< NC_MAX_THREADS
-1; i
++) {
171 /* without join we are limited by the max number of threads */
176 void TestManyThreadsDetached() {
179 for (i
= 0; i
< kTestLoops
; i
++) {
185 void* SemaphoresThread(void *state
)
187 sem_t
* sem
= (sem_t
*) state
;
189 for (i
= 0; i
< kTestLoops
; i
++) {
190 rv
= sem_wait(&sem
[0]);
192 rv
= sem_post(&sem
[1]);
195 EXPECT_EQ(kTestLoops
, i
);
199 void TestSemaphores() {
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
);
215 for (i
= 0; i
< kTestLoops
; i
++) {
216 rv
= sem_post(&sem
[0]);
218 rv
= sem_wait(&sem
[1]);
221 sem_destroy(&sem
[0]);
222 sem_destroy(&sem
[1]);
226 pthread_once_t once_control
= PTHREAD_ONCE_INIT
;
228 void pthread_once_routine() {
229 static AtomicWord count
= 0;
231 res
= AtomicIncrement(&count
, 1);
235 void* OnceThread(void *userdata
) {
236 pthread_once(&once_control
, pthread_once_routine
);
241 void TestPthreadOnce() {
244 for (i
= 0; i
< kTestLoops
; i
++) {
247 pthread_attr_init(&attr
);
248 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
249 int p
= pthread_create(&thread_id
, &attr
, OnceThread
, NULL
);
255 void* RecursiveLockThread(void *state
) {
258 pthread_mutex_t
*lock
= state
;
260 for (i
= 0; i
< kTestLoops
; ++i
) {
261 rv
= pthread_mutex_lock(lock
);
265 for (i
= 0; i
< kTestLoops
; ++i
) {
266 rv
= pthread_mutex_unlock(lock
);
272 void TestRecursiveMutex() {
274 pthread_mutexattr_t attr
;
275 pthread_mutex_t mutex
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
;
278 pthread_t tid
[kSmallNumberOfThreads
];
280 for (i
= 0; i
< kSmallNumberOfThreads
; ++i
) {
281 int rv
= pthread_create(&tid
[i
], NULL
, RecursiveLockThread
, &mutex
);
285 for (i
= 0; i
< kSmallNumberOfThreads
; ++i
) {
286 pthread_join(tid
[i
], NULL
);
289 rv
= pthread_mutex_lock(&mutex
);
291 rv
= pthread_mutex_trylock(&mutex
);
293 rv
= pthread_mutex_unlock(&mutex
);
295 rv
= pthread_mutex_unlock(&mutex
);
298 rv
= pthread_mutex_destroy(&mutex
);
300 memset(&mutex
, 0, sizeof(mutex
));
302 rv
= pthread_mutexattr_init(&attr
);
304 rv
= pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_RECURSIVE_NP
);
306 rv
= pthread_mutex_init(&mutex
, &attr
);
309 for (i
= 0; i
< kSmallNumberOfThreads
; ++i
) {
310 int rv
= pthread_create(&tid
[i
], NULL
, RecursiveLockThread
, &mutex
);
314 for (i
= 0; i
< kSmallNumberOfThreads
; ++i
) {
315 pthread_join(tid
[i
], NULL
);
321 void TestErrorCheckingMutex() {
323 pthread_mutexattr_t attr
;
324 pthread_mutex_t mutex
;
326 rv
= pthread_mutexattr_init(&attr
);
328 rv
= pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_ERRORCHECK_NP
);
330 rv
= pthread_mutex_init(&mutex
, &attr
);
332 rv
= pthread_mutex_unlock(&mutex
);
334 rv
= pthread_mutex_lock(&mutex
);
336 rv
= pthread_mutex_trylock(&mutex
);
338 rv
= pthread_mutex_unlock(&mutex
);
340 rv
= pthread_mutex_unlock(&mutex
);
345 void tsd_destructor(void *arg
) {
349 pthread_key_t tsd_key
;
351 void* TsdThread(void *state
) {
353 rv
= pthread_setspecific(tsd_key
, state
);
355 pthread_exit((void*) 5);
361 int rv
= pthread_key_create(&tsd_key
, tsd_destructor
);
363 int destructor_count
= 0;
366 rv
= pthread_setspecific(tsd_key
, &rv
);
369 ptr
= pthread_getspecific(tsd_key
);
372 CreateWithJoin(TsdThread
, &destructor_count
);
373 EXPECT_EQ(1, destructor_count
);
375 rv
= pthread_key_delete(tsd_key
);
381 void* MallocThread(void *userdata
) {
384 for (i
= 0; i
< kTestLoops
; ++i
) {
385 ptr
= (void*) malloc(16);
386 EXPECT_NE(NULL
, ptr
);
392 pthread_t tid
[kSmallNumberOfThreads
];
395 for (i
= 0; i
< kSmallNumberOfThreads
; ++i
) {
396 int rv
= pthread_create(&tid
[i
], NULL
, MallocThread
, NULL
);
400 for (i
= 0; i
< kSmallNumberOfThreads
; ++i
) {
401 pthread_join(tid
[i
], NULL
);
407 void* ReallocThread(void *userdata
) {
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
);
428 pthread_t tid
[kSmallNumberOfThreads
];
431 for (i
= 0; i
<kSmallNumberOfThreads
; ++i
) {
432 int rv
= pthread_create(&tid
[i
], NULL
, ReallocThread
, NULL
);
436 for (i
= 0; i
<kSmallNumberOfThreads
; ++i
) {
437 pthread_join(tid
[i
], NULL
);
443 int main(int argc
, char **argv
) {
445 TestManyThreadsJoinable();
446 TestManyThreadsDetached();
449 TestRecursiveMutex();
450 TestErrorCheckingMutex();