summaryrefslogtreecommitdiff
path: root/nptl/pthreadP.h
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2015-07-01 14:05:27 -0600
committerMartin Sebor <msebor@redhat.com>2015-07-01 14:05:27 -0600
commited225df3ad9cbac3c22ec3f0fbbed1f9c61d1c54 (patch)
tree175abf6476b8924e619c559993324efdb855e392 /nptl/pthreadP.h
parent9081b7bcb11e74cd2d4363663ccd1bb641392719 (diff)
The C++ 2011 std::call_once function is specified to allow
the initialization routine to exit by throwing an exception. Such an execution, termed exceptional, requires call_once to propagate the exception to its caller. A program may contain any number of exceptional executions but only one returning execution (which, if it exists, must be the last execution with the same once flag). On POSIX systems such as Linux, std::call_once is implemented in terms of pthread_once. However, as discussed in libstdc++ bug 66146 - "call_once not C++11-compliant on ppc64le," GLIBC's pthread_once hangs when the initialization function exits by throwing an exception on at least arm and ppc64 (though apparently not on x86_64). This effectively prevents call_once from conforming to the C++ requirements since there doesn't appear to be a thread-safe way to work around this problem in libstdc++. This patch changes pthread_once to handle gracefully init functions that exit by throwing exceptions. It was successfully tested on ppc64, ppc64le, and x86_64. [BZ #18435] * nptl/Makefile: Add tst-once5.cc. * nptl/pthreadP.h (pthread_cleanup_push, pthread_cleanup_pop): Remove macro redefinitions. * nptl/tst-once5.cc: New test.
Diffstat (limited to 'nptl/pthreadP.h')
-rw-r--r--nptl/pthreadP.h7
1 files changed, 0 insertions, 7 deletions
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index 84a7105848..72d3e23b95 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -536,16 +536,9 @@ extern void __librt_disable_asynccancel (int oldtype)
extern void __pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
void (*routine) (void *), void *arg)
attribute_hidden;
-# undef pthread_cleanup_push
-# define pthread_cleanup_push(routine,arg) \
- { struct _pthread_cleanup_buffer _buffer; \
- __pthread_cleanup_push (&_buffer, (routine), (arg));
extern void __pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
int execute) attribute_hidden;
-# undef pthread_cleanup_pop
-# define pthread_cleanup_pop(execute) \
- __pthread_cleanup_pop (&_buffer, (execute)); }
#endif
extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,