1 #include "dat.h" 2 #include "fns.h" 3 #include "error.h" 4 #include "interp.h" 5 6 Proc* 7 newproc(void) 8 { 9 Proc *p; 10 11 p = malloc(sizeof(Proc)); 12 if(p == nil) 13 return nil; 14 15 p->type = Unknown; 16 p->killed = 0; 17 p->swipend = 0; 18 p->env = &p->defenv; 19 kstrdup(&p->env->user, "*nouser"); 20 p->env->errstr = p->env->errbuf0; 21 p->env->syserrstr = p->env->errbuf1; 22 addprog(p); 23 24 return p; 25 } 26 27 void 28 Sleep(Rendez *r, int (*f)(void*), void *arg) 29 { 30 lock(&up->rlock); 31 lock(&r->l); 32 33 /* 34 * if interrupted or condition happened, never mind 35 */ 36 if(up->killed || f(arg)) { 37 unlock(&r->l); 38 }else{ 39 if(r->p != nil) 40 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); 41 42 r->p = up; 43 unlock(&r->l); 44 up->swipend = 0; 45 up->r = r; /* for swiproc */ 46 unlock(&up->rlock); 47 48 osblock(); 49 50 lock(&up->rlock); 51 up->r = nil; 52 } 53 54 if(up->killed || up->swipend) { 55 up->killed = 0; 56 up->swipend = 0; 57 unlock(&up->rlock); 58 error(Eintr); 59 } 60 unlock(&up->rlock); 61 } 62 63 int 64 Wakeup(Rendez *r) 65 { 66 Proc *p; 67 68 lock(&r->l); 69 p = r->p; 70 if(p != nil) { 71 r->p = nil; 72 osready(p); 73 } 74 unlock(&r->l); 75 return p != nil; 76 } 77 78 void 79 swiproc(Proc *p, int interp) 80 { 81 Rendez *r; 82 83 if(p == nil) 84 return; 85 86 /* 87 * Pull out of emu Sleep 88 */ 89 lock(&p->rlock); 90 if(!interp) 91 p->killed = 1; 92 r = p->r; 93 if(r != nil) { 94 lock(&r->l); 95 if(r->p == p){ 96 p->swipend = 1; 97 r->p = nil; 98 osready(p); 99 } 100 unlock(&r->l); 101 unlock(&p->rlock); 102 return; 103 } 104 unlock(&p->rlock); 105 106 /* 107 * Maybe pull out of Host OS 108 */ 109 lock(&p->sysio); 110 if(p->syscall && p->intwait == 0) { 111 p->swipend = 1; 112 p->intwait = 1; 113 unlock(&p->sysio); 114 oshostintr(p); 115 return; 116 } 117 unlock(&p->sysio); 118 } 119 120 void 121 notkilled(void) 122 { 123 lock(&up->rlock); 124 up->killed = 0; 125 unlock(&up->rlock); 126 } 127 128 void 129 osenter(void) 130 { 131 up->syscall = 1; 132 } 133 134 void 135 osleave(void) 136 { 137 int r; 138 139 lock(&up->rlock); 140 r = up->swipend; 141 up->swipend = 0; 142 unlock(&up->rlock); 143 144 lock(&up->sysio); 145 up->syscall = 0; 146 unlock(&up->sysio); 147 148 /* Cleared by the signal/note/exception handler */ 149 while(up->intwait) 150 osyield(); 151 152 if(r != 0) 153 error(Eintr); 154 } 155 156 void 157 rptwakeup(void *o, void *ar) 158 { 159 Rept *r; 160 161 r = ar; 162 if(r == nil) 163 return; 164 lock(&r->l); 165 r->o = o; 166 unlock(&r->l); 167 Wakeup(&r->r); 168 } 169 170 static int 171 rptactive(void *a) 172 { 173 Rept *r = a; 174 int i; 175 lock(&r->l); 176 i = r->active(r->o); 177 unlock(&r->l); 178 return i; 179 } 180 181 static void 182 rproc(void *a) 183 { 184 long now, then; 185 ulong t; 186 int i; 187 void *o; 188 Rept *r; 189 190 up->env->fgrp = newfgrp(nil); 191 r = a; 192 t = (ulong)r->t; 193 194 Wait: 195 Sleep(&r->r, rptactive, r); 196 lock(&r->l); 197 o = r->o; 198 unlock(&r->l); 199 then = osmillisec(); 200 for(;;){ 201 osmillisleep(t); 202 now = osmillisec(); 203 if(waserror()) 204 break; 205 i = r->ck(o, now-then); 206 poperror(); 207 if(i == -1) 208 goto Wait; 209 if(i == 0) 210 continue; 211 then = now; 212 acquire(); 213 if(waserror()) { 214 release(); 215 break; 216 } 217 r->f(o); 218 poperror(); 219 release(); 220 } 221 pexit("", 0); 222 } 223 224 void* 225 rptproc(char *s, int t, void *o, int (*active)(void*), int (*ck)(void*, int), void (*f)(void*)) 226 { 227 Rept *r; 228 229 r = mallocz(sizeof(Rept), 1); 230 if(r == nil) 231 return nil; 232 r->t = t; 233 r->active = active; 234 r->ck = ck; 235 r->f = f; 236 r->o = o; 237 kproc(s, rproc, r, KPDUPPG); 238 return r; 239 } 240