| 41 | } |
| 42 | |
| 43 | void *ThreadMain(void *arg) |
| 44 | { |
| 45 | // Do some stdio to test proxying to the main thread. |
| 46 | emscripten_outf("pthread %p starting\n", arg); |
| 47 | |
| 48 | assert(pthread_self() != 0); |
| 49 | assert(globalUchar == 5); |
| 50 | assert(globalUshort == 5); |
| 51 | assert(globalUint == 5); |
| 52 | assert(globalFloat == 5.0f); |
| 53 | assert(globalDouble == 5.0); |
| 54 | struct Test *t = (struct Test*)arg; |
| 55 | emscripten_outf("Thread %d for test %d: starting computation", t->threadId, t->op); |
| 56 | |
| 57 | for(int i = 0; i < 99999; ++i) |
| 58 | for(int j = 0; j < N; ++j) |
| 59 | { |
| 60 | switch(t->op) |
| 61 | { |
| 62 | case 0: emscripten_atomic_add_u32(&sharedData[j], 1); break; |
| 63 | case 1: emscripten_atomic_sub_u32(&sharedData[j], 1); break; |
| 64 | case 2: emscripten_atomic_and_u32(&sharedData[j], ~(1UL << t->threadId)); break; |
| 65 | case 3: emscripten_atomic_or_u32(&sharedData[j], 1UL << t->threadId); break; |
| 66 | case 4: emscripten_atomic_xor_u32(&sharedData[j], 1UL << t->threadId); break; |
| 67 | case 5: |
| 68 | { |
| 69 | // Atomically load and store data, and test that each individual u8 is the same. |
| 70 | int data = emscripten_atomic_load_u32(&sharedData[j]); |
| 71 | uint8_t dataU8[4]; |
| 72 | memcpy(dataU8, &data, 4); |
| 73 | assert(dataU8[0] >= 10 && dataU8[0] < 10+NUM_THREADS); |
| 74 | assert(dataU8[0] == dataU8[1] && dataU8[0] == dataU8[2] && dataU8[0] == dataU8[3]); |
| 75 | dataU8[0] = dataU8[1] = dataU8[2] = dataU8[3] = 10 + t->threadId; |
| 76 | memcpy(&data, dataU8, 4); |
| 77 | emscripten_atomic_store_u32(&sharedData[j], data); |
| 78 | } |
| 79 | break; |
| 80 | case 6: |
| 81 | { |
| 82 | int newData = rand_32(); |
| 83 | int data; |
| 84 | int prevData; |
| 85 | do { |
| 86 | data = emscripten_atomic_load_u32(&sharedData[j]); |
| 87 | prevData = emscripten_atomic_cas_u32(&sharedData[j], data, newData); |
| 88 | } while(prevData != data); |
| 89 | threadCasAccumulatedReadData[t->threadId] += data; |
| 90 | threadCasAccumulatedWrittenData[t->threadId] += newData; |
| 91 | } |
| 92 | break; |
| 93 | } |
| 94 | } |
| 95 | emscripten_outf("Thread %d for test %d: finished, exit()ing", t->threadId, t->op); |
| 96 | pthread_exit(0); |
| 97 | } |
| 98 | |
| 99 | struct Test t[NUM_THREADS] = {}; |
| 100 | pthread_t thread[NUM_THREADS]; |
nothing calls this directly
no test coverage detected