refactoring to send signal

This commit is contained in:
Tomoki Shirasawa
2015-10-15 17:10:02 +09:00
parent 6ae99454da
commit a325a78866
3 changed files with 131 additions and 133 deletions

View File

@ -804,19 +804,26 @@ do_kill(struct thread *thread, int pid, int tid, int sig, siginfo_t *info,
int ptracecont) int ptracecont)
{ {
dkprintf("do_kill,pid=%d,tid=%d,sig=%d\n", pid, tid, sig); dkprintf("do_kill,pid=%d,tid=%d,sig=%d\n", pid, tid, sig);
struct cpu_local_var *v;
struct thread *t; struct thread *t;
struct process *tproc;
struct process *proc = thread? thread->proc: NULL;
struct thread *tthread = NULL; struct thread *tthread = NULL;
int i; int i;
__sigset_t mask; __sigset_t mask;
struct list_head *head; ihk_spinlock_t *savelock = NULL;
struct list_head *head = NULL;
int rc; int rc;
unsigned long irqstate = 0; unsigned long irqstate = 0;
struct k_sigaction *k; struct k_sigaction *k;
int doint; int doint;
ihk_spinlock_t *savelock = NULL;
int found = 0; int found = 0;
siginfo_t info0; siginfo_t info0;
struct resource_set *rset = cpu_local_var(resource_set);
int hash;
struct thread_hash *thash = rset->thread_hash;
struct process_hash *phash = rset->process_hash;
struct mcs_rwlock_node lock;
struct mcs_rwlock_node updatelock;
if(sig > 64 || sig < 0) if(sig > 64 || sig < 0)
return -EINVAL; return -EINVAL;
@ -829,10 +836,11 @@ do_kill(struct thread *thread, int pid, int tid, int sig, siginfo_t *info,
} }
if(tid == -1 && pid <= 0){ if(tid == -1 && pid <= 0){
struct process *p;
struct mcs_rwlock_node_irqsave slock;
int pgid = -pid; int pgid = -pid;
int rc = -ESRCH; int rc = -ESRCH;
int *pids; int *pids;
int i;
int n = 0; int n = 0;
int sendme = 0; int sendme = 0;
@ -844,30 +852,21 @@ do_kill(struct thread *thread, int pid, int tid, int sig, siginfo_t *info,
pids = kmalloc(sizeof(int) * num_processors, IHK_MC_AP_NOWAIT); pids = kmalloc(sizeof(int) * num_processors, IHK_MC_AP_NOWAIT);
if(!pids) if(!pids)
return -ENOMEM; return -ENOMEM;
for(i = 0; i < num_processors; i++){ for(i = 0; i < HASH_SIZE; i++){
v = get_cpu_local_var(i); mcs_rwlock_reader_lock(&phash->lock[i], &slock);
irqstate = ihk_mc_spinlock_lock(&(v->runq_lock)); list_for_each_entry(p, &phash->list[i], hash_list){
list_for_each_entry(t, &(v->runq), sched_list){ if(pgid != 1 && p->pgid != pgid)
int j; continue;
if(t->proc->pid <= 0) if(thread && p->pid == thread->proc->pid){
continue;
if(pgid != 1 && t->proc->pgid != pgid)
continue;
if(thread && t->proc->pid == thread->proc->pid){
sendme = 1; sendme = 1;
continue; continue;
} }
for(j = 0; j < n; j++) pids[n] = p->pid;
if(pids[j] == t->proc->pid) n++;
break;
if(j == n){
pids[n] = t->proc->pid;
n++;
}
} }
ihk_mc_spinlock_unlock(&(v->runq_lock), irqstate); mcs_rwlock_reader_unlock(&phash->lock[i], &slock);
} }
for(i = 0; i < n; i++) for(i = 0; i < n; i++)
rc = do_kill(thread, pids[i], -1, sig, info, ptracecont); rc = do_kill(thread, pids[i], -1, sig, info, ptracecont);
@ -877,130 +876,132 @@ do_kill(struct thread *thread, int pid, int tid, int sig, siginfo_t *info,
kfree(pids); kfree(pids);
return rc; return rc;
} }
irqstate = cpu_disable_interrupt_save(); irqstate = cpu_disable_interrupt_save();
mask = __sigmask(sig); mask = __sigmask(sig);
if(tid == -1){ if(tid == -1){
struct thread *tthread0 = NULL; struct thread *tthread0 = NULL;
ihk_spinlock_t *savelock0 = NULL; struct mcs_rwlock_node plock;
struct mcs_rwlock_node updatelock;
for(i = 0; i < num_processors; i++){ found = 0;
v = get_cpu_local_var(i); hash = process_hash(pid);
found = 0; mcs_rwlock_reader_lock_noirq(&phash->lock[hash], &plock);
ihk_mc_spinlock_lock_noirq(&(v->runq_lock)); list_for_each_entry(tproc, &phash->list[hash], hash_list){
list_for_each_entry(t, &(v->runq), sched_list){ if(tproc->pid == pid){
if(t->proc->pid == pid){ found = 1;
if(t->tid == pid || tthread == NULL){ break;
if(!(mask & t->sigmask.__val[0])){
tthread = t;
if(!found && savelock) {
ihk_mc_spinlock_unlock_noirq(savelock);
}
found = 1;
savelock = &(v->runq_lock);
if(savelock0 && savelock0 != savelock){
ihk_mc_spinlock_unlock_noirq(savelock0);
savelock0 = NULL;
}
}
else if(tthread == NULL && tthread0 == NULL){
tthread0 = t;
found = 1;
savelock0 = &(v->runq_lock);
}
}
if(!(mask & t->sigmask.__val[0])){
if(t->tid == pid || tthread == NULL){
}
}
}
} }
if(!found) { }
ihk_mc_spinlock_unlock_noirq(&(v->runq_lock)); if(!found){
mcs_rwlock_reader_unlock_noirq(&phash->lock[hash], &plock);
cpu_restore_interrupt(irqstate);
return -ESRCH;
}
mcs_rwlock_reader_lock_noirq(&tproc->update_lock, &updatelock);
if(tproc->pstatus == PS_EXITED || tproc->pstatus == PS_ZOMBIE){
goto done;
}
mcs_rwlock_reader_lock_noirq(&tproc->threads_lock, &lock);
list_for_each_entry(t, &tproc->threads_list, siblings_list){
if(t->tid == pid || tthread == NULL){
if(t->tstatus == PS_EXITED){
continue;
}
if(!(mask & t->sigmask.__val[0])){
tthread = t;
found = 1;
}
else if(tthread == NULL && tthread0 == NULL){
tthread0 = t;
found = 1;
}
} }
} }
if(tthread == NULL){ if(tthread == NULL){
tthread = tthread0; tthread = tthread0;
savelock = savelock0;
} }
} if(tthread && tthread->tstatus != PS_EXITED){
else if(pid == -1){ savelock = &tthread->sigcommon->lock;
for(i = 0; i < num_processors; i++){ head = &tthread->sigcommon->sigpending;
v = get_cpu_local_var(i); hold_thread(tthread);
found = 0;
ihk_mc_spinlock_lock_noirq(&(v->runq_lock));
list_for_each_entry(t, &(v->runq), sched_list){
if(t->proc->pid > 0 &&
t->tid == tid){
savelock = &(v->runq_lock);
found = 1;
tthread = t;
break;
}
}
if(!found)
ihk_mc_spinlock_unlock_noirq(&(v->runq_lock));
} }
else
tthread = NULL;
mcs_rwlock_reader_unlock_noirq(&tproc->threads_lock, &lock);
done:
mcs_rwlock_reader_unlock_noirq(&tproc->update_lock, &updatelock);
mcs_rwlock_reader_unlock_noirq(&phash->lock[hash], &plock);
} }
else{ else{
for(i = 0; i < num_processors; i++){ found = 0;
v = get_cpu_local_var(i); hash = thread_hash(tid);
found = 0; mcs_rwlock_reader_lock_noirq(&thash->lock[hash], &lock);
ihk_mc_spinlock_lock_noirq(&(v->runq_lock)); list_for_each_entry(tthread, &thash->list[hash], hash_list){
list_for_each_entry(t, &(v->runq), sched_list){ if(pid != -1 && tthread->proc->pid != pid){
if(t->proc->pid == pid && continue;
t->tid == tid){
savelock = &(v->runq_lock);
found = 1;
tthread = t;
break;
}
} }
if(found) if(tthread->tid == tid){
found = 1;
break; break;
ihk_mc_spinlock_unlock_noirq(&(v->runq_lock)); }
} }
if(!found){
mcs_rwlock_reader_unlock_noirq(&thash->lock[hash], &lock);
cpu_restore_interrupt(irqstate);
return -ESRCH;
}
tproc = tthread->proc;
mcs_rwlock_reader_lock_noirq(&tproc->update_lock, &updatelock);
savelock = &tthread->sigpendinglock;
head = &tthread->sigpending;
if(sig == SIGKILL ||
(tproc->pstatus != PS_EXITED &&
tproc->pstatus != PS_ZOMBIE &&
tthread->tstatus != PS_EXITED)){
hold_thread(tthread);
}
else{
tthread = NULL;
}
mcs_rwlock_reader_unlock_noirq(&tproc->update_lock, &updatelock);
mcs_rwlock_reader_unlock_noirq(&thash->lock[hash], &lock);
} }
if(!tthread){
cpu_restore_interrupt(irqstate);
return -ESRCH;
}
if(sig != SIGCONT && if(sig != SIGCONT &&
thread && proc &&
thread->proc->euid != 0 && proc->euid != 0 &&
thread->proc->ruid != tthread->proc->ruid && proc->ruid != tproc->ruid &&
thread->proc->euid != tthread->proc->ruid && proc->euid != tproc->ruid &&
thread->proc->ruid != tthread->proc->suid && proc->ruid != tproc->suid &&
thread->proc->euid != tthread->proc->suid){ proc->euid != tproc->suid){
ihk_mc_spinlock_unlock_noirq(savelock); if(tthread)
release_thread(tthread);
cpu_restore_interrupt(irqstate); cpu_restore_interrupt(irqstate);
return -EPERM; return -EPERM;
} }
if(sig == 0){ if(sig == 0 || tthread == NULL || tthread->tstatus == PS_EXITED){
ihk_mc_spinlock_unlock_noirq(savelock); if(tthread)
release_thread(tthread);
cpu_restore_interrupt(irqstate); cpu_restore_interrupt(irqstate);
return 0; return 0;
} }
doint = 0; doint = 0;
if(tid == -1){
ihk_mc_spinlock_lock_noirq(&tthread->sigcommon->lock); ihk_mc_spinlock_lock_noirq(savelock);
head = &tthread->sigcommon->sigpending;
}
else{
ihk_mc_spinlock_lock_noirq(&tthread->sigpendinglock);
head = &tthread->sigpending;
}
/* Put signal event even when handler is SIG_IGN or SIG_DFL /* Put signal event even when handler is SIG_IGN or SIG_DFL
because target ptraced thread must call ptrace_report_signal because target ptraced thread must call ptrace_report_signal
in check_signal */ in check_signal */
rc = 0; rc = 0;
k = tthread->sigcommon->action + sig - 1; k = tthread->sigcommon->action + sig - 1;
if((sig != SIGKILL && (tthread->proc->ptrace & PT_TRACED)) || if((sig != SIGKILL && (tproc->ptrace & PT_TRACED)) ||
(k->sa.sa_handler != (void *)1 && (k->sa.sa_handler != (void *)1 &&
(k->sa.sa_handler != NULL || (k->sa.sa_handler != NULL ||
(sig != SIGCHLD && sig != SIGURG)))){ (sig != SIGCHLD && sig != SIGURG)))){
@ -1032,27 +1033,20 @@ do_kill(struct thread *thread, int pid, int tid, int sig, siginfo_t *info,
} }
} }
} }
ihk_mc_spinlock_unlock_noirq(savelock);
if(tid == -1){ cpu_restore_interrupt(irqstate);
ihk_mc_spinlock_unlock_noirq(&tthread->sigcommon->lock);
}
else{
ihk_mc_spinlock_unlock_noirq(&tthread->sigpendinglock);
}
if (doint && !(mask & tthread->sigmask.__val[0])) { if (doint && !(mask & tthread->sigmask.__val[0])) {
int cpuid = tthread->cpu_id; int cpuid = tthread->cpu_id;
int pid = tthread->proc->pid; int pid = tproc->pid;
int status = tthread->tstatus; int status = tthread->tstatus;
if (thread != tthread) { if (thread != tthread) {
dkprintf("do_kill,ipi,pid=%d,cpu_id=%d\n", dkprintf("do_kill,ipi,pid=%d,cpu_id=%d\n",
tthread->proc->pid, tthread->cpu_id); tproc->pid, tthread->cpu_id);
ihk_mc_interrupt_cpu(get_x86_cpu_local_variable(tthread->cpu_id)->apic_id, 0xd0); ihk_mc_interrupt_cpu(get_x86_cpu_local_variable(tthread->cpu_id)->apic_id, 0xd0);
} }
ihk_mc_spinlock_unlock_noirq(savelock);
cpu_restore_interrupt(irqstate);
if(!tthread->proc->nohost) if(!tthread->proc->nohost)
interrupt_syscall(pid, cpuid); interrupt_syscall(pid, cpuid);
@ -1067,10 +1061,7 @@ do_kill(struct thread *thread, int pid, int tid, int sig, siginfo_t *info,
} }
} }
} }
else { release_thread(tthread);
ihk_mc_spinlock_unlock_noirq(savelock);
cpu_restore_interrupt(irqstate);
}
return rc; return rc;
} }

