xref: /freebsd/sys/compat/linux/linux_emul.c (revision 4732e446fbed17b57193d849f254e1280ad8cfb5)
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 #ifdef COMPAT_LINUX32
48ad2056f2SAlexander Leidinger #include <machine/../linux32/linux.h>
49ad2056f2SAlexander Leidinger #include <machine/../linux32/linux32_proto.h>
50ad2056f2SAlexander Leidinger #else
51ad2056f2SAlexander Leidinger #include <machine/../linux/linux.h>
52ad2056f2SAlexander Leidinger #include <machine/../linux/linux_proto.h>
53ad2056f2SAlexander Leidinger #endif
54ad2056f2SAlexander Leidinger 
554732e446SRoman Divacky #include <compat/linux/linux_emul.h>
564732e446SRoman Divacky #include <compat/linux/linux_futex.h>
574732e446SRoman Divacky 
58ad2056f2SAlexander Leidinger struct sx	emul_shared_lock;
59357afa71SJung-uk Kim struct mtx	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;
894732e446SRoman Divacky 		em->robust_futexes = NULL;
90a4e3bad7SJung-uk Kim 		if (flags & LINUX_CLONE_THREAD) {
91ad2056f2SAlexander Leidinger 			/* handled later in the code */
92ad2056f2SAlexander Leidinger 		} else {
93ad2056f2SAlexander Leidinger 			struct linux_emuldata_shared *s;
94ad2056f2SAlexander Leidinger 
955342db08SSuleiman Souhlal 			s = malloc(sizeof *s, M_LINUX, M_WAITOK | M_ZERO);
96ad2056f2SAlexander Leidinger 			s->refs = 1;
97ad2056f2SAlexander Leidinger 			s->group_pid = child;
98ad2056f2SAlexander Leidinger 
99ad2056f2SAlexander Leidinger 			LIST_INIT(&s->threads);
100d071f504SAlexander Leidinger 			em->shared = s;
101ad2056f2SAlexander Leidinger 		}
102ad2056f2SAlexander Leidinger 	} else {
103ad2056f2SAlexander Leidinger 		/* lookup the old one */
1041c65504cSAlexander Leidinger 		em = em_find(td->td_proc, EMUL_DOLOCK);
105ad2056f2SAlexander Leidinger 		KASSERT(em != NULL, ("proc_init: emuldata not found in exec case.\n"));
106ad2056f2SAlexander Leidinger 	}
107ad2056f2SAlexander Leidinger 
108ad2056f2SAlexander Leidinger 	em->child_clear_tid = NULL;
109ad2056f2SAlexander Leidinger 	em->child_set_tid = NULL;
110ad2056f2SAlexander Leidinger 
1110eef2f8aSAlexander Leidinger 	/*
112a628609eSAlexander Leidinger 	 * allocate the shared struct only in clone()/fork cases in the case
113a628609eSAlexander Leidinger 	 * of clone() td = calling proc and child = pid of the newly created
114a628609eSAlexander Leidinger 	 * proc
115ad2056f2SAlexander Leidinger 	 */
116ad2056f2SAlexander Leidinger 	if (child != 0) {
117a4e3bad7SJung-uk Kim 		if (flags & LINUX_CLONE_THREAD) {
118ad2056f2SAlexander Leidinger 			/* lookup the parent */
11925954d74SKonstantin Belousov 			/*
12025954d74SKonstantin Belousov 			 * we dont have to lock the p_em because
12125954d74SKonstantin Belousov 			 * its waiting for us in linux_clone so
12225954d74SKonstantin Belousov 			 * there is no chance of it changing the
12325954d74SKonstantin Belousov 			 * p_em->shared address
12425954d74SKonstantin Belousov 			 */
12525954d74SKonstantin Belousov 			p_em = em_find(td->td_proc, EMUL_DONTLOCK);
126292a85f4SKonstantin Belousov 			KASSERT(p_em != NULL, ("proc_init: parent emuldata not found for CLONE_THREAD\n"));
127ad2056f2SAlexander Leidinger 			em->shared = p_em->shared;
12825954d74SKonstantin Belousov 			EMUL_SHARED_WLOCK(&emul_shared_lock);
129ad2056f2SAlexander Leidinger 			em->shared->refs++;
130291081ceSAlexander Leidinger 			EMUL_SHARED_WUNLOCK(&emul_shared_lock);
131ad2056f2SAlexander Leidinger 		} else {
132a628609eSAlexander Leidinger 			/*
133a628609eSAlexander Leidinger 			 * handled earlier to avoid malloc(M_WAITOK) with
134a628609eSAlexander Leidinger 			 * rwlock held
135a628609eSAlexander Leidinger 			 */
136ad2056f2SAlexander Leidinger 		}
137ad2056f2SAlexander Leidinger 	}
138ad2056f2SAlexander Leidinger 	if (child != 0) {
139ad2056f2SAlexander Leidinger 		EMUL_SHARED_WLOCK(&emul_shared_lock);
140ad2056f2SAlexander Leidinger 		LIST_INSERT_HEAD(&em->shared->threads, em, threads);
141ad2056f2SAlexander Leidinger 		EMUL_SHARED_WUNLOCK(&emul_shared_lock);
142ad2056f2SAlexander Leidinger 
143ad2056f2SAlexander Leidinger 		p = pfind(child);
144d071f504SAlexander Leidinger 		KASSERT(p != NULL, ("process not found in proc_init\n"));
145d071f504SAlexander Leidinger 		p->p_emuldata = em;
1468618fd85SAlexander Leidinger 		PROC_UNLOCK(p);
147ad2056f2SAlexander Leidinger 	} else
148ad2056f2SAlexander Leidinger 		EMUL_UNLOCK(&emul_lock);
149ad2056f2SAlexander Leidinger 
150ad2056f2SAlexander Leidinger 	return (0);
151ad2056f2SAlexander Leidinger }
152ad2056f2SAlexander Leidinger 
153ad2056f2SAlexander Leidinger void
154ad2056f2SAlexander Leidinger linux_proc_exit(void *arg __unused, struct proc *p)
155ad2056f2SAlexander Leidinger {
156ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
157ad2056f2SAlexander Leidinger 	int error;
158ad2056f2SAlexander Leidinger 	struct thread *td = FIRST_THREAD_IN_PROC(p);
159ad2056f2SAlexander Leidinger 	int *child_clear_tid;
160955d762aSAlexander Leidinger 	struct proc *q, *nq;
161ad2056f2SAlexander Leidinger 
162ad2056f2SAlexander Leidinger 	if (__predict_true(p->p_sysent != &elf_linux_sysvec))
163ad2056f2SAlexander Leidinger 		return;
164ad2056f2SAlexander Leidinger 
1654732e446SRoman Divacky 	release_futexes(p);
1664732e446SRoman Divacky 
167ad2056f2SAlexander Leidinger 	/* find the emuldata */
1681c65504cSAlexander Leidinger 	em = em_find(p, EMUL_DOLOCK);
169ad2056f2SAlexander Leidinger 
170ad2056f2SAlexander Leidinger 	KASSERT(em != NULL, ("proc_exit: emuldata not found.\n"));
171ad2056f2SAlexander Leidinger 
17225954d74SKonstantin Belousov 	/* reparent all procs that are not a thread leader to initproc */
17325954d74SKonstantin Belousov 	if (em->shared->group_pid != p->p_pid) {
174e8b8b834SAlexander Leidinger 		child_clear_tid = em->child_clear_tid;
175e8b8b834SAlexander Leidinger 		EMUL_UNLOCK(&emul_lock);
17625954d74SKonstantin Belousov 		sx_xlock(&proctree_lock);
17725954d74SKonstantin Belousov 		wakeup(initproc);
17825954d74SKonstantin Belousov 		PROC_LOCK(p);
17925954d74SKonstantin Belousov 		proc_reparent(p, initproc);
18025954d74SKonstantin Belousov 		p->p_sigparent = SIGCHLD;
18125954d74SKonstantin Belousov 		PROC_UNLOCK(p);
18225954d74SKonstantin Belousov 		sx_xunlock(&proctree_lock);
183e8b8b834SAlexander Leidinger 	} else {
184ad2056f2SAlexander Leidinger 		child_clear_tid = em->child_clear_tid;
185ad2056f2SAlexander Leidinger 		EMUL_UNLOCK(&emul_lock);
186e8b8b834SAlexander Leidinger 	}
187ad2056f2SAlexander Leidinger 
188ad2056f2SAlexander Leidinger 	EMUL_SHARED_WLOCK(&emul_shared_lock);
189ad2056f2SAlexander Leidinger 	LIST_REMOVE(em, threads);
190ad2056f2SAlexander Leidinger 
191ad2056f2SAlexander Leidinger 	em->shared->refs--;
1921a26db0aSAlexander Leidinger 	if (em->shared->refs == 0) {
1931a26db0aSAlexander Leidinger 		EMUL_SHARED_WUNLOCK(&emul_shared_lock);
1945342db08SSuleiman Souhlal 		free(em->shared, M_LINUX);
1951a26db0aSAlexander Leidinger 	} else
196ad2056f2SAlexander Leidinger 		EMUL_SHARED_WUNLOCK(&emul_shared_lock);
197ad2056f2SAlexander Leidinger 
198ad2056f2SAlexander Leidinger 	if (child_clear_tid != NULL) {
199ad2056f2SAlexander Leidinger 		struct linux_sys_futex_args cup;
200ad2056f2SAlexander Leidinger 		int null = 0;
201ad2056f2SAlexander Leidinger 
202ad2056f2SAlexander Leidinger 		error = copyout(&null, child_clear_tid, sizeof(null));
20328638377SAlexander Leidinger 		if (error) {
20428638377SAlexander Leidinger 			free(em, M_LINUX);
205ad2056f2SAlexander Leidinger 			return;
20628638377SAlexander Leidinger 		}
207ad2056f2SAlexander Leidinger 
208ad2056f2SAlexander Leidinger 		/* futexes stuff */
209ad2056f2SAlexander Leidinger 		cup.uaddr = child_clear_tid;
210ad2056f2SAlexander Leidinger 		cup.op = LINUX_FUTEX_WAKE;
211ad2056f2SAlexander Leidinger 		cup.val = 0x7fffffff;	/* Awake everyone */
212ad2056f2SAlexander Leidinger 		cup.timeout = NULL;
213ad2056f2SAlexander Leidinger 		cup.uaddr2 = NULL;
214ad2056f2SAlexander Leidinger 		cup.val3 = 0;
215ad2056f2SAlexander Leidinger 		error = linux_sys_futex(FIRST_THREAD_IN_PROC(p), &cup);
2160eef2f8aSAlexander Leidinger 		/*
217a628609eSAlexander Leidinger 		 * this cannot happen at the moment and if this happens it
218802e08a3SAlexander Leidinger 		 * probably means there is a user space bug
219ad2056f2SAlexander Leidinger 		 */
220ad2056f2SAlexander Leidinger 		if (error)
221ad2056f2SAlexander Leidinger 			printf(LMSG("futex stuff in proc_exit failed.\n"));
222ad2056f2SAlexander Leidinger 	}
223ad2056f2SAlexander Leidinger 
224ad2056f2SAlexander Leidinger 	/* clean the stuff up */
2255342db08SSuleiman Souhlal 	free(em, M_LINUX);
226955d762aSAlexander Leidinger 
227955d762aSAlexander Leidinger 	/* this is a little weird but rewritten from exit1() */
228955d762aSAlexander Leidinger 	sx_xlock(&proctree_lock);
229955d762aSAlexander Leidinger 	q = LIST_FIRST(&p->p_children);
230955d762aSAlexander Leidinger 	for (; q != NULL; q = nq) {
231955d762aSAlexander Leidinger 		nq = LIST_NEXT(q, p_sibling);
232955d762aSAlexander Leidinger 		if (q->p_flag & P_WEXIT)
233955d762aSAlexander Leidinger 			continue;
234955d762aSAlexander Leidinger 		if (__predict_false(q->p_sysent != &elf_linux_sysvec))
235955d762aSAlexander Leidinger 			continue;
2361c65504cSAlexander Leidinger 		em = em_find(q, EMUL_DOLOCK);
237955d762aSAlexander Leidinger 		KASSERT(em != NULL, ("linux_reparent: emuldata not found: %i\n", q->p_pid));
238955d762aSAlexander Leidinger 		if (em->pdeath_signal != 0) {
239955d762aSAlexander Leidinger 			PROC_LOCK(q);
240955d762aSAlexander Leidinger 			psignal(q, em->pdeath_signal);
241955d762aSAlexander Leidinger 			PROC_UNLOCK(q);
242955d762aSAlexander Leidinger 		}
243955d762aSAlexander Leidinger 		EMUL_UNLOCK(&emul_lock);
244955d762aSAlexander Leidinger 	}
245955d762aSAlexander Leidinger 	sx_xunlock(&proctree_lock);
246ad2056f2SAlexander Leidinger }
247ad2056f2SAlexander Leidinger 
2480eef2f8aSAlexander Leidinger /*
2490eef2f8aSAlexander Leidinger  * This is used in a case of transition from FreeBSD binary execing to linux binary
250ad2056f2SAlexander Leidinger  * in this case we create linux emuldata proc entry with the pid of the currently running
251ad2056f2SAlexander Leidinger  * process.
252ad2056f2SAlexander Leidinger  */
253a628609eSAlexander Leidinger void
254a628609eSAlexander Leidinger linux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp)
255ad2056f2SAlexander Leidinger {
256ad2056f2SAlexander Leidinger 	if (__predict_false(imgp->sysent == &elf_linux_sysvec
257ad2056f2SAlexander Leidinger 	    && p->p_sysent != &elf_linux_sysvec))
258ad2056f2SAlexander Leidinger 		linux_proc_init(FIRST_THREAD_IN_PROC(p), p->p_pid, 0);
259ad2056f2SAlexander Leidinger 	if (__predict_false(imgp->sysent != &elf_linux_sysvec
260ad2056f2SAlexander Leidinger 	    && p->p_sysent == &elf_linux_sysvec)) {
261ad2056f2SAlexander Leidinger 		struct linux_emuldata *em;
262ad2056f2SAlexander Leidinger 
26325954d74SKonstantin Belousov 		/*
26425954d74SKonstantin Belousov 		 * XXX:There's a race because here we assign p->p_emuldata NULL
26525954d74SKonstantin Belousov 		 * but the process is still counted as linux one for a short
26625954d74SKonstantin Belousov  		 * time so some other process might reference it and try to
26725954d74SKonstantin Belousov  		 * access its p->p_emuldata and panicing on a NULL reference.
26825954d74SKonstantin Belousov 		 */
26925954d74SKonstantin Belousov 		em = em_find(p, EMUL_DONTLOCK);
270ad2056f2SAlexander Leidinger 
271ad2056f2SAlexander Leidinger 		KASSERT(em != NULL, ("proc_exec: emuldata not found.\n"));
272ad2056f2SAlexander Leidinger 
273ad2056f2SAlexander Leidinger 		EMUL_SHARED_WLOCK(&emul_shared_lock);
274ad2056f2SAlexander Leidinger 		LIST_REMOVE(em, threads);
275ad2056f2SAlexander Leidinger 
276ad2056f2SAlexander Leidinger 		PROC_LOCK(p);
277ad2056f2SAlexander Leidinger 		p->p_emuldata = NULL;
278ad2056f2SAlexander Leidinger 		PROC_UNLOCK(p);
279ad2056f2SAlexander Leidinger 
280ad2056f2SAlexander Leidinger 		em->shared->refs--;
2811a26db0aSAlexander Leidinger 		if (em->shared->refs == 0) {
2821a26db0aSAlexander Leidinger 			EMUL_SHARED_WUNLOCK(&emul_shared_lock);
283c67e0cc9SSuleiman Souhlal 			free(em->shared, M_LINUX);
2841a26db0aSAlexander Leidinger 		} else
285ad2056f2SAlexander Leidinger 			EMUL_SHARED_WUNLOCK(&emul_shared_lock);
286ad2056f2SAlexander Leidinger 
287c67e0cc9SSuleiman Souhlal 		free(em, M_LINUX);
288ad2056f2SAlexander Leidinger 	}
289ad2056f2SAlexander Leidinger }
290ad2056f2SAlexander Leidinger 
291ad2056f2SAlexander Leidinger void
292ad2056f2SAlexander Leidinger linux_schedtail(void *arg __unused, struct proc *p)
293ad2056f2SAlexander Leidinger {
294ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
295ad2056f2SAlexander Leidinger 	int error = 0;
296ad2056f2SAlexander Leidinger 	int *child_set_tid;
297ad2056f2SAlexander Leidinger 
298955d762aSAlexander Leidinger 	if (__predict_true(p->p_sysent != &elf_linux_sysvec))
299ad2056f2SAlexander Leidinger 		return;
300ad2056f2SAlexander Leidinger 
301ad2056f2SAlexander Leidinger 	/* find the emuldata */
3021c65504cSAlexander Leidinger 	em = em_find(p, EMUL_DOLOCK);
303ad2056f2SAlexander Leidinger 
30425954d74SKonstantin Belousov 	KASSERT(em != NULL, ("linux_schedtail: emuldata not found.\n"));
305ad2056f2SAlexander Leidinger 	child_set_tid = em->child_set_tid;
306ad2056f2SAlexander Leidinger 	EMUL_UNLOCK(&emul_lock);
307ad2056f2SAlexander Leidinger 
308ad2056f2SAlexander Leidinger 	if (child_set_tid != NULL)
309a628609eSAlexander Leidinger 		error = copyout(&p->p_pid, (int *)child_set_tid,
310a628609eSAlexander Leidinger 		    sizeof(p->p_pid));
311ad2056f2SAlexander Leidinger 
312ad2056f2SAlexander Leidinger 	return;
313ad2056f2SAlexander Leidinger }
314ad2056f2SAlexander Leidinger 
315ad2056f2SAlexander Leidinger int
316ad2056f2SAlexander Leidinger linux_set_tid_address(struct thread *td, struct linux_set_tid_address_args *args)
317ad2056f2SAlexander Leidinger {
318ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
319ad2056f2SAlexander Leidinger 
320ad2056f2SAlexander Leidinger #ifdef DEBUG
321ad2056f2SAlexander Leidinger 	if (ldebug(set_tid_address))
322ad2056f2SAlexander Leidinger 		printf(ARGS(set_tid_address, "%p"), args->tidptr);
323ad2056f2SAlexander Leidinger #endif
324ad2056f2SAlexander Leidinger 
325ad2056f2SAlexander Leidinger 	/* find the emuldata */
3261c65504cSAlexander Leidinger 	em = em_find(td->td_proc, EMUL_DOLOCK);
327ad2056f2SAlexander Leidinger 
328ad2056f2SAlexander Leidinger 	KASSERT(em != NULL, ("set_tid_address: emuldata not found.\n"));
329ad2056f2SAlexander Leidinger 
330ad2056f2SAlexander Leidinger 	em->child_clear_tid = args->tidptr;
331ad2056f2SAlexander Leidinger 	td->td_retval[0] = td->td_proc->p_pid;
332ad2056f2SAlexander Leidinger 
333ad2056f2SAlexander Leidinger 	EMUL_UNLOCK(&emul_lock);
334ad2056f2SAlexander Leidinger 	return 0;
335ad2056f2SAlexander Leidinger }
336