1 #include "dat.h"
2 #include "fns.h"
3 #include "error.h"
4 #include "interp.h"
5
6 Proc*
newproc(void)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
Sleep(Rendez * r,int (* f)(void *),void * arg)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
Wakeup(Rendez * r)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
swiproc(Proc * p,int interp)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
notkilled(void)121 notkilled(void)
122 {
123 lock(&up->rlock);
124 up->killed = 0;
125 unlock(&up->rlock);
126 }
127
128 void
osenter(void)129 osenter(void)
130 {
131 up->syscall = 1;
132 }
133
134 void
osleave(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
rptwakeup(void * o,void * ar)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
rptactive(void * a)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
rproc(void * a)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*
rptproc(char * s,int t,void * o,int (* active)(void *),int (* ck)(void *,int),void (* f)(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