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 <pthread.h>
7 #include <sys/types.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <assert.h>
11 #include <unistd.h>
12 #include <errno.h>
13 #include <signal.h>
14 #include <emscripten.h>
15 #include <emscripten/threading.h>
16 
17 volatile int sharedVar = 0;
18 
thread_start(void * arg)19 static void *thread_start(void *arg)
20 {
21   // As long as this thread is running, keep the shared variable latched to nonzero value.
22   for(;;)
23   {
24     ++sharedVar;
25     emscripten_atomic_store_u32((void*)&sharedVar, sharedVar+1);
26   }
27 
28   pthread_exit(0);
29 }
30 
31 pthread_t thr;
32 
BusySleep(double msecs)33 void BusySleep(double msecs)
34 {
35   double t0 = emscripten_get_now();
36   while(emscripten_get_now() < t0 + msecs);
37 }
38 
main()39 int main()
40 {
41   if (!emscripten_has_threading_support())
42   {
43 #ifdef REPORT_RESULT
44     REPORT_RESULT(0);
45 #endif
46     printf("Skipped: Threading is not supported.\n");
47     return 0;
48   }
49 
50   sharedVar = 0;
51   int s = pthread_create(&thr, NULL, thread_start, 0);
52   assert(s == 0);
53 
54   // Wait until thread kicks in and sets the shared variable.
55   while(sharedVar == 0)
56     BusySleep(10);
57 
58   s = pthread_kill(thr, SIGKILL);
59   assert(s == 0);
60 
61   // Wait until we see the shared variable stop incrementing. (This is a bit heuristic and hacky)
62   for(;;)
63   {
64     int val = emscripten_atomic_load_u32((void*)&sharedVar);
65     BusySleep(100);
66     int val2 = emscripten_atomic_load_u32((void*)&sharedVar);
67     if (val == val2) break;
68   }
69 
70   // Reset to 0.
71   sharedVar = 0;
72   emscripten_atomic_store_u32((void*)&sharedVar, 0);
73 
74   // Wait for a long time, if the thread is still running, it should progress and set sharedVar by this time.
75   BusySleep(3000);
76 
77   // Finally test that the thread is not doing any work and it is dead.
78   assert(sharedVar == 0);
79   assert(emscripten_atomic_load_u32((void*)&sharedVar) == 0);
80   EM_ASM(out('Main: Done. Successfully killed thread. sharedVar: '+$0+'.'), sharedVar);
81 #ifdef REPORT_RESULT
82   REPORT_RESULT(sharedVar);
83 #endif
84 }
85