Changeset View
Changeset View
Standalone View
Standalone View
sys/compat/linux/linux_fork.c
Show First 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | |||||
int | int | ||||
linux_fork(struct thread *td, struct linux_fork_args *args) | linux_fork(struct thread *td, struct linux_fork_args *args) | ||||
{ | { | ||||
struct fork_req fr; | struct fork_req fr; | ||||
int error; | int error; | ||||
struct proc *p2; | struct proc *p2; | ||||
struct thread *td2; | struct thread *td2; | ||||
#ifdef DEBUG | |||||
if (ldebug(fork)) | |||||
printf(ARGS(fork, "")); | |||||
#endif | |||||
bzero(&fr, sizeof(fr)); | bzero(&fr, sizeof(fr)); | ||||
fr.fr_flags = RFFDG | RFPROC | RFSTOPPED; | fr.fr_flags = RFFDG | RFPROC | RFSTOPPED; | ||||
fr.fr_procp = &p2; | fr.fr_procp = &p2; | ||||
if ((error = fork1(td, &fr)) != 0) | if ((error = fork1(td, &fr)) != 0) | ||||
return (error); | return (error); | ||||
td2 = FIRST_THREAD_IN_PROC(p2); | td2 = FIRST_THREAD_IN_PROC(p2); | ||||
Show All 15 Lines | |||||
int | int | ||||
linux_vfork(struct thread *td, struct linux_vfork_args *args) | linux_vfork(struct thread *td, struct linux_vfork_args *args) | ||||
{ | { | ||||
struct fork_req fr; | struct fork_req fr; | ||||
int error; | int error; | ||||
struct proc *p2; | struct proc *p2; | ||||
struct thread *td2; | struct thread *td2; | ||||
#ifdef DEBUG | |||||
if (ldebug(vfork)) | |||||
printf(ARGS(vfork, "")); | |||||
#endif | |||||
bzero(&fr, sizeof(fr)); | bzero(&fr, sizeof(fr)); | ||||
fr.fr_flags = RFFDG | RFPROC | RFMEM | RFPPWAIT | RFSTOPPED; | fr.fr_flags = RFFDG | RFPROC | RFMEM | RFPPWAIT | RFSTOPPED; | ||||
fr.fr_procp = &p2; | fr.fr_procp = &p2; | ||||
if ((error = fork1(td, &fr)) != 0) | if ((error = fork1(td, &fr)) != 0) | ||||
return (error); | return (error); | ||||
td2 = FIRST_THREAD_IN_PROC(p2); | td2 = FIRST_THREAD_IN_PROC(p2); | ||||
Show All 18 Lines | |||||
{ | { | ||||
struct fork_req fr; | struct fork_req fr; | ||||
int error, ff = RFPROC | RFSTOPPED; | int error, ff = RFPROC | RFSTOPPED; | ||||
struct proc *p2; | struct proc *p2; | ||||
struct thread *td2; | struct thread *td2; | ||||
int exit_signal; | int exit_signal; | ||||
struct linux_emuldata *em; | struct linux_emuldata *em; | ||||
#ifdef DEBUG | |||||
if (ldebug(clone)) { | |||||
printf(ARGS(clone, "flags %x, stack %p, parent tid: %p, " | |||||
"child tid: %p"), (unsigned)args->flags, | |||||
args->stack, args->parent_tidptr, args->child_tidptr); | |||||
} | |||||
#endif | |||||
exit_signal = args->flags & 0x000000ff; | exit_signal = args->flags & 0x000000ff; | ||||
if (LINUX_SIG_VALID(exit_signal)) { | if (LINUX_SIG_VALID(exit_signal)) { | ||||
exit_signal = linux_to_bsd_signal(exit_signal); | exit_signal = linux_to_bsd_signal(exit_signal); | ||||
} else if (exit_signal != 0) | } else if (exit_signal != 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (args->flags & LINUX_CLONE_VM) | if (args->flags & LINUX_CLONE_VM) | ||||
ff |= RFMEM; | ff |= RFMEM; | ||||
Show All 39 Lines | if (args->flags & LINUX_CLONE_CHILD_CLEARTID) | ||||
em->child_clear_tid = args->child_tidptr; | em->child_clear_tid = args->child_tidptr; | ||||
else | else | ||||
em->child_clear_tid = NULL; | em->child_clear_tid = NULL; | ||||
if (args->flags & LINUX_CLONE_PARENT_SETTID) { | if (args->flags & LINUX_CLONE_PARENT_SETTID) { | ||||
error = copyout(&p2->p_pid, args->parent_tidptr, | error = copyout(&p2->p_pid, args->parent_tidptr, | ||||
sizeof(p2->p_pid)); | sizeof(p2->p_pid)); | ||||
if (error) | if (error) | ||||
printf(LMSG("copyout failed!")); | linux_msg(td, "copyout p_pid failed!"); | ||||
} | } | ||||
PROC_LOCK(p2); | PROC_LOCK(p2); | ||||
p2->p_sigparent = exit_signal; | p2->p_sigparent = exit_signal; | ||||
PROC_UNLOCK(p2); | PROC_UNLOCK(p2); | ||||
/* | /* | ||||
* In a case of stack = NULL, we are supposed to COW calling process | * In a case of stack = NULL, we are supposed to COW calling process | ||||
* stack. This is what normal fork() does, so we just keep tf_rsp arg | * stack. This is what normal fork() does, so we just keep tf_rsp arg | ||||
Show All 11 Lines | linux_clone_proc(struct thread *td, struct linux_clone_args *args) | ||||
if (args->flags & LINUX_CLONE_PARENT) { | if (args->flags & LINUX_CLONE_PARENT) { | ||||
sx_xlock(&proctree_lock); | sx_xlock(&proctree_lock); | ||||
PROC_LOCK(p2); | PROC_LOCK(p2); | ||||
proc_reparent(p2, td->td_proc->p_pptr, true); | proc_reparent(p2, td->td_proc->p_pptr, true); | ||||
PROC_UNLOCK(p2); | PROC_UNLOCK(p2); | ||||
sx_xunlock(&proctree_lock); | sx_xunlock(&proctree_lock); | ||||
} | } | ||||
#ifdef DEBUG | |||||
if (ldebug(clone)) | |||||
printf(LMSG("clone: successful rfork to %d, " | |||||
"stack %p sig = %d"), (int)p2->p_pid, args->stack, | |||||
exit_signal); | |||||
#endif | |||||
/* | /* | ||||
* Make this runnable after we are finished with it. | * Make this runnable after we are finished with it. | ||||
*/ | */ | ||||
thread_lock(td2); | thread_lock(td2); | ||||
TD_SET_CAN_RUN(td2); | TD_SET_CAN_RUN(td2); | ||||
sched_add(td2, SRQ_BORING); | sched_add(td2, SRQ_BORING); | ||||
thread_unlock(td2); | thread_unlock(td2); | ||||
td->td_retval[0] = p2->p_pid; | td->td_retval[0] = p2->p_pid; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
linux_clone_thread(struct thread *td, struct linux_clone_args *args) | linux_clone_thread(struct thread *td, struct linux_clone_args *args) | ||||
{ | { | ||||
struct linux_emuldata *em; | struct linux_emuldata *em; | ||||
struct thread *newtd; | struct thread *newtd; | ||||
struct proc *p; | struct proc *p; | ||||
int error; | int error; | ||||
#ifdef DEBUG | |||||
if (ldebug(clone)) { | |||||
printf(ARGS(clone, "thread: flags %x, stack %p, parent tid: %p, " | |||||
"child tid: %p"), (unsigned)args->flags, | |||||
args->stack, args->parent_tidptr, args->child_tidptr); | |||||
} | |||||
#endif | |||||
LINUX_CTR4(clone_thread, "thread(%d) flags %x ptid %p ctid %p", | LINUX_CTR4(clone_thread, "thread(%d) flags %x ptid %p ctid %p", | ||||
td->td_tid, (unsigned)args->flags, | td->td_tid, (unsigned)args->flags, | ||||
args->parent_tidptr, args->child_tidptr); | args->parent_tidptr, args->child_tidptr); | ||||
if (args->flags & LINUX_CLONE_PARENT_SETTID) | if (args->flags & LINUX_CLONE_PARENT_SETTID) | ||||
if (args->parent_tidptr == NULL) | if (args->parent_tidptr == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | if (P_SHOULDSTOP(p)) | ||||
newtd->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK; | newtd->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK; | ||||
if (p->p_ptevents & PTRACE_LWP) | if (p->p_ptevents & PTRACE_LWP) | ||||
newtd->td_dbgflags |= TDB_BORN; | newtd->td_dbgflags |= TDB_BORN; | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
tidhash_add(newtd); | tidhash_add(newtd); | ||||
#ifdef DEBUG | |||||
if (ldebug(clone)) | |||||
printf(ARGS(clone, "successful clone to %d, stack %p"), | |||||
(int)newtd->td_tid, args->stack); | |||||
#endif | |||||
LINUX_CTR2(clone_thread, "thread(%d) successful clone to %d", | LINUX_CTR2(clone_thread, "thread(%d) successful clone to %d", | ||||
td->td_tid, newtd->td_tid); | td->td_tid, newtd->td_tid); | ||||
if (args->flags & LINUX_CLONE_PARENT_SETTID) { | if (args->flags & LINUX_CLONE_PARENT_SETTID) { | ||||
error = copyout(&newtd->td_tid, args->parent_tidptr, | error = copyout(&newtd->td_tid, args->parent_tidptr, | ||||
sizeof(newtd->td_tid)); | sizeof(newtd->td_tid)); | ||||
if (error) | if (error) | ||||
printf(LMSG("clone_thread: copyout failed!")); | linux_msg(td, "clone_thread: copyout td_tid failed!"); | ||||
} | } | ||||
/* | /* | ||||
* Make this runnable after we are finished with it. | * Make this runnable after we are finished with it. | ||||
*/ | */ | ||||
thread_lock(newtd); | thread_lock(newtd); | ||||
TD_SET_CAN_RUN(newtd); | TD_SET_CAN_RUN(newtd); | ||||
sched_add(newtd, SRQ_BORING); | sched_add(newtd, SRQ_BORING); | ||||
▲ Show 20 Lines • Show All 109 Lines • Show Last 20 Lines |