xref: /freebsd/sys/compat/linux/linux_emul.c (revision 81338031c4839351c7f27c04c1e4924751319a88)
1ad2056f2SAlexander Leidinger /*-
2ad2056f2SAlexander Leidinger  * Copyright (c) 2006 Roman Divacky
3*81338031SDmitry Chagin  * Copyright (c) 2013 Dmitry Chagin
4ad2056f2SAlexander Leidinger  * All rights reserved.
5ad2056f2SAlexander Leidinger  *
6ad2056f2SAlexander Leidinger  * Redistribution and use in source and binary forms, with or without
7ad2056f2SAlexander Leidinger  * modification, are permitted provided that the following conditions
8ad2056f2SAlexander Leidinger  * are met:
9ad2056f2SAlexander Leidinger  * 1. Redistributions of source code must retain the above copyright
10ad2056f2SAlexander Leidinger  *    notice, this list of conditions and the following disclaimer
11ad2056f2SAlexander Leidinger  *    in this position and unchanged.
12ad2056f2SAlexander Leidinger  * 2. Redistributions in binary form must reproduce the above copyright
13ad2056f2SAlexander Leidinger  *    notice, this list of conditions and the following disclaimer in the
14ad2056f2SAlexander Leidinger  *    documentation and/or other materials provided with the distribution.
15ad2056f2SAlexander Leidinger  * 3. The name of the author may not be used to endorse or promote products
16ad2056f2SAlexander Leidinger  *    derived from this software without specific prior written permission
17ad2056f2SAlexander Leidinger  *
18ad2056f2SAlexander Leidinger  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19ad2056f2SAlexander Leidinger  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20ad2056f2SAlexander Leidinger  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21ad2056f2SAlexander Leidinger  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22ad2056f2SAlexander Leidinger  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23ad2056f2SAlexander Leidinger  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24ad2056f2SAlexander Leidinger  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25ad2056f2SAlexander Leidinger  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26ad2056f2SAlexander Leidinger  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27ad2056f2SAlexander Leidinger  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28ad2056f2SAlexander Leidinger  */
29ad2056f2SAlexander Leidinger 
30ad2056f2SAlexander Leidinger #include <sys/cdefs.h>
31ad2056f2SAlexander Leidinger __FBSDID("$FreeBSD$");
32ad2056f2SAlexander Leidinger 
33ad2056f2SAlexander Leidinger #include "opt_compat.h"
34ad2056f2SAlexander Leidinger 
35ad2056f2SAlexander Leidinger #include <sys/param.h>
36ad2056f2SAlexander Leidinger #include <sys/systm.h>
37ad2056f2SAlexander Leidinger #include <sys/imgact.h>
38b4bb5154SKonstantin Belousov #include <sys/kernel.h>
39*81338031SDmitry Chagin #include <sys/ktr.h>
40ad2056f2SAlexander Leidinger #include <sys/lock.h>
41ad2056f2SAlexander Leidinger #include <sys/malloc.h>
42ad2056f2SAlexander Leidinger #include <sys/mutex.h>
4319e252baSAlexander Leidinger #include <sys/sdt.h>
44ad2056f2SAlexander Leidinger #include <sys/sx.h>
45ad2056f2SAlexander Leidinger #include <sys/proc.h>
46ad2056f2SAlexander Leidinger #include <sys/syscallsubr.h>
4795353459SDimitry Andric #include <sys/sysent.h>
48ad2056f2SAlexander Leidinger #include <sys/sysproto.h>
49ad2056f2SAlexander Leidinger #include <sys/unistd.h>
50ad2056f2SAlexander Leidinger 
51ad2056f2SAlexander Leidinger #ifdef COMPAT_LINUX32
52ad2056f2SAlexander Leidinger #include <machine/../linux32/linux.h>
53ad2056f2SAlexander Leidinger #include <machine/../linux32/linux32_proto.h>
54ad2056f2SAlexander Leidinger #else
55ad2056f2SAlexander Leidinger #include <machine/../linux/linux.h>
56ad2056f2SAlexander Leidinger #include <machine/../linux/linux_proto.h>
57ad2056f2SAlexander Leidinger #endif
58ad2056f2SAlexander Leidinger 
5919e252baSAlexander Leidinger #include <compat/linux/linux_dtrace.h>
604732e446SRoman Divacky #include <compat/linux/linux_emul.h>
614732e446SRoman Divacky #include <compat/linux/linux_futex.h>
62d825ce0aSJohn Baldwin #include <compat/linux/linux_misc.h>
63*81338031SDmitry Chagin #include <compat/linux/linux_util.h>
644732e446SRoman Divacky 
6519e252baSAlexander Leidinger /**
6619e252baSAlexander Leidinger  * Special DTrace provider for the linuxulator.
6719e252baSAlexander Leidinger  *
6819e252baSAlexander Leidinger  * In this file we define the provider for the entire linuxulator. All
6919e252baSAlexander Leidinger  * modules (= files of the linuxulator) use it.
7019e252baSAlexander Leidinger  *
7119e252baSAlexander Leidinger  * We define a different name depending on the emulated bitsize, see
7219e252baSAlexander Leidinger  * ../../<ARCH>/linux{,32}/linux.h, e.g.:
7319e252baSAlexander Leidinger  *      native bitsize          = linuxulator
7419e252baSAlexander Leidinger  *      amd64, 32bit emulation  = linuxulator32
7519e252baSAlexander Leidinger  */
7619e252baSAlexander Leidinger LIN_SDT_PROVIDER_DEFINE(LINUX_DTRACE);
7719e252baSAlexander Leidinger 
7819e252baSAlexander Leidinger /**
7919e252baSAlexander Leidinger  * DTrace probes in this module.
8019e252baSAlexander Leidinger  */
81*81338031SDmitry Chagin LIN_SDT_PROBE_DEFINE1(emul, em_find, entry, "struct thread *");
8219e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, em_find, return);
83*81338031SDmitry Chagin LIN_SDT_PROBE_DEFINE3(emul, proc_init, entry, "struct thread *",
84*81338031SDmitry Chagin     "struct thread *", "int");
8519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, proc_init, create_thread);
8619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, proc_init, fork);
8719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, proc_init, exec);
8819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, proc_init, return);
8919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(emul, proc_exit, entry, "struct proc *");
90*81338031SDmitry Chagin LIN_SDT_PROBE_DEFINE1(emul, linux_thread_detach, entry, "struct thread *");
91*81338031SDmitry Chagin LIN_SDT_PROBE_DEFINE0(emul, linux_thread_detach, futex_failed);
92*81338031SDmitry Chagin LIN_SDT_PROBE_DEFINE1(emul, linux_thread_detach, child_clear_tid_error, "int");
93*81338031SDmitry Chagin LIN_SDT_PROBE_DEFINE0(emul, linux_thread_detach, return);
9419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(emul, proc_exec, entry, "struct proc *",
9519e252baSAlexander Leidinger     "struct image_params *");
9619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, proc_exec, return);
9719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, linux_schedtail, entry);
9819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(emul, linux_schedtail, copyout_error, "int");
9919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, linux_schedtail, return);
10019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(emul, linux_set_tid_address, entry, "int *");
10119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, linux_set_tid_address, return);
10219e252baSAlexander Leidinger 
103*81338031SDmitry Chagin /*
104*81338031SDmitry Chagin  * This returns reference to the emuldata entry (if found)
105*81338031SDmitry Chagin  *
106*81338031SDmitry Chagin  * Hold PROC_LOCK when referencing emuldata from other threads.
107*81338031SDmitry Chagin  */
108ad2056f2SAlexander Leidinger struct linux_emuldata *
109*81338031SDmitry Chagin em_find(struct thread *td)
110ad2056f2SAlexander Leidinger {
111ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
112ad2056f2SAlexander Leidinger 
113*81338031SDmitry Chagin 	LIN_SDT_PROBE1(emul, em_find, entry, td);
11419e252baSAlexander Leidinger 
115*81338031SDmitry Chagin 	em = td->td_emuldata;
116ad2056f2SAlexander Leidinger 
11719e252baSAlexander Leidinger 	LIN_SDT_PROBE1(emul, em_find, return, em);
118*81338031SDmitry Chagin 
119ad2056f2SAlexander Leidinger 	return (em);
120ad2056f2SAlexander Leidinger }
121ad2056f2SAlexander Leidinger 
122*81338031SDmitry Chagin void
123*81338031SDmitry Chagin linux_proc_init(struct thread *td, struct thread *newtd, int flags)
124ad2056f2SAlexander Leidinger {
125*81338031SDmitry Chagin 	struct linux_emuldata *em;
126ad2056f2SAlexander Leidinger 
127*81338031SDmitry Chagin 	LIN_SDT_PROBE3(emul, proc_init, entry, td, newtd, flags);
12819e252baSAlexander Leidinger 
129*81338031SDmitry Chagin 	if (newtd != NULL) {
130*81338031SDmitry Chagin 		/* non-exec call */
131*81338031SDmitry Chagin 		em = malloc(sizeof(*em), M_TEMP, M_WAITOK | M_ZERO);
132955d762aSAlexander Leidinger 		em->pdeath_signal = 0;
133d14cc07dSDmitry Chagin 		em->flags = 0;
1344732e446SRoman Divacky 		em->robust_futexes = NULL;
135a4e3bad7SJung-uk Kim 		if (flags & LINUX_CLONE_THREAD) {
13619e252baSAlexander Leidinger 			LIN_SDT_PROBE0(emul, proc_init, create_thread);
137ad2056f2SAlexander Leidinger 
138*81338031SDmitry Chagin 			em->em_tid = newtd->td_tid;
139*81338031SDmitry Chagin 		} else {
14019e252baSAlexander Leidinger 			LIN_SDT_PROBE0(emul, proc_init, fork);
14119e252baSAlexander Leidinger 
142*81338031SDmitry Chagin 			em->em_tid = newtd->td_proc->p_pid;
143ad2056f2SAlexander Leidinger 		}
144*81338031SDmitry Chagin 		newtd->td_emuldata = em;
145ad2056f2SAlexander Leidinger 	} else {
14619e252baSAlexander Leidinger 		/* exec */
14719e252baSAlexander Leidinger 		LIN_SDT_PROBE0(emul, proc_init, exec);
14819e252baSAlexander Leidinger 
149ad2056f2SAlexander Leidinger 		/* lookup the old one */
150*81338031SDmitry Chagin 		em = em_find(td);
151ad2056f2SAlexander Leidinger 		KASSERT(em != NULL, ("proc_init: emuldata not found in exec case.\n"));
152*81338031SDmitry Chagin 
153*81338031SDmitry Chagin 		em->em_tid = td->td_proc->p_pid;
154ad2056f2SAlexander Leidinger 	}
155ad2056f2SAlexander Leidinger 
156ad2056f2SAlexander Leidinger 	em->child_clear_tid = NULL;
157ad2056f2SAlexander Leidinger 	em->child_set_tid = NULL;
158ad2056f2SAlexander Leidinger 
15919e252baSAlexander Leidinger 	LIN_SDT_PROBE0(emul, proc_init, return);
160ad2056f2SAlexander Leidinger }
161ad2056f2SAlexander Leidinger 
162ad2056f2SAlexander Leidinger void
163ad2056f2SAlexander Leidinger linux_proc_exit(void *arg __unused, struct proc *p)
164ad2056f2SAlexander Leidinger {
165*81338031SDmitry Chagin 	struct thread *td = curthread;
166ad2056f2SAlexander Leidinger 
167*81338031SDmitry Chagin 	if (__predict_false(SV_CURPROC_ABI() != SV_ABI_LINUX)) {
16819e252baSAlexander Leidinger 		LIN_SDT_PROBE1(emul, proc_exit, entry, p);
169*81338031SDmitry Chagin 		(p->p_sysent->sv_thread_detach)(td);
170*81338031SDmitry Chagin 	}
171e8b8b834SAlexander Leidinger }
172ad2056f2SAlexander Leidinger 
173*81338031SDmitry Chagin int
174*81338031SDmitry Chagin linux_common_execve(struct thread *td, struct image_args *eargs)
175*81338031SDmitry Chagin {
176*81338031SDmitry Chagin 	struct linux_emuldata *em;
177*81338031SDmitry Chagin 	struct proc *p;
178*81338031SDmitry Chagin 	int error;
179ad2056f2SAlexander Leidinger 
180*81338031SDmitry Chagin 	p = td->td_proc;
181ad2056f2SAlexander Leidinger 
182*81338031SDmitry Chagin 	/*
183*81338031SDmitry Chagin 	 * Unlike FreeBSD abort all other threads before
184*81338031SDmitry Chagin 	 * proceeding exec.
185*81338031SDmitry Chagin 	 */
186*81338031SDmitry Chagin 	PROC_LOCK(p);
187*81338031SDmitry Chagin 	/* See exit1() comments. */
188*81338031SDmitry Chagin 	thread_suspend_check(0);
189*81338031SDmitry Chagin 	while (p->p_flag & P_HADTHREADS) {
190*81338031SDmitry Chagin 		if (!thread_single(p, SINGLE_EXIT))
191*81338031SDmitry Chagin 			break;
192*81338031SDmitry Chagin 		thread_suspend_check(0);
193*81338031SDmitry Chagin 	}
194*81338031SDmitry Chagin 	PROC_UNLOCK(p);
195*81338031SDmitry Chagin 
196*81338031SDmitry Chagin 	error = kern_execve(td, eargs, NULL);
197*81338031SDmitry Chagin 	if (error != 0)
198*81338031SDmitry Chagin 		return (error);
199*81338031SDmitry Chagin 
200*81338031SDmitry Chagin 	/*
201*81338031SDmitry Chagin 	 * In a case of transition from Linux binary execing to
202*81338031SDmitry Chagin 	 * FreeBSD binary we destroy linux emuldata thread entry.
203*81338031SDmitry Chagin 	 */
204*81338031SDmitry Chagin 	if (SV_CURPROC_ABI() != SV_ABI_LINUX) {
205*81338031SDmitry Chagin 		PROC_LOCK(p);
206*81338031SDmitry Chagin 		em = em_find(td);
207*81338031SDmitry Chagin 		KASSERT(em != NULL, ("proc_exec: emuldata not found.\n"));
208*81338031SDmitry Chagin 		td->td_emuldata = NULL;
209*81338031SDmitry Chagin 		PROC_UNLOCK(p);
210*81338031SDmitry Chagin 
211*81338031SDmitry Chagin 		free(em, M_TEMP);
212*81338031SDmitry Chagin 	}
213*81338031SDmitry Chagin 	return (0);
214*81338031SDmitry Chagin }
215*81338031SDmitry Chagin 
216*81338031SDmitry Chagin void
217*81338031SDmitry Chagin linux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp)
218*81338031SDmitry Chagin {
219*81338031SDmitry Chagin 	struct thread *td = curthread;
220*81338031SDmitry Chagin 
221*81338031SDmitry Chagin 	/*
222*81338031SDmitry Chagin 	 * In a case of execing to linux binary we create linux
223*81338031SDmitry Chagin 	 * emuldata thread entry.
224*81338031SDmitry Chagin 	 */
225*81338031SDmitry Chagin 	if (__predict_false((imgp->sysent->sv_flags & SV_ABI_MASK) ==
226*81338031SDmitry Chagin 	    SV_ABI_LINUX)) {
227*81338031SDmitry Chagin 		LIN_SDT_PROBE2(emul, proc_exec, entry, p, imgp);
228*81338031SDmitry Chagin 		if (SV_PROC_ABI(p) == SV_ABI_LINUX)
229*81338031SDmitry Chagin 			linux_proc_init(td, NULL, 0);
230*81338031SDmitry Chagin 		else
231*81338031SDmitry Chagin 			linux_proc_init(td, td, 0);
232*81338031SDmitry Chagin 
233*81338031SDmitry Chagin 		LIN_SDT_PROBE0(emul, proc_exec, return);
234*81338031SDmitry Chagin 	}
235*81338031SDmitry Chagin }
236*81338031SDmitry Chagin 
237*81338031SDmitry Chagin void
238*81338031SDmitry Chagin linux_thread_detach(struct thread *td)
239*81338031SDmitry Chagin {
240*81338031SDmitry Chagin 	struct linux_sys_futex_args cup;
241*81338031SDmitry Chagin 	struct linux_emuldata *em;
242*81338031SDmitry Chagin 	int *child_clear_tid;
243*81338031SDmitry Chagin 	int null = 0;
244*81338031SDmitry Chagin 	int error;
245*81338031SDmitry Chagin 
246*81338031SDmitry Chagin 	LIN_SDT_PROBE1(emul, linux_thread_detach, entry, td);
247*81338031SDmitry Chagin 
248*81338031SDmitry Chagin 	em = em_find(td);
249*81338031SDmitry Chagin 	KASSERT(em != NULL, ("thread_detach: emuldata not found.\n"));
250*81338031SDmitry Chagin 
251*81338031SDmitry Chagin 	LINUX_CTR1(exit, "thread detach(%d)", em->em_tid);
252*81338031SDmitry Chagin 
253*81338031SDmitry Chagin 	release_futexes(td, em);
254*81338031SDmitry Chagin 
255*81338031SDmitry Chagin 	child_clear_tid = em->child_clear_tid;
256bb63fddeSAlexander Leidinger 
257ad2056f2SAlexander Leidinger 	if (child_clear_tid != NULL) {
258*81338031SDmitry Chagin 
259*81338031SDmitry Chagin 		LINUX_CTR2(exit, "thread detach(%d) %p",
260*81338031SDmitry Chagin 		    em->em_tid, child_clear_tid);
261ad2056f2SAlexander Leidinger 
262ad2056f2SAlexander Leidinger 		error = copyout(&null, child_clear_tid, sizeof(null));
26328638377SAlexander Leidinger 		if (error) {
264*81338031SDmitry Chagin 			LIN_SDT_PROBE1(emul, linux_thread_detach,
26519e252baSAlexander Leidinger 			    child_clear_tid_error, error);
26619e252baSAlexander Leidinger 
267*81338031SDmitry Chagin 			LIN_SDT_PROBE0(emul, linux_thread_detach, return);
268ad2056f2SAlexander Leidinger 			return;
26928638377SAlexander Leidinger 		}
270ad2056f2SAlexander Leidinger 
271ad2056f2SAlexander Leidinger 		cup.uaddr = child_clear_tid;
272ad2056f2SAlexander Leidinger 		cup.op = LINUX_FUTEX_WAKE;
273ad2056f2SAlexander Leidinger 		cup.val = 0x7fffffff;	/* Awake everyone */
274ad2056f2SAlexander Leidinger 		cup.timeout = NULL;
275ad2056f2SAlexander Leidinger 		cup.uaddr2 = NULL;
276ad2056f2SAlexander Leidinger 		cup.val3 = 0;
277*81338031SDmitry Chagin 		error = linux_sys_futex(td, &cup);
2780eef2f8aSAlexander Leidinger 		/*
279a628609eSAlexander Leidinger 		 * this cannot happen at the moment and if this happens it
280802e08a3SAlexander Leidinger 		 * probably means there is a user space bug
281ad2056f2SAlexander Leidinger 		 */
28219e252baSAlexander Leidinger 		if (error) {
283*81338031SDmitry Chagin 			LIN_SDT_PROBE0(emul, linux_thread_detach, futex_failed);
284*81338031SDmitry Chagin 			printf(LMSG("futex stuff in thread_detach failed.\n"));
285ad2056f2SAlexander Leidinger 		}
28619e252baSAlexander Leidinger 	}
287ad2056f2SAlexander Leidinger 
288*81338031SDmitry Chagin 	LIN_SDT_PROBE0(emul, linux_thread_detach, return);
289ad2056f2SAlexander Leidinger }
290ad2056f2SAlexander Leidinger 
291a628609eSAlexander Leidinger void
292*81338031SDmitry Chagin linux_thread_dtor(void *arg __unused, struct thread *td)
293ad2056f2SAlexander Leidinger {
294ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
295ad2056f2SAlexander Leidinger 
296*81338031SDmitry Chagin 	em = em_find(td);
297*81338031SDmitry Chagin 	if (em == NULL)
298*81338031SDmitry Chagin 		return;
299*81338031SDmitry Chagin 	td->td_emuldata = NULL;
300ad2056f2SAlexander Leidinger 
301*81338031SDmitry Chagin 	LINUX_CTR1(exit, "thread dtor(%d)", em->em_tid);
302ad2056f2SAlexander Leidinger 
303*81338031SDmitry Chagin 	free(em, M_TEMP);
304ad2056f2SAlexander Leidinger }
305ad2056f2SAlexander Leidinger 
306ad2056f2SAlexander Leidinger void
307e5d81ef1SDmitry Chagin linux_schedtail(struct thread *td)
308ad2056f2SAlexander Leidinger {
309ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
310e5d81ef1SDmitry Chagin 	struct proc *p;
311ad2056f2SAlexander Leidinger 	int error = 0;
312ad2056f2SAlexander Leidinger 	int *child_set_tid;
313ad2056f2SAlexander Leidinger 
314*81338031SDmitry Chagin 	LIN_SDT_PROBE1(emul, linux_schedtail, entry, td);
315*81338031SDmitry Chagin 
316e5d81ef1SDmitry Chagin 	p = td->td_proc;
317e5d81ef1SDmitry Chagin 
318*81338031SDmitry Chagin 	em = em_find(td);
31925954d74SKonstantin Belousov 	KASSERT(em != NULL, ("linux_schedtail: emuldata not found.\n"));
320ad2056f2SAlexander Leidinger 	child_set_tid = em->child_set_tid;
321ad2056f2SAlexander Leidinger 
32219e252baSAlexander Leidinger 	if (child_set_tid != NULL) {
323*81338031SDmitry Chagin 		error = copyout(&em->em_tid, (int *)child_set_tid,
324*81338031SDmitry Chagin 		    sizeof(em->em_tid));
325*81338031SDmitry Chagin 		LINUX_CTR4(clone, "schedtail(%d) %p stored %d error %d",
326*81338031SDmitry Chagin 		    td->td_tid, child_set_tid, em->em_tid, error);
327ad2056f2SAlexander Leidinger 
32819e252baSAlexander Leidinger 		if (error != 0) {
32919e252baSAlexander Leidinger 			LIN_SDT_PROBE1(emul, linux_schedtail, copyout_error,
33019e252baSAlexander Leidinger 			    error);
33119e252baSAlexander Leidinger 		}
332*81338031SDmitry Chagin 	} else
333*81338031SDmitry Chagin 		LINUX_CTR1(clone, "schedtail(%d)", em->em_tid);
33419e252baSAlexander Leidinger 
33519e252baSAlexander Leidinger 	LIN_SDT_PROBE0(emul, linux_schedtail, return);
336ad2056f2SAlexander Leidinger }
337ad2056f2SAlexander Leidinger 
338ad2056f2SAlexander Leidinger int
339ad2056f2SAlexander Leidinger linux_set_tid_address(struct thread *td, struct linux_set_tid_address_args *args)
340ad2056f2SAlexander Leidinger {
341ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
342ad2056f2SAlexander Leidinger 
34319e252baSAlexander Leidinger 	LIN_SDT_PROBE1(emul, linux_set_tid_address, entry, args->tidptr);
344ad2056f2SAlexander Leidinger 
345*81338031SDmitry Chagin 	em = em_find(td);
346ad2056f2SAlexander Leidinger 	KASSERT(em != NULL, ("set_tid_address: emuldata not found.\n"));
347ad2056f2SAlexander Leidinger 
348ad2056f2SAlexander Leidinger 	em->child_clear_tid = args->tidptr;
349ad2056f2SAlexander Leidinger 
350*81338031SDmitry Chagin 	td->td_retval[0] = em->em_tid;
351*81338031SDmitry Chagin 
352*81338031SDmitry Chagin 	LINUX_CTR3(set_tid_address, "tidptr(%d) %p, returns %d",
353*81338031SDmitry Chagin 	    em->em_tid, args->tidptr, td->td_retval[0]);
35419e252baSAlexander Leidinger 
35519e252baSAlexander Leidinger 	LIN_SDT_PROBE0(emul, linux_set_tid_address, return);
356*81338031SDmitry Chagin 	return (0);
357bb63fddeSAlexander Leidinger }
358