void linux_e_lwp_exit(struct lwp *l) { struct linux_emuldata *led; struct linux_sys_futex_args cup; register_t retval; int error, zero = 0; led = l->l_emuldata; if (led->led_clear_tid == NULL) { return; } /* Emulate LINUX_CLONE_CHILD_CLEARTID */ error = copyout(&zero, led->led_clear_tid, sizeof(zero)); #ifdef DEBUG_LINUX if (error != 0) printf("%s: cannot clear TID\n", __func__); #endif SCARG(&cup, uaddr) = led->led_clear_tid; SCARG(&cup, op) = LINUX_FUTEX_WAKE; SCARG(&cup, val) = 0x7fffffff; /* Awake everyone */ SCARG(&cup, timeout) = NULL; SCARG(&cup, uaddr2) = NULL; SCARG(&cup, val3) = 0; if ((error = linux_sys_futex(curlwp, &cup, &retval)) != 0) printf("%s: linux_sys_futex failed\n", __func__); release_futexes(l); led = l->l_emuldata; l->l_emuldata = NULL; kmem_free(led, sizeof(*led)); }
void linux_thread_detach(struct thread *td) { struct linux_sys_futex_args cup; struct linux_emuldata *em; int *child_clear_tid; int error; em = em_find(td); KASSERT(em != NULL, ("thread_detach: emuldata not found.\n")); LINUX_CTR1(thread_detach, "thread(%d)", em->em_tid); release_futexes(td, em); child_clear_tid = em->child_clear_tid; if (child_clear_tid != NULL) { LINUX_CTR2(thread_detach, "thread(%d) %p", em->em_tid, child_clear_tid); error = suword32(child_clear_tid, 0); if (error != 0) return; cup.uaddr = child_clear_tid; cup.op = LINUX_FUTEX_WAKE; cup.val = 1; /* wake one */ cup.timeout = NULL; cup.uaddr2 = NULL; cup.val3 = 0; error = linux_sys_futex(td, &cup); /* * this cannot happen at the moment and if this happens it * probably means there is a user space bug */ if (error != 0) linux_msg(td, "futex stuff in thread_detach failed."); } }