1*9f79a698Smpi /* $OpenBSD: rthread_fork.c,v 1.23 2017/10/29 08:45:53 mpi Exp $ */
2dc989ac6Skurt
3dc989ac6Skurt /*
4dc989ac6Skurt * Copyright (c) 2008 Kurt Miller <kurt@openbsd.org>
5514a545fSguenther * Copyright (c) 2008 Philip Guenther <guenther@openbsd.org>
6dc989ac6Skurt * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org>
7dc989ac6Skurt * All rights reserved.
8dc989ac6Skurt *
9dc989ac6Skurt * Redistribution and use in source and binary forms, with or without
10dc989ac6Skurt * modification, are permitted provided that the following conditions
11dc989ac6Skurt * are met:
12dc989ac6Skurt * 1. Redistributions of source code must retain the above copyright
13dc989ac6Skurt * notice, this list of conditions and the following disclaimer.
14dc989ac6Skurt * 2. Neither the name of the author nor the names of any co-contributors
15dc989ac6Skurt * may be used to endorse or promote products derived from this software
16dc989ac6Skurt * without specific prior written permission.
17dc989ac6Skurt *
18dc989ac6Skurt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19dc989ac6Skurt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20dc989ac6Skurt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21dc989ac6Skurt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22dc989ac6Skurt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23dc989ac6Skurt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24dc989ac6Skurt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25dc989ac6Skurt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26dc989ac6Skurt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27dc989ac6Skurt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28dc989ac6Skurt * SUCH DAMAGE.
29dc989ac6Skurt *
30dc989ac6Skurt * $FreeBSD: /repoman/r/ncvs/src/lib/libc_r/uthread/uthread_atfork.c,v 1.1 2004/12/10 03:36:45 grog Exp $
31dc989ac6Skurt */
32dc989ac6Skurt
33b8ec2dbdSguenther #ifndef NO_PIC
3428e55baeSmatthew #include <sys/types.h>
35*9f79a698Smpi #include <elf.h>
3628e55baeSmatthew #pragma weak _DYNAMIC
3728e55baeSmatthew #endif
3828e55baeSmatthew
39dc989ac6Skurt #include <errno.h>
40dc989ac6Skurt #include <pthread.h>
41a5511fa9Sguenther #include <stdio.h>
42dc989ac6Skurt #include <stdlib.h>
43fe38b55cSguenther #include <tib.h>
44dc989ac6Skurt #include <unistd.h>
45dc989ac6Skurt
46dc989ac6Skurt #include "rthread.h"
47fe38b55cSguenther #include "rthread_cb.h"
48dc989ac6Skurt
49fe38b55cSguenther /* make {fork,vfork,getthrid} call _thread_sys_{fork,vfork,getthrid} */
50fe38b55cSguenther REDIRECT_SYSCALL(fork);
51fe38b55cSguenther REDIRECT_SYSCALL(vfork);
5229088be8Sguenther REDIRECT_SYSCALL(getthrid);
5329088be8Sguenther
54fe38b55cSguenther static pid_t
_dofork(pid_t (* sys_fork)(void))55fe38b55cSguenther _dofork(pid_t (*sys_fork)(void))
56dc989ac6Skurt {
57dc989ac6Skurt pthread_t me;
58dc989ac6Skurt pid_t newid;
59a9128774Stedu extern int _post_threaded;
60dc989ac6Skurt
61dc989ac6Skurt if (!_threads_ready)
62dc989ac6Skurt return sys_fork();
63dc989ac6Skurt
64dc989ac6Skurt me = pthread_self();
65dc989ac6Skurt
66dc989ac6Skurt /*
67dc989ac6Skurt * Protect important libc/ld.so critical areas across the fork call.
68dc989ac6Skurt * dlclose() will grab the atexit lock via __cxa_finalize() so lock
695f82dc8bSguenther * the dl_lock first. malloc()/free() can use arc4random(), so lock
705f82dc8bSguenther * malloc_lock before arc4_lock
71dc989ac6Skurt */
72dc989ac6Skurt
73b8ec2dbdSguenther #ifndef NO_PIC
7428e55baeSmatthew if (_DYNAMIC)
75dc989ac6Skurt _rthread_dl_lock(0);
76dc989ac6Skurt #endif
77dc989ac6Skurt
78a5511fa9Sguenther newid = _thread_dofork(sys_fork);
79dc989ac6Skurt
80dc989ac6Skurt if (newid == 0) {
81fe38b55cSguenther struct tib *tib = me->tib;
82b8ec2dbdSguenther #ifndef NO_PIC
83e0ad4b33Sguenther /* reinitialize the lock in the child */
84e0ad4b33Sguenther if (_DYNAMIC)
85e0ad4b33Sguenther _rthread_dl_lock(2);
86e0ad4b33Sguenther #endif
87dc989ac6Skurt /* update this thread's structure */
88fe38b55cSguenther tib->tib_tid = getthrid();
89f050dd83Sakfaew me->donesem.lock = _SPINLOCK_UNLOCKED;
90f050dd83Sakfaew me->flags_lock = _SPINLOCK_UNLOCKED;
91dc989ac6Skurt
92dc989ac6Skurt /* reinit the thread list */
93dc989ac6Skurt LIST_INIT(&_thread_list);
94cd0b4b49Sguenther LIST_INSERT_HEAD(&_thread_list, me, threads);
95f050dd83Sakfaew _thread_lock = _SPINLOCK_UNLOCKED;
96d049d58eSguenther
97d049d58eSguenther /* single threaded now */
98d049d58eSguenther __isthreaded = 0;
99c85623dfStedu _post_threaded = 0; /* notyet... */
100dc989ac6Skurt }
101b8ec2dbdSguenther #ifndef NO_PIC
102e0ad4b33Sguenther else if (_DYNAMIC)
103e0ad4b33Sguenther _rthread_dl_lock(1);
104e0ad4b33Sguenther #endif
105dc989ac6Skurt return newid;
106dc989ac6Skurt }
107dc989ac6Skurt
108dc989ac6Skurt pid_t
_thread_fork(void)109514a545fSguenther _thread_fork(void)
110dc989ac6Skurt {
111fe38b55cSguenther return _dofork(&fork);
112dc989ac6Skurt }
113dc989ac6Skurt
114dc989ac6Skurt pid_t
_thread_vfork(void)115fe38b55cSguenther _thread_vfork(void)
116dc989ac6Skurt {
117fe38b55cSguenther return _dofork(&vfork);
118dc989ac6Skurt }
119