1 #include "dat.h" 2 #include "fns.h" 3 #include "error.h" 4 5 enum 6 { 7 KSTACK = 16*1024, 8 DELETE = 0x7F, 9 }; 10 11 Proc **Xup; 12 13 extern void killrefresh(void); 14 extern void tramp(char*, void (*)(void*), void*); 15 16 extern int usenewwin; 17 18 int *ustack; /* address on unshared stack: see vstack in asm*.s */ 19 extern int dflag; 20 char *hosttype = "Plan9"; 21 char *cputype; 22 23 void 24 osblock(void) 25 { 26 rendezvous(up, nil); 27 } 28 29 void 30 osready(Proc *p) 31 { 32 rendezvous(p, nil); 33 } 34 35 void 36 pexit(char *msg, int) 37 { 38 Osenv *e; 39 40 USED(msg); 41 42 lock(&procs.l); 43 if(up->prev) 44 up->prev->next = up->next; 45 else 46 procs.head = up->next; 47 48 if(up->next) 49 up->next->prev = up->prev; 50 else 51 procs.tail = up->prev; 52 unlock(&procs.l); 53 54 /* print("pexit: %s: %s\n", up->text, msg); /**/ 55 e = up->env; 56 if(e != nil) { 57 closefgrp(e->fgrp); 58 closepgrp(e->pgrp); 59 closeegrp(e->egrp); 60 closesigs(e->sigs); 61 } 62 free(e->user); 63 free(up->prog); 64 up->prog = nil; 65 up->type = Moribund; 66 longjmp(up->privstack, 1); 67 } 68 69 int 70 kproc(char *name, void (*func)(void*), void *arg, int flags) 71 { 72 int pid; 73 Proc *p; 74 Pgrp *pg; 75 Fgrp *fg; 76 Egrp *eg; 77 78 p = newproc(); 79 if(p == nil) 80 panic("kproc: no memory"); 81 p->kstack = mallocz(KSTACK, 0); 82 if(p->kstack == nil) 83 panic("kproc: no memory"); 84 85 if(flags & KPDUPPG) { 86 pg = up->env->pgrp; 87 incref(&pg->r); 88 p->env->pgrp = pg; 89 } 90 if(flags & KPDUPFDG) { 91 fg = up->env->fgrp; 92 incref(&fg->r); 93 p->env->fgrp = fg; 94 } 95 if(flags & KPDUPENVG) { 96 eg = up->env->egrp; 97 incref(&eg->r); 98 p->env->egrp = eg; 99 } 100 101 p->env->uid = up->env->uid; 102 p->env->gid = up->env->gid; 103 kstrdup(&p->env->user, up->env->user); 104 105 strcpy(p->text, name); 106 107 p->func = func; 108 p->arg = arg; 109 110 lock(&procs.l); 111 if(procs.tail != nil) { 112 p->prev = procs.tail; 113 procs.tail->next = p; 114 } 115 else { 116 procs.head = p; 117 p->prev = nil; 118 } 119 procs.tail = p; 120 unlock(&procs.l); 121 122 /* 123 * switch back to the unshared stack to do the fork 124 * only the parent returns from kproc 125 */ 126 up->kid = p; 127 up->kidsp = p->kstack; 128 pid = setjmp(up->sharestack); 129 if(pid == 0) 130 longjmp(up->privstack, 1); 131 return pid; 132 } 133 134 void 135 traphandler(void *reg, char *msg) 136 { 137 int intwait; 138 139 intwait = up->intwait; 140 up->intwait = 0; 141 /* Ignore pipe writes from devcmd */ 142 if(strstr(msg, "write on closed pipe") != nil) 143 noted(NCONT); 144 145 if(sflag) { 146 if(intwait && strcmp(msg, Eintr) == 0) 147 noted(NCONT); 148 else 149 noted(NDFLT); 150 } 151 if(intwait == 0) 152 disfault(reg, msg); 153 noted(NCONT); 154 } 155 156 int 157 readfile(char *path, char *buf, int n) 158 { 159 int fd; 160 161 fd = open(path, OREAD); 162 if(fd >= 0) { 163 n = read(fd, buf, n-1); 164 if(n > 0) /* both calls to readfile() have a ``default'' */ 165 buf[n] = '\0'; 166 close(fd); 167 return n; 168 } 169 return 0; 170 } 171 172 static void 173 dobinds(void) 174 { 175 char dir[MAXROOT+9]; 176 177 snprint(dir, sizeof(dir), "%s/net", rootdir); 178 bind("/net", dir, MREPL); 179 180 snprint(dir, sizeof(dir), "%s/net.alt", rootdir); 181 bind("/net.alt", dir, MREPL); 182 183 snprint(dir, sizeof(dir), "%s/dev", rootdir); 184 bind("#t", dir, MAFTER); 185 bind("#A", dir, MAFTER); 186 } 187 188 void 189 libinit(char *imod) 190 { 191 char *sp; 192 Proc *xup, *p; 193 int fd, n, pid; 194 char nbuf[64]; 195 196 xup = nil; 197 Xup = &xup; 198 199 /* 200 * setup personality 201 */ 202 if(readfile("/dev/user", nbuf, sizeof nbuf)) 203 kstrdup(&eve, nbuf); 204 if(readfile("/dev/sysname", nbuf, sizeof nbuf)) 205 kstrdup(&ossysname, nbuf); 206 if(readfile("/env/cputype", nbuf, sizeof nbuf)) 207 kstrdup(&cputype, nbuf); 208 209 /* 210 * guess at a safe stack for vstack 211 */ 212 ustack = &fd; 213 214 rfork(RFNAMEG|RFREND); 215 216 if(!dflag){ 217 fd = open("/dev/consctl", OWRITE); 218 if(fd < 0) 219 fprint(2, "libinit: open /dev/consctl: %r\n"); 220 n = write(fd, "rawon", 5); 221 if(n != 5) 222 fprint(2, "keyboard rawon (n=%d, %r)\n", n); 223 } 224 225 osmillisec(); /* set the epoch */ 226 dobinds(); 227 228 notify(traphandler); 229 230 /* 231 * dummy up a up and stack so the first proc 232 * calls emuinit after setting up his private jmp_buf 233 */ 234 p = newproc(); 235 p->kstack = mallocz(KSTACK, 0); 236 if(p == nil || p->kstack == nil) 237 panic("libinit: no memory"); 238 sp = p->kstack; 239 p->func = emuinit; 240 p->arg = imod; 241 242 /* 243 * set up a stack for forking kids on separate stacks. 244 * longjmp back here from kproc. 245 */ 246 while(setjmp(p->privstack)){ 247 if(up->type == Moribund){ 248 free(up->kstack); 249 free(up); 250 _exits(""); 251 } 252 p = up->kid; 253 sp = up->kidsp; 254 up->kid = nil; 255 switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){ 256 case 0: 257 /* 258 * send the kid around the loop to set up his private jmp_buf 259 */ 260 break; 261 default: 262 /* 263 * parent just returns to his shared stack in kproc 264 */ 265 longjmp(up->sharestack, pid); 266 panic("longjmp failed"); 267 } 268 } 269 270 /* 271 * you get here only once per Proc 272 * go to the shared memory stack 273 */ 274 up = p; 275 up->pid = up->sigid = getpid(); 276 tramp(sp+KSTACK, up->func, up->arg); 277 panic("tramp returned"); 278 } 279 280 void 281 oshostintr(Proc *p) 282 { 283 postnote(PNPROC, p->sigid, Eintr); 284 } 285 286 void 287 oslongjmp(void *regs, osjmpbuf env, int val) 288 { 289 if(regs != nil) 290 notejmp(regs, env, val); 291 else 292 longjmp(env, val); 293 } 294 295 void 296 osreboot(char*, char**) 297 { 298 } 299 300 void 301 cleanexit(int x) 302 { 303 USED(x); 304 killrefresh(); 305 postnote(PNGROUP, getpid(), "interrupt"); 306 exits("interrupt"); 307 } 308 309 int 310 readkbd(void) 311 { 312 int n; 313 char buf[1]; 314 315 n = read(0, buf, sizeof(buf)); 316 if(n < 0) 317 fprint(2, "emu: keyboard read error: %r\n"); 318 if(n <= 0) 319 pexit("keyboard", 0); 320 switch(buf[0]) { 321 case DELETE: 322 cleanexit(0); 323 case '\r': 324 buf[0] = '\n'; 325 } 326 return buf[0]; 327 } 328 329 static vlong 330 b2v(uchar *p) 331 { 332 int i; 333 vlong v; 334 335 v = 0; 336 for(i=0; i<sizeof(uvlong); i++) 337 v = (v<<8)|p[i]; 338 return v; 339 } 340 341 vlong 342 nsec(void) 343 { 344 int n; 345 static int nsecfd = -1; 346 uchar buf[sizeof(uvlong)]; 347 348 if(nsecfd < 0){ 349 nsecfd = open("/dev/bintime", OREAD|OCEXEC); /* never closed */ 350 if(nsecfd<0){ 351 fprint(2,"can't open /dev/bintime: %r\n"); 352 return 0; 353 } 354 } 355 n = read(nsecfd, buf, sizeof(buf)); 356 if(n!=sizeof(buf)) { 357 fprint(2,"read err on /dev/bintime: %r\n"); 358 return 0; 359 } 360 return b2v(buf); 361 } 362 363 long 364 osmillisec(void) 365 { 366 static vlong nsec0 = 0; 367 368 if(nsec0 == 0){ 369 nsec0 = nsec(); 370 return 0; 371 } 372 return (nsec()-nsec0)/1000000; 373 } 374 375 /* 376 * Return the time since the epoch in microseconds 377 * The epoch is defined at 1 Jan 1970 378 */ 379 vlong 380 osusectime(void) 381 { 382 return nsec()/1000; 383 } 384 385 int 386 osmillisleep(ulong milsec) 387 { 388 sleep(milsec); 389 return 0; 390 } 391 392 int 393 limbosleep(ulong milsec) 394 { 395 return osmillisleep(milsec); 396 } 397 398 void 399 osyield(void) 400 { 401 sleep(0); 402 } 403 404 void 405 ospause(void) 406 { 407 for(;;) 408 sleep(1000000); 409 } 410 411 void 412 oslopri(void) 413 { 414 int fd; 415 char buf[32]; 416 417 snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid()); 418 if((fd = open(buf, OWRITE)) >= 0){ 419 fprint(fd, "pri 8"); 420 close(fd); 421 } 422 } 423