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 kproc1(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 kproc(char *name, void (*func)(void*), void *arg, int flags) 136 { 137 kproc1(name, func, arg, flags); 138 } 139 140 void 141 traphandler(void *reg, char *msg) 142 { 143 int intwait; 144 145 intwait = up->intwait; 146 up->intwait = 0; 147 /* Ignore pipe writes from devcmd */ 148 if(strstr(msg, "write on closed pipe") != nil) 149 noted(NCONT); 150 151 if(sflag) { 152 if(intwait && strcmp(msg, Eintr) == 0) 153 noted(NCONT); 154 else 155 noted(NDFLT); 156 } 157 if(intwait == 0) 158 disfault(reg, msg); 159 noted(NCONT); 160 } 161 162 int 163 readfile(char *path, char *buf, int n) 164 { 165 int fd; 166 167 fd = open(path, OREAD); 168 if(fd >= 0) { 169 n = read(fd, buf, n-1); 170 if(n > 0) /* both calls to readfile() have a ``default'' */ 171 buf[n] = '\0'; 172 close(fd); 173 return n; 174 } 175 return 0; 176 } 177 178 static void 179 dobinds(void) 180 { 181 char dir[MAXROOT+9]; 182 183 snprint(dir, sizeof(dir), "%s/net", rootdir); 184 bind("/net", dir, MREPL); 185 186 snprint(dir, sizeof(dir), "%s/net.alt", rootdir); 187 bind("/net.alt", dir, MREPL); 188 189 snprint(dir, sizeof(dir), "%s/dev", rootdir); 190 bind("#t", dir, MAFTER); 191 bind("#A", dir, MAFTER); 192 } 193 194 void 195 libinit(char *imod) 196 { 197 char *sp; 198 Proc *xup, *p; 199 int fd, n, pid; 200 char nbuf[64]; 201 202 xup = nil; 203 Xup = &xup; 204 205 /* 206 * setup personality 207 */ 208 if(readfile("/dev/user", nbuf, sizeof nbuf)) 209 kstrdup(&eve, nbuf); 210 if(readfile("/dev/sysname", nbuf, sizeof nbuf)) 211 kstrdup(&ossysname, nbuf); 212 if(readfile("/env/cputype", nbuf, sizeof nbuf)) 213 kstrdup(&cputype, nbuf); 214 215 /* 216 * guess at a safe stack for vstack 217 */ 218 ustack = &fd; 219 220 rfork(RFNAMEG|RFREND); 221 222 if(!dflag){ 223 fd = open("/dev/consctl", OWRITE); 224 if(fd < 0) 225 fprint(2, "libinit: open /dev/consctl: %r\n"); 226 n = write(fd, "rawon", 5); 227 if(n != 5) 228 fprint(2, "keyboard rawon (n=%d, %r)\n", n); 229 } 230 231 osmillisec(); /* set the epoch */ 232 dobinds(); 233 234 notify(traphandler); 235 236 /* 237 * dummy up a up and stack so the first proc 238 * calls emuinit after setting up his private jmp_buf 239 */ 240 p = newproc(); 241 p->kstack = mallocz(KSTACK, 0); 242 if(p == nil || p->kstack == nil) 243 panic("libinit: no memory"); 244 sp = p->kstack; 245 p->func = emuinit; 246 p->arg = imod; 247 248 /* 249 * set up a stack for forking kids on separate stacks. 250 * longjmp back here from kproc. 251 */ 252 while(setjmp(p->privstack)){ 253 if(up->type == Moribund){ 254 free(up->kstack); 255 free(up); 256 _exits(""); 257 } 258 p = up->kid; 259 sp = up->kidsp; 260 up->kid = nil; 261 switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){ 262 case 0: 263 /* 264 * send the kid around the loop to set up his private jmp_buf 265 */ 266 break; 267 default: 268 /* 269 * parent just returns to his shared stack in kproc 270 */ 271 longjmp(up->sharestack, pid); 272 panic("longjmp failed"); 273 } 274 } 275 276 /* 277 * you get here only once per Proc 278 * go to the shared memory stack 279 */ 280 up = p; 281 up->pid = up->sigid = getpid(); 282 tramp(sp+KSTACK, up->func, up->arg); 283 panic("tramp returned"); 284 } 285 286 void 287 oshostintr(Proc *p) 288 { 289 postnote(PNPROC, p->sigid, Eintr); 290 } 291 292 void 293 oslongjmp(void *regs, osjmpbuf env, int val) 294 { 295 if(regs != nil) 296 notejmp(regs, env, val); 297 else 298 longjmp(env, val); 299 } 300 301 void 302 osreboot(char*, char**) 303 { 304 } 305 306 void 307 cleanexit(int x) 308 { 309 USED(x); 310 killrefresh(); 311 postnote(PNGROUP, getpid(), "interrupt"); 312 exits("interrupt"); 313 } 314 315 int 316 readkbd(void) 317 { 318 int n; 319 char buf[1]; 320 321 n = read(0, buf, sizeof(buf)); 322 if(n < 0) 323 fprint(2, "emu: keyboard read error: %r\n"); 324 if(n <= 0) 325 pexit("keyboard", 0); 326 switch(buf[0]) { 327 case DELETE: 328 cleanexit(0); 329 case '\r': 330 buf[0] = '\n'; 331 } 332 return buf[0]; 333 } 334 335 static vlong 336 b2v(uchar *p) 337 { 338 int i; 339 vlong v; 340 341 v = 0; 342 for(i=0; i<sizeof(uvlong); i++) 343 v = (v<<8)|p[i]; 344 return v; 345 } 346 347 vlong 348 nsec(void) 349 { 350 int n; 351 static int nsecfd = -1; 352 uchar buf[sizeof(uvlong)]; 353 354 if(nsecfd < 0){ 355 nsecfd = open("/dev/bintime", OREAD|OCEXEC); /* never closed */ 356 if(nsecfd<0){ 357 fprint(2,"can't open /dev/bintime: %r\n"); 358 return 0; 359 } 360 } 361 n = read(nsecfd, buf, sizeof(buf)); 362 if(n!=sizeof(buf)) { 363 fprint(2,"read err on /dev/bintime: %r\n"); 364 return 0; 365 } 366 return b2v(buf); 367 } 368 369 long 370 osmillisec(void) 371 { 372 static vlong nsec0 = 0; 373 374 if(nsec0 == 0){ 375 nsec0 = nsec(); 376 return 0; 377 } 378 return (nsec()-nsec0)/1000000; 379 } 380 381 /* 382 * Return the time since the epoch in microseconds 383 * The epoch is defined at 1 Jan 1970 384 */ 385 vlong 386 osusectime(void) 387 { 388 return nsec()/1000; 389 } 390 391 int 392 osmillisleep(ulong milsec) 393 { 394 sleep(milsec); 395 return 0; 396 } 397 398 int 399 limbosleep(ulong milsec) 400 { 401 return osmillisleep(milsec); 402 } 403 404 void 405 osyield(void) 406 { 407 sleep(0); 408 } 409 410 void 411 ospause(void) 412 { 413 for(;;) 414 sleep(1000000); 415 } 416 417 void 418 oslopri(void) 419 { 420 int fd; 421 char buf[32]; 422 423 snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid()); 424 if((fd = open(buf, OWRITE)) >= 0){ 425 fprint(fd, "pri 8"); 426 close(fd); 427 } 428 } 429