xref: /freebsd/sys/compat/linux/linux_emul.c (revision bb63fdde6dbfd6d953b1c7547237dfcfae8d9364)
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;
89b1121623SDmitry Chagin 		em->used_requeue = 0;
904732e446SRoman Divacky 		em->robust_futexes = NULL;
91a4e3bad7SJung-uk Kim 		if (flags & LINUX_CLONE_THREAD) {
92ad2056f2SAlexander Leidinger 			/* handled later in the code */
93ad2056f2SAlexander Leidinger 		} else {
94ad2056f2SAlexander Leidinger 			struct linux_emuldata_shared *s;
95ad2056f2SAlexander Leidinger 
965342db08SSuleiman Souhlal 			s = malloc(sizeof *s, M_LINUX, M_WAITOK | M_ZERO);
97ad2056f2SAlexander Leidinger 			s->refs = 1;
98ad2056f2SAlexander Leidinger 			s->group_pid = child;
99ad2056f2SAlexander Leidinger 
100ad2056f2SAlexander Leidinger 			LIST_INIT(&s->threads);
101d071f504SAlexander Leidinger 			em->shared = s;
102ad2056f2SAlexander Leidinger 		}
103ad2056f2SAlexander Leidinger 	} else {
104ad2056f2SAlexander Leidinger 		/* lookup the old one */
1051c65504cSAlexander Leidinger 		em = em_find(td->td_proc, EMUL_DOLOCK);
106ad2056f2SAlexander Leidinger 		KASSERT(em != NULL, ("proc_init: emuldata not found in exec case.\n"));
107ad2056f2SAlexander Leidinger 	}
108ad2056f2SAlexander Leidinger 
109ad2056f2SAlexander Leidinger 	em->child_clear_tid = NULL;
110ad2056f2SAlexander Leidinger 	em->child_set_tid = NULL;
111ad2056f2SAlexander Leidinger 
1120eef2f8aSAlexander Leidinger 	/*
113a628609eSAlexander Leidinger 	 * allocate the shared struct only in clone()/fork cases in the case
114a628609eSAlexander Leidinger 	 * of clone() td = calling proc and child = pid of the newly created
115a628609eSAlexander Leidinger 	 * proc
116ad2056f2SAlexander Leidinger 	 */
117ad2056f2SAlexander Leidinger 	if (child != 0) {
118a4e3bad7SJung-uk Kim 		if (flags & LINUX_CLONE_THREAD) {
119ad2056f2SAlexander Leidinger 			/* lookup the parent */
12025954d74SKonstantin Belousov 			/*
12125954d74SKonstantin Belousov 			 * we dont have to lock the p_em because
12225954d74SKonstantin Belousov 			 * its waiting for us in linux_clone so
12325954d74SKonstantin Belousov 			 * there is no chance of it changing the
12425954d74SKonstantin Belousov 			 * p_em->shared address
12525954d74SKonstantin Belousov 			 */
12625954d74SKonstantin Belousov 			p_em = em_find(td->td_proc, EMUL_DONTLOCK);
127292a85f4SKonstantin Belousov 			KASSERT(p_em != NULL, ("proc_init: parent emuldata not found for CLONE_THREAD\n"));
128ad2056f2SAlexander Leidinger 			em->shared = p_em->shared;
12925954d74SKonstantin Belousov 			EMUL_SHARED_WLOCK(&emul_shared_lock);
130ad2056f2SAlexander Leidinger 			em->shared->refs++;
131291081ceSAlexander Leidinger 			EMUL_SHARED_WUNLOCK(&emul_shared_lock);
132ad2056f2SAlexander Leidinger 		} else {
133a628609eSAlexander Leidinger 			/*
134a628609eSAlexander Leidinger 			 * handled earlier to avoid malloc(M_WAITOK) with
135a628609eSAlexander Leidinger 			 * rwlock held
136a628609eSAlexander Leidinger 			 */
137ad2056f2SAlexander Leidinger 		}
138ad2056f2SAlexander Leidinger 	}
139ad2056f2SAlexander Leidinger 	if (child != 0) {
140ad2056f2SAlexander Leidinger 		EMUL_SHARED_WLOCK(&emul_shared_lock);
141ad2056f2SAlexander Leidinger 		LIST_INSERT_HEAD(&em->shared->threads, em, threads);
142ad2056f2SAlexander Leidinger 		EMUL_SHARED_WUNLOCK(&emul_shared_lock);
143ad2056f2SAlexander Leidinger 
144ad2056f2SAlexander Leidinger 		p = pfind(child);
145d071f504SAlexander Leidinger 		KASSERT(p != NULL, ("process not found in proc_init\n"));
146d071f504SAlexander Leidinger 		p->p_emuldata = em;
1478618fd85SAlexander Leidinger 		PROC_UNLOCK(p);
148ad2056f2SAlexander Leidinger 	} else
149ad2056f2SAlexander Leidinger 		EMUL_UNLOCK(&emul_lock);
150ad2056f2SAlexander Leidinger 
151ad2056f2SAlexander Leidinger 	return (0);
152ad2056f2SAlexander Leidinger }
153ad2056f2SAlexander Leidinger 
154ad2056f2SAlexander Leidinger void
155ad2056f2SAlexander Leidinger linux_proc_exit(void *arg __unused, struct proc *p)
156ad2056f2SAlexander Leidinger {
157ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
158*bb63fddeSAlexander Leidinger 	int error, shared_flags, shared_xstat;
159ad2056f2SAlexander Leidinger 	struct thread *td = FIRST_THREAD_IN_PROC(p);
160ad2056f2SAlexander Leidinger 	int *child_clear_tid;
161955d762aSAlexander Leidinger 	struct proc *q, *nq;
162ad2056f2SAlexander Leidinger 
163ad2056f2SAlexander Leidinger 	if (__predict_true(p->p_sysent != &elf_linux_sysvec))
164ad2056f2SAlexander Leidinger 		return;
165ad2056f2SAlexander Leidinger 
1664732e446SRoman Divacky 	release_futexes(p);
1674732e446SRoman Divacky 
168ad2056f2SAlexander Leidinger 	/* find the emuldata */
1691c65504cSAlexander Leidinger 	em = em_find(p, EMUL_DOLOCK);
170ad2056f2SAlexander Leidinger 
171ad2056f2SAlexander Leidinger 	KASSERT(em != NULL, ("proc_exit: emuldata not found.\n"));
172ad2056f2SAlexander Leidinger 
17325954d74SKonstantin Belousov 	/* reparent all procs that are not a thread leader to initproc */
17425954d74SKonstantin Belousov 	if (em->shared->group_pid != p->p_pid) {
175e8b8b834SAlexander Leidinger 		child_clear_tid = em->child_clear_tid;
176e8b8b834SAlexander Leidinger 		EMUL_UNLOCK(&emul_lock);
17725954d74SKonstantin Belousov 		sx_xlock(&proctree_lock);
17825954d74SKonstantin Belousov 		wakeup(initproc);
17925954d74SKonstantin Belousov 		PROC_LOCK(p);
18025954d74SKonstantin Belousov 		proc_reparent(p, initproc);
18125954d74SKonstantin Belousov 		p->p_sigparent = SIGCHLD;
18225954d74SKonstantin Belousov 		PROC_UNLOCK(p);
18325954d74SKonstantin Belousov 		sx_xunlock(&proctree_lock);
184e8b8b834SAlexander Leidinger 	} else {
185ad2056f2SAlexander Leidinger 		child_clear_tid = em->child_clear_tid;
186ad2056f2SAlexander Leidinger 		EMUL_UNLOCK(&emul_lock);
187e8b8b834SAlexander Leidinger 	}
188ad2056f2SAlexander Leidinger 
189ad2056f2SAlexander Leidinger 	EMUL_SHARED_WLOCK(&emul_shared_lock);
190*bb63fddeSAlexander Leidinger 	shared_flags = em->shared->flags;
191*bb63fddeSAlexander Leidinger 	shared_xstat = em->shared->xstat;
192ad2056f2SAlexander Leidinger 	LIST_REMOVE(em, threads);
193ad2056f2SAlexander Leidinger 
194ad2056f2SAlexander Leidinger 	em->shared->refs--;
1951a26db0aSAlexander Leidinger 	if (em->shared->refs == 0) {
1961a26db0aSAlexander Leidinger 		EMUL_SHARED_WUNLOCK(&emul_shared_lock);
1975342db08SSuleiman Souhlal 		free(em->shared, M_LINUX);
1981a26db0aSAlexander Leidinger 	} else
199ad2056f2SAlexander Leidinger 		EMUL_SHARED_WUNLOCK(&emul_shared_lock);
200ad2056f2SAlexander Leidinger 
201*bb63fddeSAlexander Leidinger 	if ((shared_flags & EMUL_SHARED_HASXSTAT) != 0) {
202*bb63fddeSAlexander Leidinger 		PROC_LOCK(p);
203*bb63fddeSAlexander Leidinger 		p->p_xstat = shared_xstat;
204*bb63fddeSAlexander Leidinger 		PROC_UNLOCK(p);
205*bb63fddeSAlexander Leidinger 	}
206*bb63fddeSAlexander Leidinger 
207ad2056f2SAlexander Leidinger 	if (child_clear_tid != NULL) {
208ad2056f2SAlexander Leidinger 		struct linux_sys_futex_args cup;
209ad2056f2SAlexander Leidinger 		int null = 0;
210ad2056f2SAlexander Leidinger 
211ad2056f2SAlexander Leidinger 		error = copyout(&null, child_clear_tid, sizeof(null));
21228638377SAlexander Leidinger 		if (error) {
21328638377SAlexander Leidinger 			free(em, M_LINUX);
214ad2056f2SAlexander Leidinger 			return;
21528638377SAlexander Leidinger 		}
216ad2056f2SAlexander Leidinger 
217ad2056f2SAlexander Leidinger 		/* futexes stuff */
218ad2056f2SAlexander Leidinger 		cup.uaddr = child_clear_tid;
219ad2056f2SAlexander Leidinger 		cup.op = LINUX_FUTEX_WAKE;
220ad2056f2SAlexander Leidinger 		cup.val = 0x7fffffff;	/* Awake everyone */
221ad2056f2SAlexander Leidinger 		cup.timeout = NULL;
222ad2056f2SAlexander Leidinger 		cup.uaddr2 = NULL;
223ad2056f2SAlexander Leidinger 		cup.val3 = 0;
224ad2056f2SAlexander Leidinger 		error = linux_sys_futex(FIRST_THREAD_IN_PROC(p), &cup);
2250eef2f8aSAlexander Leidinger 		/*
226a628609eSAlexander Leidinger 		 * this cannot happen at the moment and if this happens it
227802e08a3SAlexander Leidinger 		 * probably means there is a user space bug
228ad2056f2SAlexander Leidinger 		 */
229ad2056f2SAlexander Leidinger 		if (error)
230ad2056f2SAlexander Leidinger 			printf(LMSG("futex stuff in proc_exit failed.\n"));
231ad2056f2SAlexander Leidinger 	}
232ad2056f2SAlexander Leidinger 
233ad2056f2SAlexander Leidinger 	/* clean the stuff up */
2345342db08SSuleiman Souhlal 	free(em, M_LINUX);
235955d762aSAlexander Leidinger 
236955d762aSAlexander Leidinger 	/* this is a little weird but rewritten from exit1() */
237955d762aSAlexander Leidinger 	sx_xlock(&proctree_lock);
238955d762aSAlexander Leidinger 	q = LIST_FIRST(&p->p_children);
239955d762aSAlexander Leidinger 	for (; q != NULL; q = nq) {
240955d762aSAlexander Leidinger 		nq = LIST_NEXT(q, p_sibling);
241955d762aSAlexander Leidinger 		if (q->p_flag & P_WEXIT)
242955d762aSAlexander Leidinger 			continue;
243955d762aSAlexander Leidinger 		if (__predict_false(q->p_sysent != &elf_linux_sysvec))
244955d762aSAlexander Leidinger 			continue;
2451c65504cSAlexander Leidinger 		em = em_find(q, EMUL_DOLOCK);
246955d762aSAlexander Leidinger 		KASSERT(em != NULL, ("linux_reparent: emuldata not found: %i\n", q->p_pid));
247955d762aSAlexander Leidinger 		PROC_LOCK(q);
24817b9edd3SKonstantin Belousov 		if ((q->p_flag & P_WEXIT) == 0 && em->pdeath_signal != 0) {
249955d762aSAlexander Leidinger 			psignal(q, em->pdeath_signal);
250955d762aSAlexander Leidinger 		}
25117b9edd3SKonstantin Belousov 		PROC_UNLOCK(q);
252955d762aSAlexander Leidinger 		EMUL_UNLOCK(&emul_lock);
253955d762aSAlexander Leidinger 	}
254955d762aSAlexander Leidinger 	sx_xunlock(&proctree_lock);
255ad2056f2SAlexander Leidinger }
256ad2056f2SAlexander Leidinger 
2570eef2f8aSAlexander Leidinger /*
2580eef2f8aSAlexander Leidinger  * This is used in a case of transition from FreeBSD binary execing to linux binary
259ad2056f2SAlexander Leidinger  * in this case we create linux emuldata proc entry with the pid of the currently running
260ad2056f2SAlexander Leidinger  * process.
261ad2056f2SAlexander Leidinger  */
262a628609eSAlexander Leidinger void
263a628609eSAlexander Leidinger linux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp)
264ad2056f2SAlexander Leidinger {
265ad2056f2SAlexander Leidinger 	if (__predict_false(imgp->sysent == &elf_linux_sysvec
266ad2056f2SAlexander Leidinger 	    && p->p_sysent != &elf_linux_sysvec))
267ad2056f2SAlexander Leidinger 		linux_proc_init(FIRST_THREAD_IN_PROC(p), p->p_pid, 0);
268*bb63fddeSAlexander Leidinger 	if (__predict_false(p->p_sysent == &elf_linux_sysvec))
269*bb63fddeSAlexander Leidinger 		/* Kill threads regardless of imgp->sysent value */
270*bb63fddeSAlexander Leidinger 		linux_kill_threads(FIRST_THREAD_IN_PROC(p), SIGKILL);
271ad2056f2SAlexander Leidinger 	if (__predict_false(imgp->sysent != &elf_linux_sysvec
272ad2056f2SAlexander Leidinger 	    && p->p_sysent == &elf_linux_sysvec)) {
273ad2056f2SAlexander Leidinger 		struct linux_emuldata *em;
274ad2056f2SAlexander Leidinger 
27525954d74SKonstantin Belousov 		/*
27625954d74SKonstantin Belousov 		 * XXX:There's a race because here we assign p->p_emuldata NULL
27725954d74SKonstantin Belousov 		 * but the process is still counted as linux one for a short
27825954d74SKonstantin Belousov  		 * time so some other process might reference it and try to
27925954d74SKonstantin Belousov  		 * access its p->p_emuldata and panicing on a NULL reference.
28025954d74SKonstantin Belousov 		 */
28125954d74SKonstantin Belousov 		em = em_find(p, EMUL_DONTLOCK);
282ad2056f2SAlexander Leidinger 
283ad2056f2SAlexander Leidinger 		KASSERT(em != NULL, ("proc_exec: emuldata not found.\n"));
284ad2056f2SAlexander Leidinger 
285ad2056f2SAlexander Leidinger 		EMUL_SHARED_WLOCK(&emul_shared_lock);
286ad2056f2SAlexander Leidinger 		LIST_REMOVE(em, threads);
287ad2056f2SAlexander Leidinger 
288ad2056f2SAlexander Leidinger 		PROC_LOCK(p);
289ad2056f2SAlexander Leidinger 		p->p_emuldata = NULL;
290ad2056f2SAlexander Leidinger 		PROC_UNLOCK(p);
291ad2056f2SAlexander Leidinger 
292ad2056f2SAlexander Leidinger 		em->shared->refs--;
2931a26db0aSAlexander Leidinger 		if (em->shared->refs == 0) {
2941a26db0aSAlexander Leidinger 			EMUL_SHARED_WUNLOCK(&emul_shared_lock);
295c67e0cc9SSuleiman Souhlal 			free(em->shared, M_LINUX);
2961a26db0aSAlexander Leidinger 		} else
297ad2056f2SAlexander Leidinger 			EMUL_SHARED_WUNLOCK(&emul_shared_lock);
298ad2056f2SAlexander Leidinger 
299c67e0cc9SSuleiman Souhlal 		free(em, M_LINUX);
300ad2056f2SAlexander Leidinger 	}
301ad2056f2SAlexander Leidinger }
302ad2056f2SAlexander Leidinger 
303ad2056f2SAlexander Leidinger void
304ad2056f2SAlexander Leidinger linux_schedtail(void *arg __unused, struct proc *p)
305ad2056f2SAlexander Leidinger {
306ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
307ad2056f2SAlexander Leidinger 	int error = 0;
308ad2056f2SAlexander Leidinger 	int *child_set_tid;
309ad2056f2SAlexander Leidinger 
310955d762aSAlexander Leidinger 	if (__predict_true(p->p_sysent != &elf_linux_sysvec))
311ad2056f2SAlexander Leidinger 		return;
312ad2056f2SAlexander Leidinger 
313ad2056f2SAlexander Leidinger 	/* find the emuldata */
3141c65504cSAlexander Leidinger 	em = em_find(p, EMUL_DOLOCK);
315ad2056f2SAlexander Leidinger 
31625954d74SKonstantin Belousov 	KASSERT(em != NULL, ("linux_schedtail: emuldata not found.\n"));
317ad2056f2SAlexander Leidinger 	child_set_tid = em->child_set_tid;
318ad2056f2SAlexander Leidinger 	EMUL_UNLOCK(&emul_lock);
319ad2056f2SAlexander Leidinger 
320ad2056f2SAlexander Leidinger 	if (child_set_tid != NULL)
321a628609eSAlexander Leidinger 		error = copyout(&p->p_pid, (int *)child_set_tid,
322a628609eSAlexander Leidinger 		    sizeof(p->p_pid));
323ad2056f2SAlexander Leidinger 
324ad2056f2SAlexander Leidinger 	return;
325ad2056f2SAlexander Leidinger }
326ad2056f2SAlexander Leidinger 
327ad2056f2SAlexander Leidinger int
328ad2056f2SAlexander Leidinger linux_set_tid_address(struct thread *td, struct linux_set_tid_address_args *args)
329ad2056f2SAlexander Leidinger {
330ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
331ad2056f2SAlexander Leidinger 
332ad2056f2SAlexander Leidinger #ifdef DEBUG
333ad2056f2SAlexander Leidinger 	if (ldebug(set_tid_address))
334ad2056f2SAlexander Leidinger 		printf(ARGS(set_tid_address, "%p"), args->tidptr);
335ad2056f2SAlexander Leidinger #endif
336ad2056f2SAlexander Leidinger 
337ad2056f2SAlexander Leidinger 	/* find the emuldata */
3381c65504cSAlexander Leidinger 	em = em_find(td->td_proc, EMUL_DOLOCK);
339ad2056f2SAlexander Leidinger 
340ad2056f2SAlexander Leidinger 	KASSERT(em != NULL, ("set_tid_address: emuldata not found.\n"));
341ad2056f2SAlexander Leidinger 
342ad2056f2SAlexander Leidinger 	em->child_clear_tid = args->tidptr;
343ad2056f2SAlexander Leidinger 	td->td_retval[0] = td->td_proc->p_pid;
344ad2056f2SAlexander Leidinger 
345ad2056f2SAlexander Leidinger 	EMUL_UNLOCK(&emul_lock);
346ad2056f2SAlexander Leidinger 	return 0;
347ad2056f2SAlexander Leidinger }
348*bb63fddeSAlexander Leidinger 
349*bb63fddeSAlexander Leidinger void
350*bb63fddeSAlexander Leidinger linux_kill_threads(struct thread *td, int sig)
351*bb63fddeSAlexander Leidinger {
352*bb63fddeSAlexander Leidinger 	struct linux_emuldata *em, *td_em, *tmp_em;
353*bb63fddeSAlexander Leidinger 	struct proc *sp;
354*bb63fddeSAlexander Leidinger 
355*bb63fddeSAlexander Leidinger 	td_em = em_find(td->td_proc, EMUL_DONTLOCK);
356*bb63fddeSAlexander Leidinger 
357*bb63fddeSAlexander Leidinger 	KASSERT(td_em != NULL, ("linux_kill_threads: emuldata not found.\n"));
358*bb63fddeSAlexander Leidinger 
359*bb63fddeSAlexander Leidinger 	EMUL_SHARED_RLOCK(&emul_shared_lock);
360*bb63fddeSAlexander Leidinger 	LIST_FOREACH_SAFE(em, &td_em->shared->threads, threads, tmp_em) {
361*bb63fddeSAlexander Leidinger 		if (em->pid == td_em->pid)
362*bb63fddeSAlexander Leidinger 			continue;
363*bb63fddeSAlexander Leidinger 
364*bb63fddeSAlexander Leidinger 		sp = pfind(em->pid);
365*bb63fddeSAlexander Leidinger 		if ((sp->p_flag & P_WEXIT) == 0)
366*bb63fddeSAlexander Leidinger 			psignal(sp, sig);
367*bb63fddeSAlexander Leidinger 		PROC_UNLOCK(sp);
368*bb63fddeSAlexander Leidinger #ifdef DEBUG
369*bb63fddeSAlexander Leidinger 		printf(LMSG("linux_kill_threads: kill PID %d\n"), em->pid);
370*bb63fddeSAlexander Leidinger #endif
371*bb63fddeSAlexander Leidinger 	}
372*bb63fddeSAlexander Leidinger 	EMUL_SHARED_RUNLOCK(&emul_shared_lock);
373*bb63fddeSAlexander Leidinger }
374