View File

@ -2090,7 +2090,7 @@ out:
void hold_thread(struct thread *thread) void hold_thread(struct thread *thread)
{ {
if (thread->proc->pstatus & (PS_ZOMBIE | PS_EXITED)) { if (thread->tstatus == PS_EXITED) {
panic("hold_thread: already exited process"); panic("hold_thread: already exited process");
} }
@ -2130,15 +2130,15 @@ void destroy_thread(struct thread *thread)
struct resource_set *resource_set = cpu_local_var(resource_set); struct resource_set *resource_set = cpu_local_var(resource_set);
int hash; int hash;
mcs_rwlock_writer_lock(&proc->threads_lock, &lock);
list_del(&thread->siblings_list);
mcs_rwlock_writer_unlock(&proc->threads_lock, &lock);
hash = thread_hash(thread->tid); hash = thread_hash(thread->tid);
mcs_rwlock_writer_lock(&resource_set->thread_hash->lock[hash], &lock); mcs_rwlock_writer_lock(&resource_set->thread_hash->lock[hash], &lock);
list_del(&thread->hash_list); list_del(&thread->hash_list);
mcs_rwlock_writer_unlock(&resource_set->thread_hash->lock[hash], &lock); mcs_rwlock_writer_unlock(&resource_set->thread_hash->lock[hash], &lock);
mcs_rwlock_writer_lock(&proc->threads_lock, &lock);
list_del(&thread->siblings_list);
mcs_rwlock_writer_unlock(&proc->threads_lock, &lock);
cpu_clear(thread->cpu_id, &thread->vm->cpu_set, &thread->vm->cpu_set_lock); cpu_clear(thread->cpu_id, &thread->vm->cpu_set, &thread->vm->cpu_set_lock);
list_for_each_entry_safe(pending, signext, &thread->sigpending, list){ list_for_each_entry_safe(pending, signext, &thread->sigpending, list){
list_del(&pending->list); list_del(&pending->list);
@ -2801,7 +2801,7 @@ find_thread(int pid, int tid, struct mcs_rwlock_node_irqsave *lock)
if(thread->tid == tid){ if(thread->tid == tid){
if(pid <= 0) if(pid <= 0)
return thread; return thread;
if(pid == thread->proc->pid) if(thread->proc->pid == pid)
return thread; return thread;
} }
} }
@ -2833,8 +2833,7 @@ find_process(int pid, struct mcs_rwlock_node_irqsave *lock)
mcs_rwlock_reader_lock(&phash->lock[hash], lock); mcs_rwlock_reader_lock(&phash->lock[hash], lock);
list_for_each_entry(proc, &phash->list[hash], hash_list){ list_for_each_entry(proc, &phash->list[hash], hash_list){
if(proc->pid == pid){ if(proc->pid == pid){
if(pid == proc->pid) return proc;
return proc;
} }
} }
mcs_rwlock_reader_unlock(&phash->lock[hash], lock); mcs_rwlock_reader_unlock(&phash->lock[hash], lock);

View File

@ -606,6 +606,7 @@ terminate(int rc, int sig)
do_kill(mythread, proc->pid, ids[i], SIGKILL, NULL, 0); do_kill(mythread, proc->pid, ids[i], SIGKILL, NULL, 0);
} }
kfree(ids); kfree(ids);
ids = NULL;
} }
mcs_rwlock_reader_unlock(&proc->threads_lock, &lock); mcs_rwlock_reader_unlock(&proc->threads_lock, &lock);
@ -3527,7 +3528,14 @@ SYSCALL_DECLARE(exit)
FUTEX_WAKE, 1, 0, NULL, 0, 0); FUTEX_WAKE, 1, 0, NULL, 0, 0);
} }
mcs_rwlock_reader_lock(&proc->threads_lock, &lock);
if(proc->pstatus == PS_EXITED){
mcs_rwlock_reader_unlock(&proc->threads_lock, &lock);
terminate(exit_status, 0);
return 0;
}
thread->tstatus = PS_EXITED; thread->tstatus = PS_EXITED;
mcs_rwlock_reader_unlock(&proc->threads_lock, &lock);
release_thread(thread); release_thread(thread);
schedule(); schedule();