summaryrefslogtreecommitdiff
path: root/emu/port/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'emu/port/proc.c')
-rw-r--r--emu/port/proc.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/emu/port/proc.c b/emu/port/proc.c
new file mode 100644
index 00000000..fccf1a36
--- /dev/null
+++ b/emu/port/proc.c
@@ -0,0 +1,239 @@
+#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;
+}