1 // Copyright 2015 The Emscripten Authors. All rights reserved.
2 // Emscripten is available under two separate licenses, the MIT license and the
3 // University of Illinois/NCSA Open Source License. Both these licenses can be
4 // found in the LICENSE file.
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <pthread.h>
9 #include <emscripten.h>
10 #include <emscripten/threading.h>
11 #include <errno.h>
12 #include <assert.h>
13 #include <inttypes.h>
14
15 #define NUM_THREADS 8
16 #define NUM_KEYS 16
17 #define NUM_ITERS 100
18
19 pthread_key_t keys[NUM_KEYS];
ThreadMain(void * arg)20 void *ThreadMain(void *arg)
21 {
22 uintptr_t local_keys[NUM_KEYS];
23 for(int iter = 0; iter < NUM_ITERS; ++iter)
24 {
25 for(int i = 0; i < NUM_KEYS; ++i)
26 {
27 local_keys[i] = (uintptr_t)pthread_getspecific(keys[i]);
28 // EM_ASM(err('Thread ' + $0 + ': Read value ' + $1 + ' from TLS for key at index ' + $2), pthread_self(), (int)local_keys[i], i);
29 }
30
31 for(int i = 0; i < NUM_KEYS; ++i)
32 ++local_keys[i];
33
34 for(int i = 0; i < NUM_KEYS; ++i)
35 pthread_setspecific(keys[i], (void*)local_keys[i]);
36 }
37
38 for(int i = 0; i < NUM_KEYS; ++i)
39 {
40 local_keys[i] = (uintptr_t)pthread_getspecific(keys[i]);
41 // EM_ASM(err('Thread ' + $0 + ' final verify: Read value ' + $1 + ' from TLS for key at index ' + $2), pthread_self(), (int)local_keys[i], i);
42 if (local_keys[i] != NUM_ITERS)
43 pthread_exit((void*)1);
44 }
45 pthread_exit(0);
46 }
47
48 pthread_t thread[NUM_THREADS];
49
50 int numThreadsToCreate = 32;
51
CreateThread(int i)52 void CreateThread(int i)
53 {
54 pthread_attr_t attr;
55 pthread_attr_init(&attr);
56 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
57 int rc = pthread_create(&thread[i], &attr, ThreadMain, (void*)i);
58 if (emscripten_has_threading_support()) assert(rc == 0);
59 else assert(rc == EAGAIN);
60 pthread_attr_destroy(&attr);
61 }
62
main()63 int main()
64 {
65 for(int i = 0; i < NUM_KEYS; ++i)
66 pthread_key_create(&keys[i], NULL);
67
68 // Create initial threads.
69 for(int i = 0; i < NUM_THREADS; ++i)
70 CreateThread(i);
71
72 // Join all threads and create more.
73 if (emscripten_has_threading_support())
74 {
75 for(int i = 0; i < NUM_THREADS; ++i)
76 {
77 if (thread[i])
78 {
79 int status;
80 int rc = pthread_join(thread[i], (void**)&status);
81 assert(rc == 0);
82 EM_ASM(err('Main: Joined thread idx ' + $0 + ' with status ' + $1), i, (int)status);
83 assert(status == 0);
84 thread[i] = 0;
85 if (numThreadsToCreate > 0)
86 {
87 --numThreadsToCreate;
88 CreateThread(i);
89 }
90 }
91 }
92 }
93 #ifdef REPORT_RESULT
94 REPORT_RESULT(0);
95 #endif
96
97 for(int i = 0; i < NUM_KEYS; ++i)
98 pthread_key_delete(keys[i]);
99 }
100