about summary refs log tree commit diff
path: root/src/env/__init_tls.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2018-05-02 12:13:43 -0400
committerRich Felker <dalias@aerifal.cx>2018-05-02 12:33:29 -0400
commit9e2d820a555e150df462f88c901fcbe25d692a8b (patch)
tree104c68bdbeb371bcb9e12c23b31dfc3f96fd57e6 /src/env/__init_tls.c
parent941bd884cc0221d051840ce6d21650339e711863 (diff)
downloadmusl-9e2d820a555e150df462f88c901fcbe25d692a8b.tar.gz
musl-9e2d820a555e150df462f88c901fcbe25d692a8b.tar.xz
musl-9e2d820a555e150df462f88c901fcbe25d692a8b.zip
use a dedicated futex object for pthread_join instead of tid field
the tid field in the pthread structure is not volatile, and really
shouldn't be, so as not to limit the compiler's ability to reorder,
merge, or split loads in code paths that may be relevant to
performance (like controlling lock ownership).

however, use of objects which are not volatile or atomic with futex
wait is inherently broken, since the compiler is free to transform a
single load into multiple loads, thereby using a different value for
the controlling expression of the loop and the value passed to the
futex syscall, leading the syscall to block instead of returning.

reportedly glibc's pthread_join was actually affected by an equivalent
issue in glibc on s390.

add a separate, dedicated join_futex object for pthread_join to use.
Diffstat (limited to 'src/env/__init_tls.c')
-rw-r--r--src/env/__init_tls.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/src/env/__init_tls.c b/src/env/__init_tls.c
index b125eb1f..80044960 100644
--- a/src/env/__init_tls.c
+++ b/src/env/__init_tls.c
@@ -15,7 +15,8 @@ int __init_tp(void *p)
 	int r = __set_thread_area(TP_ADJ(p));
 	if (r < 0) return -1;
 	if (!r) libc.can_do_threads = 1;
-	td->tid = __syscall(SYS_set_tid_address, &td->tid);
+	td->join_futex = -1;
+	td->tid = __syscall(SYS_set_tid_address, &td->join_futex);
 	td->locale = &libc.global_locale;
 	td->robust_list.head = &td->robust_list.head;
 	return 0;