* Copyright (c) 1999, 2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
+ *
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
- *
+ *
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
- *
+ *
* @APPLE_LICENSE_HEADER_END@
*/
#include "internal.h"
-#include <libkern/OSAtomic.h>
#include <mach/mach_init.h>
#include <mach/mach_vm.h>
#include <platform/compat.h>
-PTHREAD_NOEXPORT void pthread_workqueue_atfork_child(void);
-PTHREAD_NOEXPORT void __pthread_fork_child_internal(pthread_t);
-
int
pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
{
int res = 0;
size_t idx;
pthread_globals_t globals = _pthread_globals();
-
+
_PTHREAD_LOCK(globals->pthread_atfork_lock);
idx = globals->atfork_count++;
} else if (idx >= PTHREAD_ATFORK_MAX) {
res = ENOMEM;
}
-
+
if (res == 0) {
struct pthread_atfork_entry *e = &globals->atfork[idx];
e->prepare = prepare;
// Called before the fork(2) system call is made in the parent process.
// Iterate pthread_atfork prepare handlers.
+// Called first in libSystem_atfork_prepare().
void
-_pthread_fork_prepare(void)
+_pthread_atfork_prepare_handlers(void)
{
pthread_globals_t globals = _pthread_globals();
_PTHREAD_LOCK(globals->pthread_atfork_lock);
-
size_t idx;
for (idx = globals->atfork_count; idx > 0; --idx) {
struct pthread_atfork_entry *e = &globals->atfork[idx-1];
e->prepare();
}
}
+}
+
+// Take pthread-internal locks.
+// Called last in libSystem_atfork_prepare().
+void
+_pthread_atfork_prepare(void)
+{
+ pthread_globals_t globals = _pthread_globals();
_PTHREAD_LOCK(globals->psaved_self_global_lock);
globals->psaved_self = pthread_self();
}
// Called after the fork(2) system call returns to the parent process.
-// Iterate pthread_atfork parent handlers.
+// Release pthread-internal locks
+// Called first in libSystem_atfork_parent().
void
-_pthread_fork_parent(void)
+_pthread_atfork_parent(void)
{
pthread_globals_t globals = _pthread_globals();
_PTHREAD_UNLOCK(globals->psaved_self->lock);
_PTHREAD_UNLOCK(globals->psaved_self_global_lock);
+}
+
+// Iterate pthread_atfork parent handlers.
+// Called last in libSystem_atfork_parent().
+void
+_pthread_atfork_parent_handlers(void)
+{
+ pthread_globals_t globals = _pthread_globals();
size_t idx;
for (idx = 0; idx < globals->atfork_count; ++idx) {
// Called after the fork(2) system call returns to the new child process.
// Clean up data structures of other threads which no longer exist in the child.
// Make the current thread the main thread.
+// Called first in libSystem_atfork_child() (after _dyld_fork_child)
void
-_pthread_fork_child(void)
+_pthread_atfork_child(void)
{
pthread_globals_t globals = _pthread_globals();
_PTHREAD_LOCK_INIT(globals->psaved_self_global_lock);
- __pthread_fork_child_internal(globals->psaved_self);
__is_threaded = 0;
- pthread_workqueue_atfork_child();
+ _pthread_main_thread_postfork_init(globals->psaved_self);
+
+ struct _pthread_registration_data registration_data;
+ _pthread_bsdthread_init(®istration_data);
}
// Iterate pthread_atfork child handlers.
+// Called last in libSystem_atfork_child().
void
-_pthread_fork_child_postinit(void)
+_pthread_atfork_child_handlers(void)
{
pthread_globals_t globals = _pthread_globals();
size_t idx;
}
_PTHREAD_LOCK_INIT(globals->pthread_atfork_lock);
}
+
+// Preserve legacy symbols for older iOS simulators
+void
+_pthread_fork_prepare(void)
+{
+ _pthread_atfork_prepare_handlers();
+ _pthread_atfork_prepare();
+}
+
+void
+_pthread_fork_parent(void)
+{
+ _pthread_atfork_parent();
+ _pthread_atfork_parent_handlers();
+}
+
+void
+_pthread_fork_child(void)
+{
+ _pthread_atfork_child();
+}
+
+void
+_pthread_fork_child_postinit(void)
+{
+ _pthread_atfork_child_handlers();
+}