plan9fox/sys/src/libthread/kill.c
cinap_lenrek c235046310 libthread: use "interrupt" proc ctl message instead of posting a note for threadint()
threadint() is called to interrupt channel operation or a system call.
the kernel provides a new "interrupt" procctl message to interrupt a
process commited to or being in a blocking syscall, which is similar,
but not the same. the main difference is that "interrupt" condition
is not cleared before the process actually attempts to block. also
can be cleared with "nointerrupt" ctl message. see proc(3)
2015-08-10 03:48:37 +02:00

103 lines
1.5 KiB
C

#include <u.h>
#include <libc.h>
#include <thread.h>
#include "threadimpl.h"
static void tinterrupt(Proc*, Thread*);
static void
threadxxxgrp(int grp, int dokill)
{
Proc *p;
Thread *t;
lock(&_threadpq.lock);
for(p=_threadpq.head; p; p=p->next){
lock(&p->lock);
for(t=p->threads.head; t; t=t->nextt)
if(t->grp == grp){
if(dokill)
t->moribund = 1;
tinterrupt(p, t);
}
unlock(&p->lock);
}
unlock(&_threadpq.lock);
_threadbreakrendez();
}
static void
threadxxx(int id, int dokill)
{
Proc *p;
Thread *t;
lock(&_threadpq.lock);
for(p=_threadpq.head; p; p=p->next){
lock(&p->lock);
for(t=p->threads.head; t; t=t->nextt)
if(t->id == id){
if(dokill)
t->moribund = 1;
tinterrupt(p, t);
unlock(&p->lock);
unlock(&_threadpq.lock);
_threadbreakrendez();
return;
}
unlock(&p->lock);
}
unlock(&_threadpq.lock);
_threaddebug(DBGNOTE, "Can't find thread to kill");
return;
}
void
threadkillgrp(int grp)
{
threadxxxgrp(grp, 1);
}
void
threadkill(int id)
{
threadxxx(id, 1);
}
void
threadintgrp(int grp)
{
threadxxxgrp(grp, 0);
}
void
threadint(int id)
{
threadxxx(id, 0);
}
static void
tinterrupt(Proc *p, Thread *t)
{
char buf[64];
int fd;
switch(t->state){
case Running:
snprint(buf, sizeof(buf), "/proc/%d/ctl", p->pid);
fd = open(buf, OWRITE|OCEXEC);
if(fd >= 0){
if(write(fd, "interrupt", 9) == 9){
close(fd);
break;
}
close(fd);
}
postnote(PNPROC, p->pid, "threadint");
break;
case Rendezvous:
_threadflagrendez(t);
break;
}
}