@@ -7,34 +7,75 @@ static void dummy1(pthread_t t)
7
7
}
8
8
weak_alias (dummy1 , __tl_sync );
9
9
10
+ #ifdef __EMSCRIPTEN__ // XXX Emscripten add extern for __emscripten_thread_cleanup
11
+ extern void __emscripten_thread_cleanup (pthread_t thread );
12
+ #endif
13
+
10
14
static int __pthread_timedjoin_np (pthread_t t , void * * res , const struct timespec * at )
11
15
{
16
+ #ifdef __EMSCRIPTEN__
17
+ // Attempt to join a thread which does not point to a valid thread, or
18
+ // does not exist anymore.
19
+ if (t -> self != t ) return ESRCH ;
20
+ // Thread is attempting to join to itself. Already detached threads are
21
+ // handled below by returning EINVAL instead.
22
+ // TODO: The detached check here is just to satisfy the `other.test_{proxy,main}_pthread_join_detach` tests.
23
+ if (t -> detach_state != DT_DETACHED && __pthread_self () == t ) return EDEADLK ;
24
+ #endif
12
25
int state , cs , r = 0 ;
13
26
__pthread_testcancel ();
14
27
__pthread_setcancelstate (PTHREAD_CANCEL_DISABLE , & cs );
15
28
if (cs == PTHREAD_CANCEL_ENABLE ) __pthread_setcancelstate (cs , 0 );
16
29
while ((state = t -> detach_state ) && r != ETIMEDOUT && r != EINVAL ) {
30
+ #ifdef __EMSCRIPTEN__
31
+ // The thread is (already) detached and therefore not joinable.
32
+ // This also handle cases where the thread becomes detached
33
+ // *during* the join.
34
+ if (state >= DT_DETACHED ) {
35
+ // Even though the man page says this is undefined
36
+ // behaviour we ave several tests in the posixtest suite
37
+ // that depend on this.
38
+ r = EINVAL ;
39
+ break ;
40
+ }
41
+ #else
17
42
if (state >= DT_DETACHED ) a_crash ();
43
+ #endif
18
44
r = __timedwait_cp (& t -> detach_state , state , CLOCK_REALTIME , at , 1 );
19
45
}
20
46
__pthread_setcancelstate (cs , 0 );
21
47
if (r == ETIMEDOUT || r == EINVAL ) return r ;
22
48
__tl_sync (t );
23
49
if (res ) * res = t -> result ;
50
+ #ifdef __EMSCRIPTEN__
51
+ // Thread was exited during this call, be sure to clean it up.
52
+ if (state == DT_EXITED ) __emscripten_thread_cleanup (t );
53
+ #else // XXX Emscripten map_base unused
24
54
if (t -> map_base ) __munmap (t -> map_base , t -> map_size );
55
+ #endif
25
56
return 0 ;
26
57
}
27
58
28
59
int __pthread_join (pthread_t t , void * * res )
29
60
{
61
+ #ifdef __EMSCRIPTEN__ // XXX Emscripten check whether blocking is allowed.
62
+ emscripten_check_blocking_allowed ();
63
+ #endif
30
64
return __pthread_timedjoin_np (t , res , 0 );
31
65
}
32
66
33
67
static int __pthread_tryjoin_np (pthread_t t , void * * res )
34
68
{
69
+ #ifdef __EMSCRIPTEN__ // XXX Emscripten call __pthread_timedjoin_np directly to avoid additional check
70
+ return t -> detach_state == DT_JOINABLE ? EBUSY : __pthread_timedjoin_np (t , res , 0 );
71
+ #else
35
72
return t -> detach_state == DT_JOINABLE ? EBUSY : __pthread_join (t , res );
73
+ #endif
36
74
}
37
75
38
76
weak_alias (__pthread_tryjoin_np , pthread_tryjoin_np );
39
77
weak_alias (__pthread_timedjoin_np , pthread_timedjoin_np );
40
78
weak_alias (__pthread_join , pthread_join );
79
+ #ifdef __EMSCRIPTEN__ // XXX Emscripten add an extra alias for LSan
80
+ weak_alias (__pthread_join , emscripten_builtin_pthread_join );
81
+ #endif
0 commit comments