diff --git a/src/sim/process.cc b/src/sim/process.cc index 207c275cf2..272fc9fd12 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -174,6 +174,9 @@ Process::clone(ThreadContext *otc, ThreadContext *ntc, #endif #ifndef CLONE_THREAD #define CLONE_THREAD 0 +#endif +#ifndef CLONE_VFORK +#define CLONE_VFORK 0 #endif if (CLONE_VM & flags) { /** @@ -249,6 +252,10 @@ Process::clone(ThreadContext *otc, ThreadContext *ntc, np->exitGroup = exitGroup; } + if (CLONE_VFORK & flags) { + np->vforkContexts.push_back(otc->contextId()); + } + np->argv.insert(np->argv.end(), argv.begin(), argv.end()); np->envp.insert(np->envp.end(), envp.begin(), envp.end()); } diff --git a/src/sim/process.hh b/src/sim/process.hh index 632ba90edd..34768a0d92 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -284,6 +284,9 @@ class Process : public SimObject // Process was forked with SIGCHLD set. bool *sigchld; + // Contexts to wake up when this thread exits or calls execve + std::vector vforkContexts; + // Track how many system calls are executed statistics::Scalar numSyscalls; }; diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 147cb3931c..713bec42d6 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -193,6 +193,16 @@ exitImpl(SyscallDesc *desc, ThreadContext *tc, bool group, int status) } } + /** + * If we were a thread created by a clone with vfork set, wake up + * the thread that created us + */ + if (!p->vforkContexts.empty()) { + ThreadContext *vtc = sys->threads[p->vforkContexts.front()]; + assert(vtc->status() == ThreadContext::Suspended); + vtc->activate(); + } + tc->halt(); /** diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 09be700f27..8695638758 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -1521,6 +1521,10 @@ cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, ctc->pcState(cpc); ctc->activate(); + if (flags & OS::TGT_CLONE_VFORK) { + tc->suspend(); + } + return cp->pid(); } @@ -1997,6 +2001,16 @@ execveFunc(SyscallDesc *desc, ThreadContext *tc, } }; + /** + * If we were a thread created by a clone with vfork set, wake up + * the thread that created us + */ + if (!p->vforkContexts.empty()) { + ThreadContext *vtc = p->system->threads[p->vforkContexts.front()]; + assert(vtc->status() == ThreadContext::Suspended); + vtc->activate(); + } + /** * Note that ProcessParams is generated by swig and there are no other * examples of how to create anything but this default constructor. The