Skip to content

Commit fdc2ea7

Browse files
authored
Cleanup some pthread tests. NFC (#21293)
1 parent 7080012 commit fdc2ea7

11 files changed

+435
-476
lines changed
+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
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 <memory.h>
9+
#include <pthread.h>
10+
#include <emscripten.h>
11+
#include <emscripten/threading.h>
12+
#include <emscripten/console.h>
13+
#include <assert.h>
14+
15+
#define NUM_THREADS 8
16+
#define DATA_COUNT 10
17+
18+
volatile double globalDouble = 0.0;
19+
volatile uint64_t globalU64 = 0;
20+
21+
uint64_t sharedData[DATA_COUNT] = {};
22+
23+
struct Test {
24+
int op;
25+
int threadId;
26+
};
27+
28+
uint64_t threadCasAccumulatedWrittenData[NUM_THREADS] = {};
29+
uint64_t threadCasAccumulatedReadData[NUM_THREADS] = {};
30+
31+
int64_t rand_60() {
32+
return (int64_t)(emscripten_random() * (float)0x3FFFFFFF) | ((int64_t)(emscripten_random() * (float)0x3FFFFFFF) << 30);
33+
}
34+
35+
void *ThreadMain(void *arg) {
36+
assert(pthread_self() != 0);
37+
assert(globalDouble == 5.0);
38+
assert(globalU64 == 5);
39+
struct Test *t = (struct Test*)arg;
40+
emscripten_outf("Thread %d for test %d: starting computation", t->threadId, t->op);
41+
42+
for (int i = 0; i < 99999; ++i) {
43+
for (int j = 0; j < DATA_COUNT; ++j) {
44+
switch (t->op) {
45+
case 0: emscripten_atomic_add_u64(&sharedData[j], 1); break;
46+
case 1: emscripten_atomic_sub_u64(&sharedData[j], 1); break;
47+
case 2: emscripten_atomic_and_u64(&sharedData[j], ~(1UL << t->threadId)); break;
48+
case 3: emscripten_atomic_or_u64(&sharedData[j], 1UL << t->threadId); break;
49+
case 4: emscripten_atomic_xor_u64(&sharedData[j], 1UL << t->threadId); break;
50+
case 5: {
51+
// Atomically load and store data, and test that each individual u8 is the same.
52+
uint64_t data = emscripten_atomic_load_u64(&sharedData[j]);
53+
uint8_t dataU8[8];
54+
memcpy(dataU8, &data, 8);
55+
assert(dataU8[0] >= 10 && dataU8[0] < 10+NUM_THREADS);
56+
assert(dataU8[0] == dataU8[1] && dataU8[0] == dataU8[2] && dataU8[0] == dataU8[3]);
57+
assert(dataU8[0] == dataU8[4] && dataU8[0] == dataU8[5] && dataU8[0] == dataU8[6] && dataU8[0] == dataU8[7]);
58+
dataU8[0] = dataU8[1] = dataU8[2] = dataU8[3] = dataU8[4] = dataU8[5] = dataU8[6] = dataU8[7] = 10 + t->threadId;
59+
memcpy(&data, dataU8, 8);
60+
emscripten_atomic_store_u64(&sharedData[j], data);
61+
}
62+
break;
63+
case 6: {
64+
uint64_t newData = rand_60();
65+
uint64_t data;
66+
uint64_t prevData;
67+
do {
68+
data = emscripten_atomic_load_u64(&sharedData[j]);
69+
prevData = emscripten_atomic_cas_u64(&sharedData[j], data, newData);
70+
} while(prevData != data);
71+
threadCasAccumulatedReadData[t->threadId] += data;
72+
threadCasAccumulatedWrittenData[t->threadId] += newData;
73+
}
74+
break;
75+
}
76+
}
77+
}
78+
emscripten_outf("Thread %d for test %d: finished, exit()ing", t->threadId, t->op);
79+
pthread_exit(0);
80+
}
81+
82+
struct Test t[NUM_THREADS] = {};
83+
pthread_t thread[NUM_THREADS];
84+
85+
void RunTest(int test) {
86+
pthread_attr_t attr;
87+
pthread_attr_init(&attr);
88+
pthread_attr_setstacksize(&attr, 4*1024);
89+
90+
emscripten_outf("Main thread has thread ID %p\n", pthread_self());
91+
assert(pthread_self() != 0);
92+
93+
switch(test) {
94+
case 2: memset(sharedData, 0xFF, sizeof(sharedData)); break;
95+
case 5: memset(sharedData, 0x10, sizeof(sharedData)); break;
96+
default: memset(sharedData, 0, sizeof(sharedData)); break;
97+
}
98+
99+
emscripten_outf("Main: Starting test %d", test);
100+
101+
for (int i = 0; i < NUM_THREADS; ++i) {
102+
t[i].op = test;
103+
t[i].threadId = i;
104+
int rc = pthread_create(&thread[i], &attr, ThreadMain, &t[i]);
105+
assert(rc == 0);
106+
}
107+
108+
pthread_attr_destroy(&attr);
109+
110+
for (int i = 0; i < NUM_THREADS; ++i) {
111+
int status = 1;
112+
int rc = pthread_join(thread[i], (void**)&status);
113+
assert(rc == 0);
114+
assert(status == 0);
115+
}
116+
117+
int val = sharedData[0];
118+
emscripten_outf("Main: Test %d finished. Result: %d", test, val);
119+
if (test != 6) {
120+
for (int i = 1; i < DATA_COUNT; ++i) {
121+
assert(sharedData[i] == sharedData[0]);
122+
}
123+
}
124+
}
125+
126+
int main() {
127+
globalDouble = 5.0;
128+
globalU64 = 4;
129+
130+
uint64_t prevU64 = emscripten_atomic_add_u64((void*)&globalU64, 1);
131+
assert(prevU64 == 4);
132+
133+
for (int i = 0; i < 7; ++i) {
134+
RunTest(i);
135+
}
136+
137+
uint64_t totalRead = 0;
138+
uint64_t totalWritten = 0;
139+
for (int i = 0; i < NUM_THREADS; ++i) {
140+
totalRead += threadCasAccumulatedReadData[i];
141+
totalWritten += threadCasAccumulatedWrittenData[i];
142+
}
143+
for (int i = 0; i < DATA_COUNT; ++i) {
144+
totalRead += sharedData[i];
145+
}
146+
147+
if (totalRead == totalWritten) {
148+
emscripten_outf("totalRead: %llu, totalWritten: %llu\n", totalRead, totalWritten);
149+
} else {
150+
emscripten_outf("64-bit CAS test failed! totalRead != totalWritten (%llu != %llu)\n", totalRead, totalWritten);
151+
}
152+
assert(totalRead == totalWritten);
153+
emscripten_outf("Main: Test successfully finished");
154+
return 0;
155+
}

test/pthread/test_pthread_64bit_atomics.cpp

-162
This file was deleted.

test/pthread/test_pthread_malloc.cpp renamed to test/pthread/test_pthread_malloc.c

+8-12
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,16 @@
1212
#define NUM_THREADS 8
1313
#define N 6
1414

15-
static void *thread_start(void *arg)
16-
{
15+
static void *thread_start(void *arg) {
1716
long n = (long)arg;
1817
long *mem[N] = {};
19-
for(long i = 0; i < N; ++i)
20-
{
18+
for (long i = 0; i < N; ++i) {
2119
mem[i] = (long*)malloc(4);
2220
*mem[i] = n+i;
2321
}
24-
for(long i = 0; i < N; ++i)
25-
{
22+
for (long i = 0; i < N; ++i) {
2623
long k = *mem[i];
27-
if (k != n+i)
28-
{
24+
if (k != n+i) {
2925
emscripten_errf("Memory corrupted! mem[i]: %ld, i: %ld, n: %ld", k, i, n);
3026
pthread_exit((void*)1);
3127
}
@@ -37,13 +33,13 @@ static void *thread_start(void *arg)
3733
pthread_exit(0);
3834
}
3935

40-
int main()
41-
{
36+
int main() {
4237
pthread_t thr[NUM_THREADS];
43-
for(intptr_t i = 0; i < NUM_THREADS; ++i)
38+
for (intptr_t i = 0; i < NUM_THREADS; ++i) {
4439
pthread_create(&thr[i], NULL, thread_start, (void*)(i*N));
40+
}
4541
int result = 0;
46-
for(int i = 0; i < NUM_THREADS; ++i) {
42+
for (int i = 0; i < NUM_THREADS; ++i) {
4743
int res = 0;
4844
pthread_join(thr[i], (void**)&res);
4945
result += res;

0 commit comments

Comments
 (0)