Keep one builtin slot so that pthread initialization doesn't need to use
malloc().
This commit is contained in:
parent
8ecf8999bf
commit
1046045268
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: pthread_atfork.c,v 1.6 2007/12/14 19:51:37 yamt Exp $ */
|
/* $NetBSD: pthread_atfork.c,v 1.7 2008/03/07 17:56:39 ad Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 2002 The NetBSD Foundation, Inc.
|
* Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
__RCSID("$NetBSD: pthread_atfork.c,v 1.6 2007/12/14 19:51:37 yamt Exp $");
|
__RCSID("$NetBSD: pthread_atfork.c,v 1.7 2008/03/07 17:56:39 ad Exp $");
|
||||||
#endif /* LIBC_SCCS and not lint */
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
#include "namespace.h"
|
#include "namespace.h"
|
||||||
|
@ -67,6 +67,7 @@ struct atfork_callback {
|
||||||
* since the intended use of the functions is obtaining locks to hold
|
* since the intended use of the functions is obtaining locks to hold
|
||||||
* across the fork, forking is going to be serialized anyway.
|
* across the fork, forking is going to be serialized anyway.
|
||||||
*/
|
*/
|
||||||
|
static struct atfork_callback atfork_builtin;
|
||||||
static mutex_t atfork_lock = MUTEX_INITIALIZER;
|
static mutex_t atfork_lock = MUTEX_INITIALIZER;
|
||||||
SIMPLEQ_HEAD(atfork_callback_q, atfork_callback);
|
SIMPLEQ_HEAD(atfork_callback_q, atfork_callback);
|
||||||
|
|
||||||
|
@ -74,6 +75,24 @@ static struct atfork_callback_q prepareq = SIMPLEQ_HEAD_INITIALIZER(prepareq);
|
||||||
static struct atfork_callback_q parentq = SIMPLEQ_HEAD_INITIALIZER(parentq);
|
static struct atfork_callback_q parentq = SIMPLEQ_HEAD_INITIALIZER(parentq);
|
||||||
static struct atfork_callback_q childq = SIMPLEQ_HEAD_INITIALIZER(childq);
|
static struct atfork_callback_q childq = SIMPLEQ_HEAD_INITIALIZER(childq);
|
||||||
|
|
||||||
|
static struct atfork_callback *
|
||||||
|
af_alloc(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (atfork_builtin.fn == NULL)
|
||||||
|
return &atfork_builtin;
|
||||||
|
|
||||||
|
return malloc(sizeof(atfork_builtin));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
af_free(struct atfork_callback *af)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (af != &atfork_builtin)
|
||||||
|
free(af);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pthread_atfork(void (*prepare)(void), void (*parent)(void),
|
pthread_atfork(void (*prepare)(void), void (*parent)(void),
|
||||||
void (*child)(void))
|
void (*child)(void))
|
||||||
|
@ -82,36 +101,40 @@ pthread_atfork(void (*prepare)(void), void (*parent)(void),
|
||||||
|
|
||||||
newprepare = newparent = newchild = NULL;
|
newprepare = newparent = newchild = NULL;
|
||||||
|
|
||||||
|
mutex_lock(&atfork_lock);
|
||||||
if (prepare != NULL) {
|
if (prepare != NULL) {
|
||||||
newprepare = malloc(sizeof(struct atfork_callback));
|
newprepare = af_alloc();
|
||||||
if (newprepare == NULL)
|
if (newprepare == NULL) {
|
||||||
|
mutex_unlock(&atfork_lock);
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
}
|
||||||
newprepare->fn = prepare;
|
newprepare->fn = prepare;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent != NULL) {
|
if (parent != NULL) {
|
||||||
newparent = malloc(sizeof(struct atfork_callback));
|
newparent = af_alloc();
|
||||||
if (newparent == NULL) {
|
if (newparent == NULL) {
|
||||||
if (newprepare != NULL)
|
if (newprepare != NULL)
|
||||||
free(newprepare);
|
af_free(newprepare);
|
||||||
|
mutex_unlock(&atfork_lock);
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
newparent->fn = parent;
|
newparent->fn = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child != NULL) {
|
if (child != NULL) {
|
||||||
newchild = malloc(sizeof(struct atfork_callback));
|
newchild = af_alloc();
|
||||||
if (newchild == NULL) {
|
if (newchild == NULL) {
|
||||||
if (newprepare != NULL)
|
if (newprepare != NULL)
|
||||||
free(newprepare);
|
af_free(newprepare);
|
||||||
if (newparent != NULL)
|
if (newparent != NULL)
|
||||||
free(newparent);
|
af_free(newparent);
|
||||||
|
mutex_unlock(&atfork_lock);
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
newchild->fn = child;
|
newchild->fn = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&atfork_lock);
|
|
||||||
/*
|
/*
|
||||||
* The order in which the functions are called is specified as
|
* The order in which the functions are called is specified as
|
||||||
* LIFO for the prepare handler and FIFO for the others; insert
|
* LIFO for the prepare handler and FIFO for the others; insert
|
||||||
|
|
Loading…
Reference in New Issue