static void futex_put(struct futex *f, struct waiting_proc *wp) { LIN_SDT_PROBE2(futex, futex_put, entry, f, wp); FUTEX_ASSERT_LOCKED(f); if (wp != NULL) { if ((wp->wp_flags & FUTEX_WP_REMOVED) == 0) TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list); free(wp, M_FUTEX_WP); } FUTEXES_LOCK; if (--f->f_refcount == 0) { LIST_REMOVE(f, f_list); FUTEXES_UNLOCK; FUTEX_UNLOCK(f); LIN_SDT_PROBE3(futex, futex_put, destroy, f->f_uaddr, f->f_refcount, f->f_key.shared); LINUX_CTR3(sys_futex, "futex_put destroy uaddr %p ref %d " "shared %d", f->f_uaddr, f->f_refcount, f->f_key.shared); umtx_key_release(&f->f_key); FUTEX_DESTROY(f); free(f, M_FUTEX); LIN_SDT_PROBE0(futex, futex_put, return); return; }
int linux_lchown16(struct thread *td, struct linux_lchown16_args *args) { char *path; int error; LCONVPATHEXIST(td, args->path, &path); /* * The DTrace probes have to be after the LCONVPATHEXIST, as * LCONVPATHEXIST may return on its own and we do not want to * have a stray entry without the corresponding return. */ LIN_SDT_PROBE3(uid16, linux_lchown16, entry, args->path, args->uid, args->gid); LIN_SDT_PROBE1(uid16, linux_lchown16, conv_path, path); error = kern_lchown(td, path, UIO_SYSSPACE, CAST_NOCHG(args->uid), CAST_NOCHG(args->gid)); LFREEPATH(path); LIN_SDT_PROBE1(uid16, linux_lchown16, return, error); return (error); }
int linux_proc_init(struct thread *td, pid_t child, int flags) { struct linux_emuldata *em, *p_em; struct proc *p; LIN_SDT_PROBE3(emul, proc_init, entry, td, child, flags); if (child != 0) { /* fork or create a thread */ em = malloc(sizeof *em, M_LINUX, M_WAITOK | M_ZERO); em->pid = child; em->pdeath_signal = 0; em->flags = 0; em->robust_futexes = NULL; if (flags & LINUX_CLONE_THREAD) { /* handled later in the code */ LIN_SDT_PROBE0(emul, proc_init, create_thread); } else { struct linux_emuldata_shared *s; LIN_SDT_PROBE0(emul, proc_init, fork); s = malloc(sizeof *s, M_LINUX, M_WAITOK | M_ZERO); s->refs = 1; s->group_pid = child; LIST_INIT(&s->threads); em->shared = s; } } else { /* exec */ LIN_SDT_PROBE0(emul, proc_init, exec); /* lookup the old one */ em = em_find(td->td_proc, EMUL_DOLOCK); KASSERT(em != NULL, ("proc_init: emuldata not found in exec case.\n")); } em->child_clear_tid = NULL; em->child_set_tid = NULL; /* * allocate the shared struct only in clone()/fork cases in the case * of clone() td = calling proc and child = pid of the newly created * proc */ if (child != 0) { if (flags & LINUX_CLONE_THREAD) { /* lookup the parent */ /* * we dont have to lock the p_em because * its waiting for us in linux_clone so * there is no chance of it changing the * p_em->shared address */ p_em = em_find(td->td_proc, EMUL_DONTLOCK); KASSERT(p_em != NULL, ("proc_init: parent emuldata not found for CLONE_THREAD\n")); em->shared = p_em->shared; EMUL_SHARED_WLOCK(&emul_shared_lock); em->shared->refs++; EMUL_SHARED_WUNLOCK(&emul_shared_lock); } else { /* * handled earlier to avoid malloc(M_WAITOK) with * rwlock held */ } EMUL_SHARED_WLOCK(&emul_shared_lock); LIST_INSERT_HEAD(&em->shared->threads, em, threads); EMUL_SHARED_WUNLOCK(&emul_shared_lock); p = pfind(child); KASSERT(p != NULL, ("process not found in proc_init\n")); p->p_emuldata = em; PROC_UNLOCK(p); } else EMUL_UNLOCK(&emul_lock); LIN_SDT_PROBE0(emul, proc_init, return); return (0); }