summaryrefslogtreecommitdiff
path: root/win32_threads.c
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2012-11-21 22:26:29 +0400
committerIvan Maidanski <ivmai@mail.ru>2012-11-21 22:31:30 +0400
commit0a420dc3f8b69a5675b504f7975d170ee79f1ee2 (patch)
tree21475965be9b38a050f22afbaf90b9cdf9b94026 /win32_threads.c
parentff93a74691be86ed6ae4f9572a028e7eb9e5c944 (diff)
downloadbdwgc-0a420dc3f8b69a5675b504f7975d170ee79f1ee2.tar.gz
Add manual POSIX fork handling support (Android)
* include/gc.h (GC_set_handle_fork): Update comment. * include/gc.h (GC_atfork_prepare, GC_atfork_parent, GC_atfork_child): New API proto. * include/private/gc_priv.h (GC_handle_fork): Change type from GC_bool to int (to hold a value of -1). * misc.c (GC_handle_fork): Likewise. * include/private/gc_priv.h (GC_handle_fork): Add comment. * misc.c (GC_set_handle_fork): Likewise. * include/private/gcconfig.h (CAN_HANDLE_FORK): Define also for HURD and PLATFORM_ANDROID; do not define if HAVE_NO_FORK already defined. * include/private/gcconfig.h (CAN_CALL_ATFORK): New macro (defined if CAN_HANDLE_FORK but not HURD or PLATFORM_ANDROID). * include/private/gcconfig.h (HAVE_NO_FORK): New macro (defined for Win32, OS/2 and others). * misc.c (GC_atfork_prepare, GC_atfork_parent, GC_atfork_child): New API function definition (only if not CAN_HANDLE_FORK and not HAVE_NO_FORK). * misc.c (GC_handle_fork): Map all negative values of argument except for -1 to a positive one stored to GC_handle_fork; call GC_init to initialize GC_stderr before ABORT invocation (only if not SMALL_CONFIG). * pthread_support.c (GC_atfork_prepare, GC_atfork_parent, GC_atfork_child): New API function definition (only if CAN_HANDLE_FORK). * win32_threads.c (GC_atfork_prepare, GC_atfork_parent, GC_atfork_child): Likewise. * pthread_support.c (GC_thr_init): No pthread_atfork call if not CAN_CALL_ATFORK; adjust GC_handle_fork value if pthread_atfork succeeds; do not about in case of pthread_atfork failure provided GC_handle_fork is -1 (only if CAN_HANDLE_FORK). * win32_threads.c (GC_thr_init): Likewise. * tests/test.c (TEST_FORK_WITHOUT_ATFORK): Recognize new macro (do not define NO_TEST_HANDLE_FORK in this case and set INIT_FORK_SUPPORT to no-op). * tests/test.c (INIT_FORK_SUPPORT): Define to GC_set_handle_fork(-1) unless HANDLE_FORK, or NO_TEST_HANDLE_FORK or TEST_FORK_WITHOUT_ATFORK. * tests/test.c (run_one_test): Surround fork() invocation with GC_atfork_prepare, GC_atfork_parent, GC_atfork_child calls. * win32_threads.c: Include unistd.h if CAN_CALL_ATFORK defined (instead of CAN_HANDLE_FORK) to get pthread_atfork prototype.
Diffstat (limited to 'win32_threads.c')
-rw-r--r--win32_threads.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/win32_threads.c b/win32_threads.c
index 4e25bc71..83b2c420 100644
--- a/win32_threads.c
+++ b/win32_threads.c
@@ -60,7 +60,7 @@
STATIC void GC_thread_exit_proc(void *arg);
# include <pthread.h>
-# ifdef CAN_HANDLE_FORK
+# ifdef CAN_CALL_ATFORK
# include <unistd.h>
# endif
@@ -1085,6 +1085,25 @@ GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type fn,
GC_remove_all_threads_but_me();
UNLOCK();
}
+
+ /* Routines for fork handling by client (no-op if pthread_atfork works). */
+ GC_API void GC_CALL GC_atfork_prepare(void)
+ {
+ if (GC_handle_fork <= 0)
+ fork_prepare_proc();
+ }
+
+ GC_API void GC_CALL GC_atfork_parent(void)
+ {
+ if (GC_handle_fork <= 0)
+ fork_parent_proc();
+ }
+
+ GC_API void GC_CALL GC_atfork_child(void)
+ {
+ if (GC_handle_fork <= 0)
+ fork_child_proc();
+ }
#endif /* CAN_HANDLE_FORK */
void GC_push_thread_structures(void)
@@ -2404,10 +2423,17 @@ GC_INNER void GC_thr_init(void)
# ifdef CAN_HANDLE_FORK
/* Prepare for forks if requested. */
- if (GC_handle_fork
- && pthread_atfork(fork_prepare_proc, fork_parent_proc,
- fork_child_proc) != 0)
- ABORT("pthread_atfork failed");
+ if (GC_handle_fork) {
+# ifdef CAN_CALL_ATFORK
+ if (pthread_atfork(fork_prepare_proc, fork_parent_proc,
+ fork_child_proc) == 0) {
+ /* Handlers successfully registered. */
+ GC_handle_fork = 1;
+ } else
+# endif
+ /* else */ if (GC_handle_fork != -1)
+ ABORT("pthread_atfork failed");
+ }
# endif
/* Add the initial thread, so we can stop it. */