File: test_pthread_thread_local_storage.cpp

package info (click to toggle)
emscripten 3.1.6~dfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 114,112 kB
  • sloc: ansic: 583,052; cpp: 391,943; javascript: 79,361; python: 54,180; sh: 49,997; pascal: 4,658; makefile: 3,426; asm: 2,191; lisp: 1,869; ruby: 488; cs: 142
file content (121 lines) | stat: -rw-r--r-- 2,957 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2015 The Emscripten Authors.  All rights reserved.
// Emscripten is available under two separate licenses, the MIT license and the
// University of Illinois/NCSA Open Source License.  Both these licenses can be
// found in the LICENSE file.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <emscripten.h>
#include <emscripten/threading.h>
#include <errno.h>
#include <assert.h>
#include <inttypes.h>

#define NUM_THREADS 8
#define NUM_KEYS 16
#define NUM_ITERS 100

pthread_key_t keys[NUM_KEYS];
void *ThreadMain(void *arg)
{
	uintptr_t local_keys[NUM_KEYS];
	for(int iter = 0; iter < NUM_ITERS; ++iter)
	{
		for(int i = 0; i < NUM_KEYS; ++i)
		{
			local_keys[i] = (uintptr_t)pthread_getspecific(keys[i]);
//			EM_ASM(err('Thread ' + $0 + ': Read value ' + $1 + ' from TLS for key at index ' + $2), pthread_self(), (int)local_keys[i], i);
		}

		for(int i = 0; i < NUM_KEYS; ++i)
			++local_keys[i];

		for(int i = 0; i < NUM_KEYS; ++i)
			pthread_setspecific(keys[i], (void*)local_keys[i]);
	}

	for(int i = 0; i < NUM_KEYS; ++i)
	{
		local_keys[i] = (uintptr_t)pthread_getspecific(keys[i]);
//		EM_ASM(err('Thread ' + $0 + ' final verify: Read value ' + $1 + ' from TLS for key at index ' + $2), pthread_self(), (int)local_keys[i], i);
		assert(local_keys[i] == NUM_ITERS);
	}
	return 0;
}

pthread_t thread[NUM_THREADS];

int numThreadsToCreate = 32;
int threadCounter = 0;
_Atomic int destructorCounter = 0;

void CreateThread(long i)
{
	printf("CreateThread %ld\n", i);
	threadCounter++;
	int rc = pthread_create(&thread[i], NULL, ThreadMain, (void*)i);
	if (emscripten_has_threading_support()) assert(rc == 0);
	else assert(rc == EAGAIN);
}

void destructor1(void* val) {
	destructorCounter++;
}

int main()
{
	for(int i = 0; i < NUM_KEYS; ++i) {
		if (i == 0)
			pthread_key_create(&keys[i], destructor1);
		else
			pthread_key_create(&keys[i], NULL);
	}

	// Create initial threads.
	for(long i = 0; i < NUM_THREADS; ++i)
		CreateThread(i);

	// Join all threads and create more.
	if (emscripten_has_threading_support())
	{
		for(long i = 0; i < NUM_THREADS; ++i)
		{
			if (thread[i])
			{
				int status;
				int rc = pthread_join(thread[i], (void**)&status);
				assert(rc == 0);
				printf("Main: Joined thread idx %ld with status %d\n", i, status);
				assert(status == 0);
				thread[i] = 0;
				if (numThreadsToCreate > 0)
				{
					--numThreadsToCreate;
					CreateThread(i);
				}
			}
		}
	}

	for(int i = 0; i < NUM_THREADS; ++i)
	{
			if (thread[i])
			{
				int status = 1;
				int rc = pthread_join(thread[i], (void**)&status);
				assert(rc == 0);
				printf("Main: Joined thread idx %d with status %d\n", i, status);
				assert(status == 0);
			}
	}
	printf("destructorCounter: %d\n", destructorCounter);
	printf("threadCounter: %d\n", threadCounter);
	assert(destructorCounter == threadCounter);

	for(int i = 0; i < NUM_KEYS; ++i)
		pthread_key_delete(keys[i]);

	printf("done\n");
	return 0;
}