1*fe38b55cSguenther /* $OpenBSD: w_fork.c,v 1.3 2016/05/07 19:05:22 guenther Exp $ */
2514a545fSguenther
3514a545fSguenther /*
4514a545fSguenther * Copyright (c) 2008 Kurt Miller <kurt@openbsd.org>
5514a545fSguenther * Copyright (c) 2008 Philip Guenther <guenther@openbsd.org>
6514a545fSguenther * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org>
7514a545fSguenther * All rights reserved.
8514a545fSguenther *
9514a545fSguenther * Redistribution and use in source and binary forms, with or without
10514a545fSguenther * modification, are permitted provided that the following conditions
11514a545fSguenther * are met:
12514a545fSguenther * 1. Redistributions of source code must retain the above copyright
13514a545fSguenther * notice, this list of conditions and the following disclaimer.
14514a545fSguenther * 2. Neither the name of the author nor the names of any co-contributors
15514a545fSguenther * may be used to endorse or promote products derived from this software
16514a545fSguenther * without specific prior written permission.
17514a545fSguenther *
18514a545fSguenther * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19514a545fSguenther * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20514a545fSguenther * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21514a545fSguenther * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22514a545fSguenther * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23514a545fSguenther * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24514a545fSguenther * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25514a545fSguenther * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26514a545fSguenther * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27514a545fSguenther * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28514a545fSguenther * SUCH DAMAGE.
29514a545fSguenther *
30514a545fSguenther * $FreeBSD: /repoman/r/ncvs/src/lib/libc_r/uthread/uthread_atfork.c,v 1.1 2004/12/10 03:36:45 grog Exp $
31514a545fSguenther */
32514a545fSguenther
33*fe38b55cSguenther #include <tib.h>
34514a545fSguenther #include <unistd.h>
35514a545fSguenther #include "thread_private.h"
36514a545fSguenther #include "atfork.h"
37514a545fSguenther
38514a545fSguenther pid_t
WRAP(fork)39*fe38b55cSguenther WRAP(fork)(void)
40514a545fSguenther {
41514a545fSguenther struct atfork_fn *p;
42514a545fSguenther pid_t newid;
43514a545fSguenther
44514a545fSguenther /*
45514a545fSguenther * In the common case the list is empty; remain async-signal-safe
46514a545fSguenther * then by skipping the locking and just forking
47514a545fSguenther */
48*fe38b55cSguenther if (TAILQ_FIRST(&_atfork_list) == NULL) {
49*fe38b55cSguenther if (_thread_cb.tc_fork != NULL)
50*fe38b55cSguenther return _thread_cb.tc_fork();
51*fe38b55cSguenther newid = fork();
52*fe38b55cSguenther if (newid == 0)
53*fe38b55cSguenther TIB_GET()->tib_tid = getthrid();
54*fe38b55cSguenther return newid;
55*fe38b55cSguenther }
56514a545fSguenther
57514a545fSguenther _ATFORK_LOCK();
58514a545fSguenther TAILQ_FOREACH_REVERSE(p, &_atfork_list, atfork_listhead, fn_next)
59514a545fSguenther if (p->fn_prepare)
60514a545fSguenther p->fn_prepare();
61514a545fSguenther
62*fe38b55cSguenther if (_thread_cb.tc_fork != NULL)
63*fe38b55cSguenther newid = _thread_cb.tc_fork();
64*fe38b55cSguenther else {
65*fe38b55cSguenther newid = fork();
66*fe38b55cSguenther if (newid == 0)
67*fe38b55cSguenther TIB_GET()->tib_tid = getthrid();
68*fe38b55cSguenther }
69514a545fSguenther
70514a545fSguenther if (newid == 0) {
71514a545fSguenther TAILQ_FOREACH(p, &_atfork_list, fn_next)
72514a545fSguenther if (p->fn_child)
73514a545fSguenther p->fn_child();
74514a545fSguenther } else {
75514a545fSguenther TAILQ_FOREACH(p, &_atfork_list, fn_next)
76514a545fSguenther if (p->fn_parent)
77514a545fSguenther p->fn_parent();
78514a545fSguenther }
79514a545fSguenther _ATFORK_UNLOCK();
80514a545fSguenther
81514a545fSguenther return (newid);
82514a545fSguenther }
83*fe38b55cSguenther DEF_WRAP(fork);
84