xref: /freebsd/sys/compat/linux/linux_emul.c (revision e8b8b834b4bc8960f553e50589329e5c3b6d7fe5)
1ad2056f2SAlexander Leidinger /*-
2ad2056f2SAlexander Leidinger  * Copyright (c) 2006 Roman Divacky
3ad2056f2SAlexander Leidinger  * All rights reserved.
4ad2056f2SAlexander Leidinger  *
5ad2056f2SAlexander Leidinger  * Redistribution and use in source and binary forms, with or without
6ad2056f2SAlexander Leidinger  * modification, are permitted provided that the following conditions
7ad2056f2SAlexander Leidinger  * are met:
8ad2056f2SAlexander Leidinger  * 1. Redistributions of source code must retain the above copyright
9ad2056f2SAlexander Leidinger  *    notice, this list of conditions and the following disclaimer
10ad2056f2SAlexander Leidinger  *    in this position and unchanged.
11ad2056f2SAlexander Leidinger  * 2. Redistributions in binary form must reproduce the above copyright
12ad2056f2SAlexander Leidinger  *    notice, this list of conditions and the following disclaimer in the
13ad2056f2SAlexander Leidinger  *    documentation and/or other materials provided with the distribution.
14ad2056f2SAlexander Leidinger  * 3. The name of the author may not be used to endorse or promote products
15ad2056f2SAlexander Leidinger  *    derived from this software without specific prior written permission
16ad2056f2SAlexander Leidinger  *
17ad2056f2SAlexander Leidinger  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18ad2056f2SAlexander Leidinger  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19ad2056f2SAlexander Leidinger  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20ad2056f2SAlexander Leidinger  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21ad2056f2SAlexander Leidinger  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22ad2056f2SAlexander Leidinger  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23ad2056f2SAlexander Leidinger  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24ad2056f2SAlexander Leidinger  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25ad2056f2SAlexander Leidinger  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26ad2056f2SAlexander Leidinger  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27ad2056f2SAlexander Leidinger  */
28ad2056f2SAlexander Leidinger 
29ad2056f2SAlexander Leidinger #include <sys/cdefs.h>
30ad2056f2SAlexander Leidinger __FBSDID("$FreeBSD$");
31ad2056f2SAlexander Leidinger 
32ad2056f2SAlexander Leidinger #include "opt_compat.h"
33ad2056f2SAlexander Leidinger 
34ad2056f2SAlexander Leidinger #include <sys/param.h>
35ad2056f2SAlexander Leidinger #include <sys/systm.h>
36ad2056f2SAlexander Leidinger #include <sys/imgact.h>
37b4bb5154SKonstantin Belousov #include <sys/kernel.h>
38ad2056f2SAlexander Leidinger #include <sys/lock.h>
39ad2056f2SAlexander Leidinger #include <sys/malloc.h>
40ad2056f2SAlexander Leidinger #include <sys/mutex.h>
41ad2056f2SAlexander Leidinger #include <sys/sx.h>
42ad2056f2SAlexander Leidinger #include <sys/proc.h>
43ad2056f2SAlexander Leidinger #include <sys/syscallsubr.h>
44ad2056f2SAlexander Leidinger #include <sys/sysproto.h>
45ad2056f2SAlexander Leidinger #include <sys/unistd.h>
46ad2056f2SAlexander Leidinger 
47ad2056f2SAlexander Leidinger #include <compat/linux/linux_emul.h>
48ad2056f2SAlexander Leidinger #include <compat/linux/linux_futex.h>
49ad2056f2SAlexander Leidinger 
50ad2056f2SAlexander Leidinger #ifdef COMPAT_LINUX32
51ad2056f2SAlexander Leidinger #include <machine/../linux32/linux.h>
52ad2056f2SAlexander Leidinger #include <machine/../linux32/linux32_proto.h>
53ad2056f2SAlexander Leidinger #else
54ad2056f2SAlexander Leidinger #include <machine/../linux/linux.h>
55ad2056f2SAlexander Leidinger #include <machine/../linux/linux_proto.h>
56ad2056f2SAlexander Leidinger #endif
57ad2056f2SAlexander Leidinger 
58ad2056f2SAlexander Leidinger struct sx emul_shared_lock;
59ad2056f2SAlexander Leidinger struct sx emul_lock;
60ad2056f2SAlexander Leidinger 
61ad2056f2SAlexander Leidinger /* this returns locked reference to the emuldata entry (if found) */
62ad2056f2SAlexander Leidinger struct linux_emuldata *
63ad2056f2SAlexander Leidinger em_find(struct proc *p, int locked)
64ad2056f2SAlexander Leidinger {
65ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
66ad2056f2SAlexander Leidinger 
671c65504cSAlexander Leidinger 	if (locked == EMUL_DOLOCK)
68ad2056f2SAlexander Leidinger 		EMUL_LOCK(&emul_lock);
69ad2056f2SAlexander Leidinger 
70ad2056f2SAlexander Leidinger 	em = p->p_emuldata;
71ad2056f2SAlexander Leidinger 
721c65504cSAlexander Leidinger 	if (em == NULL && locked == EMUL_DOLOCK)
73ad2056f2SAlexander Leidinger 		EMUL_UNLOCK(&emul_lock);
74ad2056f2SAlexander Leidinger 
75ad2056f2SAlexander Leidinger 	return (em);
76ad2056f2SAlexander Leidinger }
77ad2056f2SAlexander Leidinger 
78ad2056f2SAlexander Leidinger int
79ad2056f2SAlexander Leidinger linux_proc_init(struct thread *td, pid_t child, int flags)
80ad2056f2SAlexander Leidinger {
81ad2056f2SAlexander Leidinger 	struct linux_emuldata *em, *p_em;
82ad2056f2SAlexander Leidinger 	struct proc *p;
83ad2056f2SAlexander Leidinger 
84ad2056f2SAlexander Leidinger 	if (child != 0) {
85ad2056f2SAlexander Leidinger 		/* non-exec call */
865342db08SSuleiman Souhlal 		em = malloc(sizeof *em, M_LINUX, M_WAITOK | M_ZERO);
87ad2056f2SAlexander Leidinger 		em->pid = child;
88955d762aSAlexander Leidinger 		em->pdeath_signal = 0;
89292a85f4SKonstantin Belousov 		if (flags & CLONE_THREAD) {
90ad2056f2SAlexander Leidinger 			/* handled later in the code */
91ad2056f2SAlexander Leidinger 		} else {
92ad2056f2SAlexander Leidinger 			struct linux_emuldata_shared *s;
93ad2056f2SAlexander Leidinger 
945342db08SSuleiman Souhlal 			s = malloc(sizeof *s, M_LINUX, M_WAITOK | M_ZERO);
95ad2056f2SAlexander Leidinger 			s->refs = 1;
96ad2056f2SAlexander Leidinger 			s->group_pid = child;
97ad2056f2SAlexander Leidinger 
98ad2056f2SAlexander Leidinger 			LIST_INIT(&s->threads);
99d071f504SAlexander Leidinger 			em->shared = s;
100ad2056f2SAlexander Leidinger 		}
101ad2056f2SAlexander Leidinger 	} else {
102ad2056f2SAlexander Leidinger 		/* lookup the old one */
1031c65504cSAlexander Leidinger 		em = em_find(td->td_proc, EMUL_DOLOCK);
104ad2056f2SAlexander Leidinger 		KASSERT(em != NULL, ("proc_init: emuldata not found in exec case.\n"));
105ad2056f2SAlexander Leidinger 	}
106ad2056f2SAlexander Leidinger 
107ad2056f2SAlexander Leidinger 	em->child_clear_tid = NULL;
108ad2056f2SAlexander Leidinger 	em->child_set_tid = NULL;
109ad2056f2SAlexander Leidinger 
1100eef2f8aSAlexander Leidinger 	/*
111a628609eSAlexander Leidinger 	 * allocate the shared struct only in clone()/fork cases in the case
112a628609eSAlexander Leidinger 	 * of clone() td = calling proc and child = pid of the newly created
113a628609eSAlexander Leidinger 	 * proc
114ad2056f2SAlexander Leidinger 	 */
115ad2056f2SAlexander Leidinger 	if (child != 0) {
116292a85f4SKonstantin Belousov 		if (flags & CLONE_THREAD) {
117ad2056f2SAlexander Leidinger 			/* lookup the parent */
11825954d74SKonstantin Belousov 			/*
11925954d74SKonstantin Belousov 			 * we dont have to lock the p_em because
12025954d74SKonstantin Belousov 			 * its waiting for us in linux_clone so
12125954d74SKonstantin Belousov 			 * there is no chance of it changing the
12225954d74SKonstantin Belousov 			 * p_em->shared address
12325954d74SKonstantin Belousov 			 */
12425954d74SKonstantin Belousov 			p_em = em_find(td->td_proc, EMUL_DONTLOCK);
125292a85f4SKonstantin Belousov 			KASSERT(p_em != NULL, ("proc_init: parent emuldata not found for CLONE_THREAD\n"));
126ad2056f2SAlexander Leidinger 			em->shared = p_em->shared;
12725954d74SKonstantin Belousov 			EMUL_SHARED_WLOCK(&emul_shared_lock);
128ad2056f2SAlexander Leidinger 			em->shared->refs++;
129291081ceSAlexander Leidinger 			EMUL_SHARED_WUNLOCK(&emul_shared_lock);
130ad2056f2SAlexander Leidinger 		} else {
131a628609eSAlexander Leidinger 			/*
132a628609eSAlexander Leidinger 			 * handled earlier to avoid malloc(M_WAITOK) with
133a628609eSAlexander Leidinger 			 * rwlock held
134a628609eSAlexander Leidinger 			 */
135ad2056f2SAlexander Leidinger 		}
136ad2056f2SAlexander Leidinger 	}
137ad2056f2SAlexander Leidinger 	if (child != 0) {
138ad2056f2SAlexander Leidinger 		EMUL_SHARED_WLOCK(&emul_shared_lock);
139ad2056f2SAlexander Leidinger 		LIST_INSERT_HEAD(&em->shared->threads, em, threads);
140ad2056f2SAlexander Leidinger 		EMUL_SHARED_WUNLOCK(&emul_shared_lock);
141ad2056f2SAlexander Leidinger 
142ad2056f2SAlexander Leidinger 		p = pfind(child);
143d071f504SAlexander Leidinger 		KASSERT(p != NULL, ("process not found in proc_init\n"));
144d071f504SAlexander Leidinger 		p->p_emuldata = em;
1458618fd85SAlexander Leidinger 		PROC_UNLOCK(p);
146ad2056f2SAlexander Leidinger 	} else
147ad2056f2SAlexander Leidinger 		EMUL_UNLOCK(&emul_lock);
148ad2056f2SAlexander Leidinger 
149ad2056f2SAlexander Leidinger 	return (0);
150ad2056f2SAlexander Leidinger }
151ad2056f2SAlexander Leidinger 
152ad2056f2SAlexander Leidinger void
153ad2056f2SAlexander Leidinger linux_proc_exit(void *arg __unused, struct proc *p)
154ad2056f2SAlexander Leidinger {
155ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
156ad2056f2SAlexander Leidinger 	int error;
157ad2056f2SAlexander Leidinger 	struct thread *td = FIRST_THREAD_IN_PROC(p);
158ad2056f2SAlexander Leidinger 	int *child_clear_tid;
159955d762aSAlexander Leidinger 	struct proc *q, *nq;
160ad2056f2SAlexander Leidinger 
161ad2056f2SAlexander Leidinger 	if (__predict_true(p->p_sysent != &elf_linux_sysvec))
162ad2056f2SAlexander Leidinger 		return;
163ad2056f2SAlexander Leidinger 
164ad2056f2SAlexander Leidinger 	/* find the emuldata */
1651c65504cSAlexander Leidinger 	em = em_find(p, EMUL_DOLOCK);
166ad2056f2SAlexander Leidinger 
167ad2056f2SAlexander Leidinger 	KASSERT(em != NULL, ("proc_exit: emuldata not found.\n"));
168ad2056f2SAlexander Leidinger 
16925954d74SKonstantin Belousov 	/* reparent all procs that are not a thread leader to initproc */
17025954d74SKonstantin Belousov 	if (em->shared->group_pid != p->p_pid) {
171e8b8b834SAlexander Leidinger 		child_clear_tid = em->child_clear_tid;
172e8b8b834SAlexander Leidinger 		EMUL_UNLOCK(&emul_lock);
17325954d74SKonstantin Belousov 		sx_xlock(&proctree_lock);
17425954d74SKonstantin Belousov 		wakeup(initproc);
17525954d74SKonstantin Belousov 		PROC_LOCK(p);
17625954d74SKonstantin Belousov 		proc_reparent(p, initproc);
17725954d74SKonstantin Belousov 		p->p_sigparent = SIGCHLD;
17825954d74SKonstantin Belousov 		PROC_UNLOCK(p);
17925954d74SKonstantin Belousov 		sx_xunlock(&proctree_lock);
180e8b8b834SAlexander Leidinger 	} else {
181ad2056f2SAlexander Leidinger 		child_clear_tid = em->child_clear_tid;
182ad2056f2SAlexander Leidinger 		EMUL_UNLOCK(&emul_lock);
183e8b8b834SAlexander Leidinger 	}
184ad2056f2SAlexander Leidinger 
185ad2056f2SAlexander Leidinger 	EMUL_SHARED_WLOCK(&emul_shared_lock);
186ad2056f2SAlexander Leidinger 	LIST_REMOVE(em, threads);
187ad2056f2SAlexander Leidinger 
188ad2056f2SAlexander Leidinger 	em->shared->refs--;
189ad2056f2SAlexander Leidinger 	if (em->shared->refs == 0)
1905342db08SSuleiman Souhlal 		free(em->shared, M_LINUX);
191ad2056f2SAlexander Leidinger 	EMUL_SHARED_WUNLOCK(&emul_shared_lock);
192ad2056f2SAlexander Leidinger 
193ad2056f2SAlexander Leidinger 	if (child_clear_tid != NULL) {
194ad2056f2SAlexander Leidinger 		struct linux_sys_futex_args cup;
195ad2056f2SAlexander Leidinger 		int null = 0;
196ad2056f2SAlexander Leidinger 
197ad2056f2SAlexander Leidinger 		error = copyout(&null, child_clear_tid, sizeof(null));
19828638377SAlexander Leidinger 		if (error) {
19928638377SAlexander Leidinger 			free(em, M_LINUX);
200ad2056f2SAlexander Leidinger 			return;
20128638377SAlexander Leidinger 		}
202ad2056f2SAlexander Leidinger 
203ad2056f2SAlexander Leidinger 		/* futexes stuff */
204ad2056f2SAlexander Leidinger 		cup.uaddr = child_clear_tid;
205ad2056f2SAlexander Leidinger 		cup.op = LINUX_FUTEX_WAKE;
206ad2056f2SAlexander Leidinger 		cup.val = 0x7fffffff;	/* Awake everyone */
207ad2056f2SAlexander Leidinger 		cup.timeout = NULL;
208ad2056f2SAlexander Leidinger 		cup.uaddr2 = NULL;
209ad2056f2SAlexander Leidinger 		cup.val3 = 0;
210ad2056f2SAlexander Leidinger 		error = linux_sys_futex(FIRST_THREAD_IN_PROC(p), &cup);
2110eef2f8aSAlexander Leidinger 		/*
212a628609eSAlexander Leidinger 		 * this cannot happen at the moment and if this happens it
213a628609eSAlexander Leidinger 		 * probably mean there is a userspace bug
214ad2056f2SAlexander Leidinger 		 */
215ad2056f2SAlexander Leidinger 		if (error)
216ad2056f2SAlexander Leidinger 			printf(LMSG("futex stuff in proc_exit failed.\n"));
217ad2056f2SAlexander Leidinger 	}
218ad2056f2SAlexander Leidinger 
219ad2056f2SAlexander Leidinger 	/* clean the stuff up */
2205342db08SSuleiman Souhlal 	free(em, M_LINUX);
221955d762aSAlexander Leidinger 
222955d762aSAlexander Leidinger 	/* this is a little weird but rewritten from exit1() */
223955d762aSAlexander Leidinger 	sx_xlock(&proctree_lock);
224955d762aSAlexander Leidinger 	q = LIST_FIRST(&p->p_children);
225955d762aSAlexander Leidinger 	for (; q != NULL; q = nq) {
226955d762aSAlexander Leidinger 		nq = LIST_NEXT(q, p_sibling);
227955d762aSAlexander Leidinger 		if (q->p_flag & P_WEXIT)
228955d762aSAlexander Leidinger 			continue;
229955d762aSAlexander Leidinger 		if (__predict_false(q->p_sysent != &elf_linux_sysvec))
230955d762aSAlexander Leidinger 			continue;
2311c65504cSAlexander Leidinger 		em = em_find(q, EMUL_DOLOCK);
232955d762aSAlexander Leidinger 		KASSERT(em != NULL, ("linux_reparent: emuldata not found: %i\n", q->p_pid));
233955d762aSAlexander Leidinger 		if (em->pdeath_signal != 0) {
234955d762aSAlexander Leidinger 			PROC_LOCK(q);
235955d762aSAlexander Leidinger 			psignal(q, em->pdeath_signal);
236955d762aSAlexander Leidinger 			PROC_UNLOCK(q);
237955d762aSAlexander Leidinger 		}
238955d762aSAlexander Leidinger 		EMUL_UNLOCK(&emul_lock);
239955d762aSAlexander Leidinger 	}
240955d762aSAlexander Leidinger 	sx_xunlock(&proctree_lock);
241ad2056f2SAlexander Leidinger }
242ad2056f2SAlexander Leidinger 
2430eef2f8aSAlexander Leidinger /*
2440eef2f8aSAlexander Leidinger  * This is used in a case of transition from FreeBSD binary execing to linux binary
245ad2056f2SAlexander Leidinger  * in this case we create linux emuldata proc entry with the pid of the currently running
246ad2056f2SAlexander Leidinger  * process.
247ad2056f2SAlexander Leidinger  */
248a628609eSAlexander Leidinger void
249a628609eSAlexander Leidinger linux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp)
250ad2056f2SAlexander Leidinger {
251ad2056f2SAlexander Leidinger 	if (__predict_false(imgp->sysent == &elf_linux_sysvec
252ad2056f2SAlexander Leidinger 	    && p->p_sysent != &elf_linux_sysvec))
253ad2056f2SAlexander Leidinger 		linux_proc_init(FIRST_THREAD_IN_PROC(p), p->p_pid, 0);
254ad2056f2SAlexander Leidinger 	if (__predict_false(imgp->sysent != &elf_linux_sysvec
255ad2056f2SAlexander Leidinger 	    && p->p_sysent == &elf_linux_sysvec)) {
256ad2056f2SAlexander Leidinger 		struct linux_emuldata *em;
257ad2056f2SAlexander Leidinger 
25825954d74SKonstantin Belousov 		/*
25925954d74SKonstantin Belousov 		 * XXX:There's a race because here we assign p->p_emuldata NULL
26025954d74SKonstantin Belousov 		 * but the process is still counted as linux one for a short
26125954d74SKonstantin Belousov  		 * time so some other process might reference it and try to
26225954d74SKonstantin Belousov  		 * access its p->p_emuldata and panicing on a NULL reference.
26325954d74SKonstantin Belousov 		 */
26425954d74SKonstantin Belousov 		em = em_find(p, EMUL_DONTLOCK);
265ad2056f2SAlexander Leidinger 
266ad2056f2SAlexander Leidinger 		KASSERT(em != NULL, ("proc_exec: emuldata not found.\n"));
267ad2056f2SAlexander Leidinger 
268ad2056f2SAlexander Leidinger 		EMUL_SHARED_WLOCK(&emul_shared_lock);
269ad2056f2SAlexander Leidinger 		LIST_REMOVE(em, threads);
270ad2056f2SAlexander Leidinger 
271ad2056f2SAlexander Leidinger 		PROC_LOCK(p);
272ad2056f2SAlexander Leidinger 		p->p_emuldata = NULL;
273ad2056f2SAlexander Leidinger 		PROC_UNLOCK(p);
274ad2056f2SAlexander Leidinger 
275ad2056f2SAlexander Leidinger 		em->shared->refs--;
276ad2056f2SAlexander Leidinger 		if (em->shared->refs == 0)
277c67e0cc9SSuleiman Souhlal 			free(em->shared, M_LINUX);
278ad2056f2SAlexander Leidinger 		EMUL_SHARED_WUNLOCK(&emul_shared_lock);
279ad2056f2SAlexander Leidinger 
280c67e0cc9SSuleiman Souhlal 		free(em, M_LINUX);
281ad2056f2SAlexander Leidinger 	}
282ad2056f2SAlexander Leidinger }
283ad2056f2SAlexander Leidinger 
284ad2056f2SAlexander Leidinger void
285ad2056f2SAlexander Leidinger linux_schedtail(void *arg __unused, struct proc *p)
286ad2056f2SAlexander Leidinger {
287ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
288ad2056f2SAlexander Leidinger 	int error = 0;
289ad2056f2SAlexander Leidinger 	int *child_set_tid;
290ad2056f2SAlexander Leidinger 
291955d762aSAlexander Leidinger 	if (__predict_true(p->p_sysent != &elf_linux_sysvec))
292ad2056f2SAlexander Leidinger 		return;
293ad2056f2SAlexander Leidinger 
294ad2056f2SAlexander Leidinger 	/* find the emuldata */
2951c65504cSAlexander Leidinger 	em = em_find(p, EMUL_DOLOCK);
296ad2056f2SAlexander Leidinger 
29725954d74SKonstantin Belousov 	KASSERT(em != NULL, ("linux_schedtail: emuldata not found.\n"));
298ad2056f2SAlexander Leidinger 	child_set_tid = em->child_set_tid;
299ad2056f2SAlexander Leidinger 	EMUL_UNLOCK(&emul_lock);
300ad2056f2SAlexander Leidinger 
301ad2056f2SAlexander Leidinger 	if (child_set_tid != NULL)
302a628609eSAlexander Leidinger 		error = copyout(&p->p_pid, (int *)child_set_tid,
303a628609eSAlexander Leidinger 		    sizeof(p->p_pid));
304ad2056f2SAlexander Leidinger 
305ad2056f2SAlexander Leidinger 	return;
306ad2056f2SAlexander Leidinger }
307ad2056f2SAlexander Leidinger 
308ad2056f2SAlexander Leidinger int
309ad2056f2SAlexander Leidinger linux_set_tid_address(struct thread *td, struct linux_set_tid_address_args *args)
310ad2056f2SAlexander Leidinger {
311ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
312ad2056f2SAlexander Leidinger 
313ad2056f2SAlexander Leidinger #ifdef DEBUG
314ad2056f2SAlexander Leidinger 	if (ldebug(set_tid_address))
315ad2056f2SAlexander Leidinger 		printf(ARGS(set_tid_address, "%p"), args->tidptr);
316ad2056f2SAlexander Leidinger #endif
317ad2056f2SAlexander Leidinger 
318ad2056f2SAlexander Leidinger 	/* find the emuldata */
3191c65504cSAlexander Leidinger 	em = em_find(td->td_proc, EMUL_DOLOCK);
320ad2056f2SAlexander Leidinger 
321ad2056f2SAlexander Leidinger 	KASSERT(em != NULL, ("set_tid_address: emuldata not found.\n"));
322ad2056f2SAlexander Leidinger 
323ad2056f2SAlexander Leidinger 	em->child_clear_tid = args->tidptr;
324ad2056f2SAlexander Leidinger 	td->td_retval[0] = td->td_proc->p_pid;
325ad2056f2SAlexander Leidinger 
326ad2056f2SAlexander Leidinger 	EMUL_UNLOCK(&emul_lock);
327ad2056f2SAlexander Leidinger 	return 0;
328ad2056f2SAlexander Leidinger }
329