ref: 2459e34d77e2e21ef829c0dfaafd99433899494f
dir: /emu/port/proc.c/
#include "dat.h"
#include "fns.h"
#include "error.h"
#include "interp.h"
Proc*
newproc(void)
{
Proc *p;
p = malloc(sizeof(Proc));
if(p == nil)
return nil;
p->type = Unknown;
p->killed = 0;
p->swipend = 0;
p->env = &p->defenv;
kstrdup(&p->env->user, "*nouser");
p->env->errstr = p->env->errbuf0;
p->env->syserrstr = p->env->errbuf1;
addprog(p);
return p;
}
void
Sleep(Rendez *r, int (*f)(void*), void *arg)
{
lock(&up->rlock);
lock(&r->l);
/*
* if interrupted or condition happened, never mind
*/
if(up->killed || f(arg)) {
unlock(&r->l);
}else{
if(r->p != nil)
panic("double sleep pc=0x%lux %s[%lud] %s[%lud] r=0x%lux\n", getcallerpc(&r), r->p->text, r->p->pid, up->text, up->pid, r);
r->p = up;
unlock(&r->l);
up->swipend = 0;
up->r = r; /* for swiproc */
unlock(&up->rlock);
osblock();
lock(&up->rlock);
up->r = nil;
}
if(up->killed || up->swipend) {
up->killed = 0;
up->swipend = 0;
unlock(&up->rlock);
error(Eintr);
}
unlock(&up->rlock);
}
int
Wakeup(Rendez *r)
{
Proc *p;
lock(&r->l);
p = r->p;
if(p != nil) {
r->p = nil;
osready(p);
}
unlock(&r->l);
return p != nil;
}
void
swiproc(Proc *p, int interp)
{
Rendez *r;
if(p == nil)
return;
/*
* Pull out of emu Sleep
*/
lock(&p->rlock);
if(!interp)
p->killed = 1;
r = p->r;
if(r != nil) {
lock(&r->l);
if(r->p == p){
p->swipend = 1;
r->p = nil;
osready(p);
}
unlock(&r->l);
unlock(&p->rlock);
return;
}
unlock(&p->rlock);
/*
* Maybe pull out of Host OS
*/
lock(&p->sysio);
if(p->syscall && p->intwait == 0) {
p->swipend = 1;
p->intwait = 1;
unlock(&p->sysio);
oshostintr(p);
return;
}
unlock(&p->sysio);
}
void
notkilled(void)
{
lock(&up->rlock);
up->killed = 0;
unlock(&up->rlock);
}
void
osenter(void)
{
up->syscall = 1;
}
void
osleave(void)
{
int r;
lock(&up->rlock);
r = up->swipend;
up->swipend = 0;
unlock(&up->rlock);
lock(&up->sysio);
up->syscall = 0;
unlock(&up->sysio);
/* Cleared by the signal/note/exception handler */
while(up->intwait)
osyield();
if(r != 0)
error(Eintr);
}
void
rptwakeup(void *o, void *ar)
{
Rept *r;
r = ar;
if(r == nil)
return;
lock(&r->l);
r->o = o;
unlock(&r->l);
Wakeup(&r->r);
}
static int
rptactive(void *a)
{
Rept *r = a;
int i;
lock(&r->l);
i = r->active(r->o);
unlock(&r->l);
return i;
}
static void
rproc(void *a)
{
long now, then;
ulong t;
int i;
void *o;
Rept *r;
up->env->fgrp = newfgrp(nil);
r = a;
t = (ulong)r->t;
Wait:
Sleep(&r->r, rptactive, r);
lock(&r->l);
o = r->o;
unlock(&r->l);
then = osmillisec();
for(;;){
osmillisleep(t);
now = osmillisec();
if(waserror())
break;
i = r->ck(o, now-then);
poperror();
if(i == -1)
goto Wait;
if(i == 0)
continue;
then = now;
acquire();
if(waserror()) {
release();
break;
}
r->f(o);
poperror();
release();
}
pexit("", 0);
}
void*
rptproc(char *s, int t, void *o, int (*active)(void*), int (*ck)(void*, int), void (*f)(void*))
{
Rept *r;
r = mallocz(sizeof(Rept), 1);
if(r == nil)
return nil;
r->t = t;
r->active = active;
r->ck = ck;
r->f = f;
r->o = o;
kproc(s, rproc, r, KPDUPPG);
return r;
}