91 lines
1.3 KiB
C
91 lines
1.3 KiB
C
#include "u.h"
|
|
#include "lib.h"
|
|
#include "dat.h"
|
|
#include "fns.h"
|
|
#include "error.h"
|
|
|
|
void
|
|
sleep(Rendez *r, int (*f)(void*), void *arg)
|
|
{
|
|
int s;
|
|
|
|
s = splhi();
|
|
|
|
lock(&r->lk);
|
|
lock(&up->rlock);
|
|
if(r->p){
|
|
print("double sleep %lud %lud\n", r->p->pid, up->pid);
|
|
dumpstack();
|
|
}
|
|
|
|
/*
|
|
* Wakeup only knows there may be something to do by testing
|
|
* r->p in order to get something to lock on.
|
|
* Flush that information out to memory in case the sleep is
|
|
* committed.
|
|
*/
|
|
r->p = up;
|
|
|
|
if((*f)(arg) || up->notepending){
|
|
/*
|
|
* if condition happened or a note is pending
|
|
* never mind
|
|
*/
|
|
r->p = nil;
|
|
unlock(&up->rlock);
|
|
unlock(&r->lk);
|
|
} else {
|
|
/*
|
|
* now we are committed to
|
|
* change state and call scheduler
|
|
*/
|
|
up->state = Wakeme;
|
|
up->r = r;
|
|
|
|
/* statistics */
|
|
/* m->cs++; */
|
|
|
|
unlock(&up->rlock);
|
|
unlock(&r->lk);
|
|
|
|
procsleep();
|
|
}
|
|
|
|
if(up->notepending) {
|
|
up->notepending = 0;
|
|
splx(s);
|
|
error(Eintr);
|
|
}
|
|
|
|
splx(s);
|
|
}
|
|
|
|
Proc*
|
|
wakeup(Rendez *r)
|
|
{
|
|
Proc *p;
|
|
int s;
|
|
|
|
s = splhi();
|
|
|
|
lock(&r->lk);
|
|
p = r->p;
|
|
|
|
if(p != nil){
|
|
lock(&p->rlock);
|
|
if(p->state != Wakeme || p->r != r)
|
|
panic("wakeup: state");
|
|
r->p = nil;
|
|
p->r = nil;
|
|
p->state = Running;
|
|
procwakeup(p);
|
|
unlock(&p->rlock);
|
|
}
|
|
unlock(&r->lk);
|
|
|
|
splx(s);
|
|
|
|
return p;
|
|
}
|
|
|