summaryrefslogtreecommitdiffstats
path: root/lib/libpthread
diff options
context:
space:
mode:
authordeischen <deischen@FreeBSD.org>2003-11-04 20:04:45 +0000
committerdeischen <deischen@FreeBSD.org>2003-11-04 20:04:45 +0000
commit1191fa7e324052c4d97e45f85cbb566eb985c1c6 (patch)
treec66d125bd34129e0d434c2444369c5dd31c55ad0 /lib/libpthread
parent573b8090444db7cfee8d60b937cc6d39632c8bbc (diff)
downloadFreeBSD-src-1191fa7e324052c4d97e45f85cbb566eb985c1c6.zip
FreeBSD-src-1191fa7e324052c4d97e45f85cbb566eb985c1c6.tar.gz
Add an implementation for pthread_atfork().
Aside from the POSIX requirements for pthread_atfork(), when fork()ing, take the malloc lock to keep malloc state consistent in the child. Reviewed by: davidxu
Diffstat (limited to 'lib/libpthread')
-rw-r--r--lib/libpthread/pthread.map2
-rw-r--r--lib/libpthread/thread/Makefile.inc3
-rw-r--r--lib/libpthread/thread/thr_fork.c43
-rw-r--r--lib/libpthread/thread/thr_init.c2
-rw-r--r--lib/libpthread/thread/thr_kern.c16
-rw-r--r--lib/libpthread/thread/thr_private.h13
6 files changed, 73 insertions, 6 deletions
diff --git a/lib/libpthread/pthread.map b/lib/libpthread/pthread.map
index ce46f96..ae0a5ae 100644
--- a/lib/libpthread/pthread.map
+++ b/lib/libpthread/pthread.map
@@ -27,6 +27,7 @@ global:
_nanosleep;
_pause;
_pselect;
+ _pthread_atfork;
_pthread_barrier_destroy;
_pthread_barrier_init;
_pthread_barrier_wait;
@@ -178,6 +179,7 @@ global:
pause;
poll;
pselect;
+ pthread_atfork;
pthread_barrier_destroy;
pthread_barrier_init;
pthread_barrier_wait;
diff --git a/lib/libpthread/thread/Makefile.inc b/lib/libpthread/thread/Makefile.inc
index 52c342c..d29da77 100644
--- a/lib/libpthread/thread/Makefile.inc
+++ b/lib/libpthread/thread/Makefile.inc
@@ -5,7 +5,7 @@
SRCS+= \
thr_aio_suspend.c \
- thr_autoinit.c \
+ thr_atfork.c \
thr_attr_destroy.c \
thr_attr_init.c \
thr_attr_get_np.c \
@@ -28,6 +28,7 @@ SRCS+= \
thr_attr_setstack.c \
thr_attr_setstackaddr.c \
thr_attr_setstacksize.c \
+ thr_autoinit.c \
thr_barrier.c \
thr_barrierattr.c \
thr_cancel.c \
diff --git a/lib/libpthread/thread/thr_fork.c b/lib/libpthread/thread/thr_fork.c
index f640614..6989174 100644
--- a/lib/libpthread/thread/thr_fork.c
+++ b/lib/libpthread/thread/thr_fork.c
@@ -37,9 +37,13 @@
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
+#include <spinlock.h>
#include <sys/signalvar.h>
#include "thr_private.h"
+extern spinlock_t *__malloc_lock;
+#pragma weak __malloc_lock
+
__weak_reference(_fork, fork);
pid_t
@@ -47,6 +51,7 @@ _fork(void)
{
sigset_t sigset, oldset;
struct pthread *curthread;
+ struct pthread_atfork *af;
pid_t ret;
int errsave;
@@ -66,18 +71,48 @@ _fork(void)
SIGFILLSET(sigset);
__sys_sigprocmask(SIG_SETMASK, &sigset, &oldset);
}
+
+ _pthread_mutex_lock(&_thr_atfork_mutex);
+
+ /* Run down atfork prepare handlers. */
+ TAILQ_FOREACH_REVERSE(af, &_thr_atfork_list, atfork_head, qe) {
+ if (af->prepare != NULL)
+ af->prepare();
+ }
+
/* Fork a new process: */
+ if ((_kse_isthreaded() != 0) && (__malloc_lock != NULL)) {
+ _spinlock(__malloc_lock);
+ }
if ((ret = __sys_fork()) == 0) {
/* Child process */
- _kse_single_thread(curthread);
+ errsave = errno;
+
/* Kernel signal mask is restored in _kse_single_thread */
+ _kse_single_thread(curthread);
+
+ /* Run down atfork child handlers. */
+ TAILQ_FOREACH(af, &_thr_atfork_list, qe) {
+ if (af->child != NULL)
+ af->child();
+ }
+ _thr_mutex_reinit(&_thr_atfork_mutex);
} else {
+ if ((_kse_isthreaded() != 0) && (__malloc_lock != NULL)) {
+ _spinunlock(__malloc_lock);
+ }
+ errsave = errno;
if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
- errsave = errno;
__sys_sigprocmask(SIG_SETMASK, &oldset, NULL);
- errno = errsave;
- }
+ }
+ /* Run down atfork parent handlers. */
+ TAILQ_FOREACH(af, &_thr_atfork_list, qe) {
+ if (af->parent != NULL)
+ af->parent();
+ }
+ _pthread_mutex_unlock(&_thr_atfork_mutex);
}
+ errno = errsave;
/* Return the process ID: */
return (ret);
diff --git a/lib/libpthread/thread/thr_init.c b/lib/libpthread/thread/thr_init.c
index 7f60994..76eeee4 100644
--- a/lib/libpthread/thread/thr_init.c
+++ b/lib/libpthread/thread/thr_init.c
@@ -461,6 +461,8 @@ init_private(void)
/* Initialize everything else. */
TAILQ_INIT(&_thread_list);
TAILQ_INIT(&_thread_gc_list);
+ TAILQ_INIT(&_thr_atfork_list);
+ _pthread_mutex_init(&_thr_atfork_mutex, NULL);
/*
* Initialize the lock for temporary installation of signal
diff --git a/lib/libpthread/thread/thr_kern.c b/lib/libpthread/thread/thr_kern.c
index e16a1b0..7909838 100644
--- a/lib/libpthread/thread/thr_kern.c
+++ b/lib/libpthread/thread/thr_kern.c
@@ -329,6 +329,20 @@ _kse_single_thread(struct pthread *curthread)
_kse_initial = NULL;
_libpthread_init(curthread);
#else
+ int i;
+
+ /* Reset the current thread and KSE lock data. */
+ for (i = 0; i < curthread->locklevel; i++) {
+ _lockuser_reinit(&curthread->lockusers[i], (void *)curthread);
+ }
+ curthread->locklevel = 0;
+ for (i = 0; i < curthread->kse->k_locklevel; i++) {
+ _lockuser_reinit(&curthread->kse->k_lockusers[i],
+ (void *)curthread->kse);
+ _LCK_SET_PRIVATE2(&curthread->kse->k_lockusers[i], NULL);
+ }
+ curthread->kse->k_locklevel = 0;
+ _thr_spinlock_init();
if (__isthreaded) {
_thr_rtld_fini();
_thr_signal_deinit();
@@ -2015,7 +2029,7 @@ _thr_setrunnable(struct pthread *curthread, struct pthread *thread)
kmbx = _thr_setrunnable_unlocked(thread);
KSE_SCHED_UNLOCK(curthread->kse, thread->kseg);
_kse_critical_leave(crit);
- if (kmbx != NULL)
+ if ((kmbx != NULL) && (__isthreaded != 0))
kse_wakeup(kmbx);
}
diff --git a/lib/libpthread/thread/thr_private.h b/lib/libpthread/thread/thr_private.h
index 518e881..d8453ff 100644
--- a/lib/libpthread/thread/thr_private.h
+++ b/lib/libpthread/thread/thr_private.h
@@ -442,6 +442,13 @@ struct pthread_cleanup {
void *routine_arg;
};
+struct pthread_atfork {
+ TAILQ_ENTRY(pthread_atfork) qe;
+ void (*prepare)(void);
+ void (*parent)(void);
+ void (*child)(void);
+};
+
struct pthread_attr {
int sched_policy;
int sched_inherit;
@@ -997,6 +1004,9 @@ SCLASS TAILQ_HEAD(, pthread) _thread_gc_list
SCLASS int _thr_active_threads SCLASS_PRESET(1);
+SCLASS TAILQ_HEAD(atfork_head, pthread_atfork) _thr_atfork_list;
+SCLASS pthread_mutex_t _thr_atfork_mutex;
+
/* Default thread attributes: */
SCLASS struct pthread_attr _pthread_attr_default
SCLASS_PRESET({
@@ -1109,8 +1119,11 @@ void _thr_exit(char *, int, char *);
void _thr_exit_cleanup(void);
void _thr_lock_wait(struct lock *lock, struct lockuser *lu);
void _thr_lock_wakeup(struct lock *lock, struct lockuser *lu);
+void _thr_mutex_reinit(pthread_mutex_t *);
int _thr_ref_add(struct pthread *, struct pthread *, int);
void _thr_ref_delete(struct pthread *, struct pthread *);
+void _thr_rtld_init(void);
+void _thr_rtld_fini(void);
int _thr_schedule_add(struct pthread *, struct pthread *);
void _thr_schedule_remove(struct pthread *, struct pthread *);
void _thr_setrunnable(struct pthread *curthread, struct pthread *thread);
OpenPOWER on IntegriCloud