1161304Snetchild/*- 2161304Snetchild * Copyright (c) 2006 Roman Divacky 3161304Snetchild * All rights reserved. 4161304Snetchild * 5161304Snetchild * Redistribution and use in source and binary forms, with or without 6161304Snetchild * modification, are permitted provided that the following conditions 7161304Snetchild * are met: 8161304Snetchild * 1. Redistributions of source code must retain the above copyright 9161304Snetchild * notice, this list of conditions and the following disclaimer 10161304Snetchild * in this position and unchanged. 11161304Snetchild * 2. Redistributions in binary form must reproduce the above copyright 12161304Snetchild * notice, this list of conditions and the following disclaimer in the 13161304Snetchild * documentation and/or other materials provided with the distribution. 14161304Snetchild * 3. The name of the author may not be used to endorse or promote products 15161304Snetchild * derived from this software without specific prior written permission 16161304Snetchild * 17161304Snetchild * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18161304Snetchild * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19161304Snetchild * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20161304Snetchild * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21161304Snetchild * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22161304Snetchild * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23161304Snetchild * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24161304Snetchild * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25161304Snetchild * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26161304Snetchild * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27161304Snetchild */ 28161304Snetchild 29161304Snetchild#include <sys/cdefs.h> 30161304Snetchild__FBSDID("$FreeBSD: releng/10.2/sys/compat/linux/linux_emul.c 246085 2013-01-29 18:41:30Z jhb $"); 31161304Snetchild 32161304Snetchild#include "opt_compat.h" 33235063Snetchild#include "opt_kdtrace.h" 34161304Snetchild 35161304Snetchild#include <sys/param.h> 36161304Snetchild#include <sys/systm.h> 37161304Snetchild#include <sys/imgact.h> 38166420Skib#include <sys/kernel.h> 39161304Snetchild#include <sys/lock.h> 40161304Snetchild#include <sys/malloc.h> 41161304Snetchild#include <sys/mutex.h> 42235063Snetchild#include <sys/sdt.h> 43161304Snetchild#include <sys/sx.h> 44161304Snetchild#include <sys/proc.h> 45161304Snetchild#include <sys/syscallsubr.h> 46215706Sdim#include <sys/sysent.h> 47161304Snetchild#include <sys/sysproto.h> 48161304Snetchild#include <sys/unistd.h> 49161304Snetchild 50161304Snetchild#ifdef COMPAT_LINUX32 51161304Snetchild#include <machine/../linux32/linux.h> 52161304Snetchild#include <machine/../linux32/linux32_proto.h> 53161304Snetchild#else 54161304Snetchild#include <machine/../linux/linux.h> 55161304Snetchild#include <machine/../linux/linux_proto.h> 56161304Snetchild#endif 57161304Snetchild 58235063Snetchild#include <compat/linux/linux_dtrace.h> 59178976Srdivacky#include <compat/linux/linux_emul.h> 60178976Srdivacky#include <compat/linux/linux_futex.h> 61246085Sjhb#include <compat/linux/linux_misc.h> 62178976Srdivacky 63235063Snetchild/** 64235063Snetchild * Special DTrace provider for the linuxulator. 65235063Snetchild * 66235063Snetchild * In this file we define the provider for the entire linuxulator. All 67235063Snetchild * modules (= files of the linuxulator) use it. 68235063Snetchild * 69235063Snetchild * We define a different name depending on the emulated bitsize, see 70235063Snetchild * ../../<ARCH>/linux{,32}/linux.h, e.g.: 71235063Snetchild * native bitsize = linuxulator 72235063Snetchild * amd64, 32bit emulation = linuxulator32 73235063Snetchild */ 74235063SnetchildLIN_SDT_PROVIDER_DEFINE(LINUX_DTRACE); 75235063Snetchild 76235063Snetchild/** 77235063Snetchild * Special DTrace module "locks", it covers some linuxulator internal 78235063Snetchild * locks. 79235063Snetchild */ 80235063SnetchildLIN_SDT_PROBE_DEFINE1(locks, emul_lock, locked, "struct mtx *"); 81235063SnetchildLIN_SDT_PROBE_DEFINE1(locks, emul_lock, unlock, "struct mtx *"); 82235063SnetchildLIN_SDT_PROBE_DEFINE1(locks, emul_shared_rlock, locked, "struct sx *"); 83235063SnetchildLIN_SDT_PROBE_DEFINE1(locks, emul_shared_rlock, unlock, "struct sx *"); 84235063SnetchildLIN_SDT_PROBE_DEFINE1(locks, emul_shared_wlock, locked, "struct sx *"); 85235063SnetchildLIN_SDT_PROBE_DEFINE1(locks, emul_shared_wlock, unlock, "struct sx *"); 86235063Snetchild 87235063Snetchild/** 88235063Snetchild * DTrace probes in this module. 89235063Snetchild */ 90235063SnetchildLIN_SDT_PROBE_DEFINE2(emul, em_find, entry, "struct proc *", "int"); 91235063SnetchildLIN_SDT_PROBE_DEFINE0(emul, em_find, return); 92235063SnetchildLIN_SDT_PROBE_DEFINE3(emul, proc_init, entry, "struct thread *", "pid_t", 93235063Snetchild "int"); 94235063SnetchildLIN_SDT_PROBE_DEFINE0(emul, proc_init, create_thread); 95235063SnetchildLIN_SDT_PROBE_DEFINE0(emul, proc_init, fork); 96235063SnetchildLIN_SDT_PROBE_DEFINE0(emul, proc_init, exec); 97235063SnetchildLIN_SDT_PROBE_DEFINE0(emul, proc_init, return); 98235063SnetchildLIN_SDT_PROBE_DEFINE1(emul, proc_exit, entry, "struct proc *"); 99235063SnetchildLIN_SDT_PROBE_DEFINE0(emul, proc_exit, futex_failed); 100235063SnetchildLIN_SDT_PROBE_DEFINE3(emul, proc_exit, reparent, "pid_t", "pid_t", 101235063Snetchild "struct proc *"); 102235063SnetchildLIN_SDT_PROBE_DEFINE1(emul, proc_exit, child_clear_tid_error, "int"); 103235063SnetchildLIN_SDT_PROBE_DEFINE0(emul, proc_exit, return); 104235063SnetchildLIN_SDT_PROBE_DEFINE2(emul, proc_exec, entry, "struct proc *", 105235063Snetchild "struct image_params *"); 106235063SnetchildLIN_SDT_PROBE_DEFINE0(emul, proc_exec, return); 107235063SnetchildLIN_SDT_PROBE_DEFINE0(emul, linux_schedtail, entry); 108235063SnetchildLIN_SDT_PROBE_DEFINE1(emul, linux_schedtail, copyout_error, "int"); 109235063SnetchildLIN_SDT_PROBE_DEFINE0(emul, linux_schedtail, return); 110235063SnetchildLIN_SDT_PROBE_DEFINE1(emul, linux_set_tid_address, entry, "int *"); 111235063SnetchildLIN_SDT_PROBE_DEFINE0(emul, linux_set_tid_address, return); 112235063SnetchildLIN_SDT_PROBE_DEFINE2(emul, linux_kill_threads, entry, "struct thread *", 113235063Snetchild "int"); 114235063SnetchildLIN_SDT_PROBE_DEFINE1(emul, linux_kill_threads, kill, "pid_t"); 115235063SnetchildLIN_SDT_PROBE_DEFINE0(emul, linux_kill_threads, return); 116235063Snetchild 117168275Sjkimstruct sx emul_shared_lock; 118168275Sjkimstruct mtx emul_lock; 119161304Snetchild 120161304Snetchild/* this returns locked reference to the emuldata entry (if found) */ 121161304Snetchildstruct linux_emuldata * 122161304Snetchildem_find(struct proc *p, int locked) 123161304Snetchild{ 124161304Snetchild struct linux_emuldata *em; 125161304Snetchild 126235063Snetchild LIN_SDT_PROBE2(emul, em_find, entry, p, locked); 127235063Snetchild 128165867Snetchild if (locked == EMUL_DOLOCK) 129165688Snetchild EMUL_LOCK(&emul_lock); 130161304Snetchild 131165688Snetchild em = p->p_emuldata; 132161304Snetchild 133165867Snetchild if (em == NULL && locked == EMUL_DOLOCK) 134165688Snetchild EMUL_UNLOCK(&emul_lock); 135161304Snetchild 136235063Snetchild LIN_SDT_PROBE1(emul, em_find, return, em); 137161304Snetchild return (em); 138161304Snetchild} 139161304Snetchild 140161304Snetchildint 141161304Snetchildlinux_proc_init(struct thread *td, pid_t child, int flags) 142161304Snetchild{ 143161304Snetchild struct linux_emuldata *em, *p_em; 144161304Snetchild struct proc *p; 145161304Snetchild 146235063Snetchild LIN_SDT_PROBE3(emul, proc_init, entry, td, child, flags); 147235063Snetchild 148161304Snetchild if (child != 0) { 149235063Snetchild /* fork or create a thread */ 150161460Sssouhlal em = malloc(sizeof *em, M_LINUX, M_WAITOK | M_ZERO); 151161304Snetchild em->pid = child; 152163734Snetchild em->pdeath_signal = 0; 153218621Sdchagin em->flags = 0; 154178976Srdivacky em->robust_futexes = NULL; 155167157Sjkim if (flags & LINUX_CLONE_THREAD) { 156165688Snetchild /* handled later in the code */ 157235063Snetchild LIN_SDT_PROBE0(emul, proc_init, create_thread); 158161304Snetchild } else { 159165688Snetchild struct linux_emuldata_shared *s; 160161304Snetchild 161235063Snetchild LIN_SDT_PROBE0(emul, proc_init, fork); 162235063Snetchild 163161460Sssouhlal s = malloc(sizeof *s, M_LINUX, M_WAITOK | M_ZERO); 164161304Snetchild s->refs = 1; 165161304Snetchild s->group_pid = child; 166161304Snetchild 167161304Snetchild LIST_INIT(&s->threads); 168166150Snetchild em->shared = s; 169161304Snetchild } 170161304Snetchild } else { 171235063Snetchild /* exec */ 172235063Snetchild LIN_SDT_PROBE0(emul, proc_init, exec); 173235063Snetchild 174161304Snetchild /* lookup the old one */ 175165867Snetchild em = em_find(td->td_proc, EMUL_DOLOCK); 176161304Snetchild KASSERT(em != NULL, ("proc_init: emuldata not found in exec case.\n")); 177161304Snetchild } 178161304Snetchild 179161304Snetchild em->child_clear_tid = NULL; 180161304Snetchild em->child_set_tid = NULL; 181161304Snetchild 182165688Snetchild /* 183165688Snetchild * allocate the shared struct only in clone()/fork cases in the case 184165688Snetchild * of clone() td = calling proc and child = pid of the newly created 185165688Snetchild * proc 186161304Snetchild */ 187161304Snetchild if (child != 0) { 188167157Sjkim if (flags & LINUX_CLONE_THREAD) { 189165688Snetchild /* lookup the parent */ 190166396Skib /* 191166396Skib * we dont have to lock the p_em because 192166396Skib * its waiting for us in linux_clone so 193166396Skib * there is no chance of it changing the 194166396Skib * p_em->shared address 195166396Skib */ 196166396Skib p_em = em_find(td->td_proc, EMUL_DONTLOCK); 197164297Skib KASSERT(p_em != NULL, ("proc_init: parent emuldata not found for CLONE_THREAD\n")); 198161304Snetchild em->shared = p_em->shared; 199166396Skib EMUL_SHARED_WLOCK(&emul_shared_lock); 200161304Snetchild em->shared->refs++; 201166396Skib EMUL_SHARED_WUNLOCK(&emul_shared_lock); 202161304Snetchild } else { 203165688Snetchild /* 204165688Snetchild * handled earlier to avoid malloc(M_WAITOK) with 205165688Snetchild * rwlock held 206165688Snetchild */ 207161304Snetchild } 208235063Snetchild 209165688Snetchild EMUL_SHARED_WLOCK(&emul_shared_lock); 210165688Snetchild LIST_INSERT_HEAD(&em->shared->threads, em, threads); 211165688Snetchild EMUL_SHARED_WUNLOCK(&emul_shared_lock); 212161304Snetchild 213161304Snetchild p = pfind(child); 214166150Snetchild KASSERT(p != NULL, ("process not found in proc_init\n")); 215166150Snetchild p->p_emuldata = em; 216162184Snetchild PROC_UNLOCK(p); 217161304Snetchild } else 218165688Snetchild EMUL_UNLOCK(&emul_lock); 219161304Snetchild 220235063Snetchild LIN_SDT_PROBE0(emul, proc_init, return); 221165688Snetchild return (0); 222161304Snetchild} 223161304Snetchild 224161304Snetchildvoid 225161304Snetchildlinux_proc_exit(void *arg __unused, struct proc *p) 226161304Snetchild{ 227165688Snetchild struct linux_emuldata *em; 228215664Snetchild int error, shared_flags, shared_xstat; 229161304Snetchild struct thread *td = FIRST_THREAD_IN_PROC(p); 230161304Snetchild int *child_clear_tid; 231163734Snetchild struct proc *q, *nq; 232161304Snetchild 233161304Snetchild if (__predict_true(p->p_sysent != &elf_linux_sysvec)) 234165688Snetchild return; 235161304Snetchild 236235063Snetchild LIN_SDT_PROBE1(emul, proc_exit, entry, p); 237235063Snetchild 238178976Srdivacky release_futexes(p); 239178976Srdivacky 240161304Snetchild /* find the emuldata */ 241165867Snetchild em = em_find(p, EMUL_DOLOCK); 242161304Snetchild 243161304Snetchild KASSERT(em != NULL, ("proc_exit: emuldata not found.\n")); 244161304Snetchild 245166396Skib /* reparent all procs that are not a thread leader to initproc */ 246166396Skib if (em->shared->group_pid != p->p_pid) { 247235063Snetchild LIN_SDT_PROBE3(emul, proc_exit, reparent, 248235063Snetchild em->shared->group_pid, p->p_pid, p); 249235063Snetchild 250166930Snetchild child_clear_tid = em->child_clear_tid; 251166930Snetchild EMUL_UNLOCK(&emul_lock); 252166930Snetchild sx_xlock(&proctree_lock); 253166930Snetchild wakeup(initproc); 254166396Skib PROC_LOCK(p); 255166396Skib proc_reparent(p, initproc); 256166396Skib p->p_sigparent = SIGCHLD; 257166396Skib PROC_UNLOCK(p); 258166930Snetchild sx_xunlock(&proctree_lock); 259166930Snetchild } else { 260166930Snetchild child_clear_tid = em->child_clear_tid; 261166930Snetchild EMUL_UNLOCK(&emul_lock); 262166396Skib } 263166396Skib 264161304Snetchild EMUL_SHARED_WLOCK(&emul_shared_lock); 265215664Snetchild shared_flags = em->shared->flags; 266215664Snetchild shared_xstat = em->shared->xstat; 267161304Snetchild LIST_REMOVE(em, threads); 268161304Snetchild 269161304Snetchild em->shared->refs--; 270166931Snetchild if (em->shared->refs == 0) { 271166931Snetchild EMUL_SHARED_WUNLOCK(&emul_shared_lock); 272161460Sssouhlal free(em->shared, M_LINUX); 273166931Snetchild } else 274166931Snetchild EMUL_SHARED_WUNLOCK(&emul_shared_lock); 275161304Snetchild 276215675Snetchild if ((shared_flags & EMUL_SHARED_HASXSTAT) != 0) 277215664Snetchild p->p_xstat = shared_xstat; 278215664Snetchild 279161304Snetchild if (child_clear_tid != NULL) { 280165688Snetchild struct linux_sys_futex_args cup; 281161304Snetchild int null = 0; 282161304Snetchild 283161304Snetchild error = copyout(&null, child_clear_tid, sizeof(null)); 284163132Snetchild if (error) { 285235063Snetchild LIN_SDT_PROBE1(emul, proc_exit, 286235063Snetchild child_clear_tid_error, error); 287235063Snetchild 288165688Snetchild free(em, M_LINUX); 289235063Snetchild 290235063Snetchild LIN_SDT_PROBE0(emul, proc_exit, return); 291165688Snetchild return; 292163132Snetchild } 293161304Snetchild 294161304Snetchild /* futexes stuff */ 295161304Snetchild cup.uaddr = child_clear_tid; 296161304Snetchild cup.op = LINUX_FUTEX_WAKE; 297165688Snetchild cup.val = 0x7fffffff; /* Awake everyone */ 298161304Snetchild cup.timeout = NULL; 299161304Snetchild cup.uaddr2 = NULL; 300161304Snetchild cup.val3 = 0; 301161304Snetchild error = linux_sys_futex(FIRST_THREAD_IN_PROC(p), &cup); 302165688Snetchild /* 303165688Snetchild * this cannot happen at the moment and if this happens it 304166944Snetchild * probably means there is a user space bug 305161365Snetchild */ 306235063Snetchild if (error) { 307235063Snetchild LIN_SDT_PROBE0(emul, proc_exit, futex_failed); 308165688Snetchild printf(LMSG("futex stuff in proc_exit failed.\n")); 309235063Snetchild } 310161304Snetchild } 311161304Snetchild 312161304Snetchild /* clean the stuff up */ 313161460Sssouhlal free(em, M_LINUX); 314163734Snetchild 315163734Snetchild /* this is a little weird but rewritten from exit1() */ 316163734Snetchild sx_xlock(&proctree_lock); 317163734Snetchild q = LIST_FIRST(&p->p_children); 318163734Snetchild for (; q != NULL; q = nq) { 319165688Snetchild nq = LIST_NEXT(q, p_sibling); 320165688Snetchild if (q->p_flag & P_WEXIT) 321165688Snetchild continue; 322163734Snetchild if (__predict_false(q->p_sysent != &elf_linux_sysvec)) 323165688Snetchild continue; 324165867Snetchild em = em_find(q, EMUL_DOLOCK); 325163734Snetchild KASSERT(em != NULL, ("linux_reparent: emuldata not found: %i\n", q->p_pid)); 326184501Skib PROC_LOCK(q); 327184501Skib if ((q->p_flag & P_WEXIT) == 0 && em->pdeath_signal != 0) { 328225617Skmacy kern_psignal(q, em->pdeath_signal); 329163734Snetchild } 330184501Skib PROC_UNLOCK(q); 331163734Snetchild EMUL_UNLOCK(&emul_lock); 332163734Snetchild } 333163734Snetchild sx_xunlock(&proctree_lock); 334235063Snetchild 335235063Snetchild LIN_SDT_PROBE0(emul, proc_exit, return); 336161304Snetchild} 337161304Snetchild 338165688Snetchild/* 339161365Snetchild * This is used in a case of transition from FreeBSD binary execing to linux binary 340161304Snetchild * in this case we create linux emuldata proc entry with the pid of the currently running 341161304Snetchild * process. 342161304Snetchild */ 343165688Snetchildvoid 344165688Snetchildlinux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp) 345161304Snetchild{ 346235063Snetchild if (__predict_false(imgp->sysent == &elf_linux_sysvec)) { 347235063Snetchild LIN_SDT_PROBE2(emul, proc_exec, entry, p, imgp); 348235063Snetchild } 349165688Snetchild if (__predict_false(imgp->sysent == &elf_linux_sysvec 350165688Snetchild && p->p_sysent != &elf_linux_sysvec)) 351165688Snetchild linux_proc_init(FIRST_THREAD_IN_PROC(p), p->p_pid, 0); 352215675Snetchild if (__predict_false((p->p_sysent->sv_flags & SV_ABI_MASK) == 353215675Snetchild SV_ABI_LINUX)) 354215664Snetchild /* Kill threads regardless of imgp->sysent value */ 355215664Snetchild linux_kill_threads(FIRST_THREAD_IN_PROC(p), SIGKILL); 356161304Snetchild if (__predict_false(imgp->sysent != &elf_linux_sysvec 357165688Snetchild && p->p_sysent == &elf_linux_sysvec)) { 358165688Snetchild struct linux_emuldata *em; 359161304Snetchild 360166396Skib /* 361166396Skib * XXX:There's a race because here we assign p->p_emuldata NULL 362166396Skib * but the process is still counted as linux one for a short 363166396Skib * time so some other process might reference it and try to 364166396Skib * access its p->p_emuldata and panicing on a NULL reference. 365166396Skib */ 366166396Skib em = em_find(p, EMUL_DONTLOCK); 367161304Snetchild 368161304Snetchild KASSERT(em != NULL, ("proc_exec: emuldata not found.\n")); 369165688Snetchild 370161304Snetchild EMUL_SHARED_WLOCK(&emul_shared_lock); 371161304Snetchild LIST_REMOVE(em, threads); 372161304Snetchild 373161304Snetchild PROC_LOCK(p); 374161304Snetchild p->p_emuldata = NULL; 375161304Snetchild PROC_UNLOCK(p); 376161304Snetchild 377161304Snetchild em->shared->refs--; 378166931Snetchild if (em->shared->refs == 0) { 379166931Snetchild EMUL_SHARED_WUNLOCK(&emul_shared_lock); 380165688Snetchild free(em->shared, M_LINUX); 381166931Snetchild } else 382166931Snetchild EMUL_SHARED_WUNLOCK(&emul_shared_lock); 383161304Snetchild 384161697Sssouhlal free(em, M_LINUX); 385161304Snetchild } 386235063Snetchild 387235063Snetchild if (__predict_false(imgp->sysent == &elf_linux_sysvec)) { 388235063Snetchild LIN_SDT_PROBE0(emul, proc_exec, return); 389235063Snetchild } 390161304Snetchild} 391161304Snetchild 392161304Snetchildvoid 393219405Sdchaginlinux_schedtail(struct thread *td) 394161304Snetchild{ 395161304Snetchild struct linux_emuldata *em; 396219405Sdchagin struct proc *p; 397161304Snetchild int error = 0; 398161304Snetchild int *child_set_tid; 399161304Snetchild 400219405Sdchagin p = td->td_proc; 401219405Sdchagin 402235063Snetchild LIN_SDT_PROBE1(emul, linux_schedtail, entry, p); 403235063Snetchild 404161304Snetchild /* find the emuldata */ 405165867Snetchild em = em_find(p, EMUL_DOLOCK); 406161304Snetchild 407166396Skib KASSERT(em != NULL, ("linux_schedtail: emuldata not found.\n")); 408161304Snetchild child_set_tid = em->child_set_tid; 409161304Snetchild EMUL_UNLOCK(&emul_lock); 410161304Snetchild 411235063Snetchild if (child_set_tid != NULL) { 412165688Snetchild error = copyout(&p->p_pid, (int *)child_set_tid, 413165688Snetchild sizeof(p->p_pid)); 414161304Snetchild 415235063Snetchild if (error != 0) { 416235063Snetchild LIN_SDT_PROBE1(emul, linux_schedtail, copyout_error, 417235063Snetchild error); 418235063Snetchild } 419235063Snetchild } 420235063Snetchild 421235063Snetchild LIN_SDT_PROBE0(emul, linux_schedtail, return); 422235063Snetchild 423161304Snetchild return; 424161304Snetchild} 425161304Snetchild 426161304Snetchildint 427161304Snetchildlinux_set_tid_address(struct thread *td, struct linux_set_tid_address_args *args) 428161304Snetchild{ 429165688Snetchild struct linux_emuldata *em; 430161304Snetchild 431235063Snetchild LIN_SDT_PROBE1(emul, linux_set_tid_address, entry, args->tidptr); 432161304Snetchild 433165688Snetchild /* find the emuldata */ 434165867Snetchild em = em_find(td->td_proc, EMUL_DOLOCK); 435161304Snetchild 436161304Snetchild KASSERT(em != NULL, ("set_tid_address: emuldata not found.\n")); 437161304Snetchild 438161304Snetchild em->child_clear_tid = args->tidptr; 439161304Snetchild td->td_retval[0] = td->td_proc->p_pid; 440161304Snetchild 441161304Snetchild EMUL_UNLOCK(&emul_lock); 442235063Snetchild 443235063Snetchild LIN_SDT_PROBE0(emul, linux_set_tid_address, return); 444161304Snetchild return 0; 445161304Snetchild} 446215664Snetchild 447215664Snetchildvoid 448215664Snetchildlinux_kill_threads(struct thread *td, int sig) 449215664Snetchild{ 450215664Snetchild struct linux_emuldata *em, *td_em, *tmp_em; 451215664Snetchild struct proc *sp; 452215664Snetchild 453235063Snetchild LIN_SDT_PROBE2(emul, linux_kill_threads, entry, td, sig); 454235063Snetchild 455215664Snetchild td_em = em_find(td->td_proc, EMUL_DONTLOCK); 456215664Snetchild 457215664Snetchild KASSERT(td_em != NULL, ("linux_kill_threads: emuldata not found.\n")); 458215664Snetchild 459215664Snetchild EMUL_SHARED_RLOCK(&emul_shared_lock); 460215664Snetchild LIST_FOREACH_SAFE(em, &td_em->shared->threads, threads, tmp_em) { 461215664Snetchild if (em->pid == td_em->pid) 462215664Snetchild continue; 463215664Snetchild 464215664Snetchild sp = pfind(em->pid); 465215664Snetchild if ((sp->p_flag & P_WEXIT) == 0) 466225617Skmacy kern_psignal(sp, sig); 467215664Snetchild PROC_UNLOCK(sp); 468235063Snetchild 469235063Snetchild LIN_SDT_PROBE1(emul, linux_kill_threads, kill, em->pid); 470215664Snetchild } 471215664Snetchild EMUL_SHARED_RUNLOCK(&emul_shared_lock); 472235063Snetchild 473235063Snetchild LIN_SDT_PROBE0(emul, linux_kill_threads, return); 474215664Snetchild} 475