![cinap_lenrek](/assets/img/avatar_default.png)
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)
103 lines
1.5 KiB
C
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;
|
|
}
|
|
}
|