Support SIGSTOP and SIGCONT

This commit is contained in:
Masamichi Takagi
2014-09-10 16:23:38 +09:00
parent b50e205a61
commit 2325d47952
3 changed files with 57 additions and 1 deletions

View File

@ -274,6 +274,30 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
case SIGCHLD:
case SIGURG:
return;
case SIGSTOP: {
dkprintf("do_signal,SIGSTOP,changing state\n");
struct process *proc = cpu_local_var(current);
struct fork_tree_node *ftn = proc->ftn;
int exit_code = SIGSTOP;
/* Update process state in fork tree */
ihk_mc_spinlock_lock_noirq(&ftn->lock);
ftn->exit_status = (exit_code << 8) | 0x7f;
ftn->status = PS_STOPPED;
ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock);
/* Wake up the parent who tried wait4 and sleeping */
waitq_wakeup(&proc->ftn->parent->waitpid_q);
dkprintf("do_signal,SIGSTOP,sleeping\n");
/* Sleep */
proc->status = PS_STOPPED;
schedule();
dkprintf("SIGSTOP(): woken up\n");
goto out; }
case SIGCONT:
dkprintf("do_signal,SIGCONT,do nothing\n");
goto out;
case SIGQUIT:
case SIGILL:
case SIGTRAP:
@ -288,6 +312,7 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
}
terminate(0, sig | coredumped, (ihk_mc_user_context_t *)regs->rsp);
}
out:;
}
void
@ -555,21 +580,39 @@ do_kill(int pid, int tid, int sig)
else{
ihk_mc_spinlock_unlock_noirq(&tproc->sigpendinglock);
}
dkprintf("do_kill,pid=%d,sig=%d\n", pid, sig);
if(doint && !(mask & tproc->sigmask.__val[0])){
int cpuid = tproc->cpu_id;
dkprintf("do_kill,proc=%p,tproc=%p\n", proc, tproc);
if(proc != tproc){
ihk_mc_interrupt_cpu(get_x86_cpu_local_variable(cpuid)->apic_id, 0xd0);
}
pid = tproc->pid;
ihk_mc_spinlock_unlock_noirq(savelock);
cpu_restore_interrupt(irqstate);
dkprintf("do_kill,sending kill to mcexec,pid=%d,cpuid=%d\n", pid, cpuid);
interrupt_syscall(pid, cpuid);
}
else{
ihk_mc_spinlock_unlock_noirq(savelock);
cpu_restore_interrupt(irqstate);
}
if(!(mask & tproc->sigmask.__val[0])) {
switch(sig) {
case SIGCONT:
dkprintf("do_kill,SIGCONT\n");
/* Wake up the target only when stopped by SIGSTOP */
sched_wakeup_process(tproc, PS_STOPPED);
if (tproc->ftn->status & PS_STOPPED) {
ihk_mc_spinlock_lock_noirq(&tproc->ftn->lock);
xchg4((int *)(&tproc->ftn->status), PS_RUNNING);
ihk_mc_spinlock_unlock_noirq(&tproc->ftn->lock);
}
break;
default:
break;
}
}
return rc;
}

View File

@ -51,6 +51,7 @@
#define PS_UNINTERRUPTIBLE 0x4
#define PS_ZOMBIE 0x8
#define PS_EXITED 0x10
#define PS_STOPPED 0x20
#define PS_NORMAL (PS_INTERRUPTIBLE | PS_UNINTERRUPTIBLE)

View File

@ -367,6 +367,18 @@ rescan:
if (ret != pid)
kprintf("WARNING: host waitpid failed?\n");
goto exit;
} else if(child->status == PS_STOPPED) {
ihk_mc_spinlock_unlock_noirq(&child->lock);
ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock);
/* exit_status is created in do_signal */
if (status) {
*status = child->exit_status;
}
pid = child->pid;
dkprintf("wait4,PS_STOPPED,pid=%d,status=%08x\n", pid, *status);
goto exit;
}