-
Nadav Har'El authored
When multiple threads concurrently use a function which has a static variable with a constructor, gcc guarantees that only one thread will run the constructor, and the other ones waits. It uses __cxa_guard_acquire()/ release()/abort() for implementing this guarantee. Unfortunately these functions, implemented in the C++ standard library, use the Linux futex syscall which we don't implement. The futex system call is only used in the rare case of contention - in the normal case, the __cxa_guard_* functions uses just atomic memory operations. This patch implements the bare minimum we need from futex to make the __cxa_guard_* functions work: All we need is FUTEX_WAIT and FUTEX_WAKE, with 0 timeout in FUTEX_WAIT and wake all in FUTEX_WAKE. It's nice how the new waitqueues fit this implementation like glove to a hand: We could use condvars too, but we anyway need to do the wake() with the mutex locked (to get the futex's atomic test-and-wait), and in that case we can use waitqueues without their additional internal mutex. This patch also adds a test for this bug. Catching this bug in a real application is very rare, but the test exposes it by defining an function- static object with a very slow constructor (it sleeps for a second), and calls the function from several threads concurrently. Before this patch the test fails with: constructing syscall(): unimplemented system call 202. Aborting. Fixes #199. Signed-off-by:
Nadav Har'El <nyh@cloudius-systems.com> Signed-off-by:
Pekka Enberg <penberg@cloudius-systems.com>
Nadav Har'El authoredWhen multiple threads concurrently use a function which has a static variable with a constructor, gcc guarantees that only one thread will run the constructor, and the other ones waits. It uses __cxa_guard_acquire()/ release()/abort() for implementing this guarantee. Unfortunately these functions, implemented in the C++ standard library, use the Linux futex syscall which we don't implement. The futex system call is only used in the rare case of contention - in the normal case, the __cxa_guard_* functions uses just atomic memory operations. This patch implements the bare minimum we need from futex to make the __cxa_guard_* functions work: All we need is FUTEX_WAIT and FUTEX_WAKE, with 0 timeout in FUTEX_WAIT and wake all in FUTEX_WAKE. It's nice how the new waitqueues fit this implementation like glove to a hand: We could use condvars too, but we anyway need to do the wake() with the mutex locked (to get the futex's atomic test-and-wait), and in that case we can use waitqueues without their additional internal mutex. This patch also adds a test for this bug. Catching this bug in a real application is very rare, but the test exposes it by defining an function- static object with a very slow constructor (it sleeps for a second), and calls the function from several threads concurrently. Before this patch the test fails with: constructing syscall(): unimplemented system call 202. Aborting. Fixes #199. Signed-off-by:
Nadav Har'El <nyh@cloudius-systems.com> Signed-off-by:
Pekka Enberg <penberg@cloudius-systems.com>