13e12c5d1SDavid du Colombier #include "u.h" 23e12c5d1SDavid du Colombier #include "../port/lib.h" 33e12c5d1SDavid du Colombier #include "mem.h" 43e12c5d1SDavid du Colombier #include "dat.h" 53e12c5d1SDavid du Colombier #include "fns.h" 63e12c5d1SDavid du Colombier #include "../port/error.h" 73e12c5d1SDavid du Colombier 83e12c5d1SDavid du Colombier #include <a.out.h> 93e12c5d1SDavid du Colombier 103e12c5d1SDavid du Colombier int shargs(char*, int, char**); 113e12c5d1SDavid du Colombier 123e12c5d1SDavid du Colombier long 133e12c5d1SDavid du Colombier sysr1(ulong *arg) 143e12c5d1SDavid du Colombier { 153e12c5d1SDavid du Colombier xsummary(); 163e12c5d1SDavid du Colombier print("[%s %s %d] r1 = %d\n", u->p->user, u->p->text, u->p->pid, arg[0]); 173e12c5d1SDavid du Colombier return 0; 183e12c5d1SDavid du Colombier } 193e12c5d1SDavid du Colombier 203e12c5d1SDavid du Colombier long 213e12c5d1SDavid du Colombier sysrfork(ulong *arg) 223e12c5d1SDavid du Colombier { 233e12c5d1SDavid du Colombier KMap *k; 243e12c5d1SDavid du Colombier Pgrp *opg; 253e12c5d1SDavid du Colombier Egrp *oeg; 263e12c5d1SDavid du Colombier Fgrp *ofg; 273e12c5d1SDavid du Colombier int n, i; 283e12c5d1SDavid du Colombier Proc *p, *parent; 293e12c5d1SDavid du Colombier ulong upa, pid, flag; 303e12c5d1SDavid du Colombier /* 313e12c5d1SDavid du Colombier * used to compute last valid system stack address for copy 323e12c5d1SDavid du Colombier */ 333e12c5d1SDavid du Colombier int lastvar; 343e12c5d1SDavid du Colombier 353e12c5d1SDavid du Colombier flag = arg[0]; 363e12c5d1SDavid du Colombier p = u->p; 373e12c5d1SDavid du Colombier if((flag&RFPROC) == 0) { 383e12c5d1SDavid du Colombier if(flag & (RFNAMEG|RFCNAMEG)) { 393e12c5d1SDavid du Colombier if((flag & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG)) 403e12c5d1SDavid du Colombier error(Ebadarg); 413e12c5d1SDavid du Colombier opg = p->pgrp; 423e12c5d1SDavid du Colombier p->pgrp = newpgrp(); 433e12c5d1SDavid du Colombier if(flag & RFNAMEG) 443e12c5d1SDavid du Colombier pgrpcpy(p->pgrp, opg); 453e12c5d1SDavid du Colombier closepgrp(opg); 463e12c5d1SDavid du Colombier } 473e12c5d1SDavid du Colombier if(flag & (RFENVG|RFCENVG)) { 483e12c5d1SDavid du Colombier if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG)) 493e12c5d1SDavid du Colombier error(Ebadarg); 503e12c5d1SDavid du Colombier oeg = p->egrp; 513e12c5d1SDavid du Colombier p->egrp = smalloc(sizeof(Egrp)); 523e12c5d1SDavid du Colombier p->egrp->ref = 1; 533e12c5d1SDavid du Colombier if(flag & RFENVG) 543e12c5d1SDavid du Colombier envcpy(p->egrp, oeg); 553e12c5d1SDavid du Colombier closeegrp(oeg); 563e12c5d1SDavid du Colombier } 573e12c5d1SDavid du Colombier if(flag & RFFDG) { 583e12c5d1SDavid du Colombier ofg = p->fgrp; 593e12c5d1SDavid du Colombier p->fgrp = dupfgrp(ofg); 603e12c5d1SDavid du Colombier closefgrp(ofg); 613e12c5d1SDavid du Colombier } 623e12c5d1SDavid du Colombier else 633e12c5d1SDavid du Colombier if(flag & RFCFDG) { 643e12c5d1SDavid du Colombier ofg = p->fgrp; 653e12c5d1SDavid du Colombier p->fgrp = smalloc(sizeof(Fgrp)); 663e12c5d1SDavid du Colombier p->fgrp->ref = 1; 673e12c5d1SDavid du Colombier closefgrp(ofg); 683e12c5d1SDavid du Colombier } 693e12c5d1SDavid du Colombier if(flag & RFNOTEG) 703e12c5d1SDavid du Colombier p->noteid = incref(¬eidalloc); 713e12c5d1SDavid du Colombier if(flag & (RFMEM|RFNOWAIT)) 723e12c5d1SDavid du Colombier error(Ebadarg); 733e12c5d1SDavid du Colombier return 0; 743e12c5d1SDavid du Colombier } 753e12c5d1SDavid du Colombier /* Check flags before we commit */ 763e12c5d1SDavid du Colombier if((flag & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG)) 773e12c5d1SDavid du Colombier error(Ebadarg); 783e12c5d1SDavid du Colombier if((flag & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG)) 793e12c5d1SDavid du Colombier error(Ebadarg); 803e12c5d1SDavid du Colombier if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG)) 813e12c5d1SDavid du Colombier error(Ebadarg); 823e12c5d1SDavid du Colombier 833e12c5d1SDavid du Colombier p = newproc(); 843e12c5d1SDavid du Colombier parent = u->p; 853e12c5d1SDavid du Colombier 863e12c5d1SDavid du Colombier /* Page va of upage used as check in mapstack */ 873e12c5d1SDavid du Colombier p->upage = newpage(0, 0, USERADDR|(p->pid&0xFFFF)); 883e12c5d1SDavid du Colombier k = kmap(p->upage); 893e12c5d1SDavid du Colombier upa = VA(k); 903e12c5d1SDavid du Colombier 913e12c5d1SDavid du Colombier /* Save time: only copy u-> data and useful stack */ 923e12c5d1SDavid du Colombier memmove((void*)upa, u, sizeof(User)); 933e12c5d1SDavid du Colombier n = USERADDR+BY2PG - (ulong)&lastvar; 943e12c5d1SDavid du Colombier n = (n+32) & ~(BY2WD-1); 953e12c5d1SDavid du Colombier memmove((void*)(upa+BY2PG-n), (void*)(USERADDR+BY2PG-n), n); 963e12c5d1SDavid du Colombier ((User *)upa)->p = p; 973e12c5d1SDavid du Colombier kunmap(k); 983e12c5d1SDavid du Colombier 993e12c5d1SDavid du Colombier /* Make a new set of memory segments */ 1003e12c5d1SDavid du Colombier n = flag & RFMEM; 1013e12c5d1SDavid du Colombier for(i = 0; i < NSEG; i++) 1023e12c5d1SDavid du Colombier if(parent->seg[i]) 103bd389b36SDavid du Colombier p->seg[i] = dupseg(parent->seg, i, n); 1043e12c5d1SDavid du Colombier 1053e12c5d1SDavid du Colombier /* Refs */ 1063e12c5d1SDavid du Colombier incref(u->dot); 1073e12c5d1SDavid du Colombier 1083e12c5d1SDavid du Colombier /* File descriptors */ 1093e12c5d1SDavid du Colombier if(flag & (RFFDG|RFCFDG)) { 1103e12c5d1SDavid du Colombier if(flag & RFFDG) 1113e12c5d1SDavid du Colombier p->fgrp = dupfgrp(parent->fgrp); 1123e12c5d1SDavid du Colombier else { 1133e12c5d1SDavid du Colombier p->fgrp = smalloc(sizeof(Fgrp)); 1143e12c5d1SDavid du Colombier p->fgrp->ref = 1; 1153e12c5d1SDavid du Colombier } 1163e12c5d1SDavid du Colombier } 1173e12c5d1SDavid du Colombier else { 1183e12c5d1SDavid du Colombier p->fgrp = parent->fgrp; 1193e12c5d1SDavid du Colombier incref(p->fgrp); 1203e12c5d1SDavid du Colombier } 1213e12c5d1SDavid du Colombier 1223e12c5d1SDavid du Colombier /* Process groups */ 1233e12c5d1SDavid du Colombier if(flag & (RFNAMEG|RFCNAMEG)) { 1243e12c5d1SDavid du Colombier p->pgrp = newpgrp(); 125bd389b36SDavid du Colombier if(flag & RFNAMEG) 1263e12c5d1SDavid du Colombier pgrpcpy(p->pgrp, parent->pgrp); 1273e12c5d1SDavid du Colombier } 1283e12c5d1SDavid du Colombier else { 1293e12c5d1SDavid du Colombier p->pgrp = parent->pgrp; 1303e12c5d1SDavid du Colombier incref(p->pgrp); 1313e12c5d1SDavid du Colombier } 1323e12c5d1SDavid du Colombier 1333e12c5d1SDavid du Colombier /* Environment group */ 1343e12c5d1SDavid du Colombier if(flag & (RFENVG|RFCENVG)) { 1353e12c5d1SDavid du Colombier p->egrp = smalloc(sizeof(Egrp)); 1363e12c5d1SDavid du Colombier p->egrp->ref = 1; 1373e12c5d1SDavid du Colombier if(flag & RFENVG) 1383e12c5d1SDavid du Colombier envcpy(p->egrp, parent->egrp); 1393e12c5d1SDavid du Colombier } 1403e12c5d1SDavid du Colombier else { 1413e12c5d1SDavid du Colombier p->egrp = parent->egrp; 1423e12c5d1SDavid du Colombier incref(p->egrp); 1433e12c5d1SDavid du Colombier } 1443e12c5d1SDavid du Colombier 1453e12c5d1SDavid du Colombier p->hang = parent->hang; 1463e12c5d1SDavid du Colombier p->procmode = parent->procmode; 1473e12c5d1SDavid du Colombier 1483e12c5d1SDavid du Colombier if(setlabel(&p->sched)){ 1493e12c5d1SDavid du Colombier /* 1503e12c5d1SDavid du Colombier * use u->p instead of p, because we don't trust the compiler, after a 1513e12c5d1SDavid du Colombier * gotolabel, to find the correct contents of a local variable. 1523e12c5d1SDavid du Colombier */ 1533e12c5d1SDavid du Colombier p = u->p; 1543e12c5d1SDavid du Colombier p->state = Running; 1553e12c5d1SDavid du Colombier p->mach = m; 1563e12c5d1SDavid du Colombier m->proc = p; 1573e12c5d1SDavid du Colombier spllo(); 1583e12c5d1SDavid du Colombier return 0; 1593e12c5d1SDavid du Colombier } 1603e12c5d1SDavid du Colombier 1613e12c5d1SDavid du Colombier p->parent = parent; 1623e12c5d1SDavid du Colombier p->parentpid = parent->pid; 1633e12c5d1SDavid du Colombier if(flag&RFNOWAIT) 1643e12c5d1SDavid du Colombier p->parentpid = 1; 1653e12c5d1SDavid du Colombier else { 1663e12c5d1SDavid du Colombier lock(&parent->exl); 1673e12c5d1SDavid du Colombier parent->nchild++; 1683e12c5d1SDavid du Colombier unlock(&parent->exl); 1693e12c5d1SDavid du Colombier } 1703e12c5d1SDavid du Colombier if((flag&RFNOTEG) == 0) 1713e12c5d1SDavid du Colombier p->noteid = parent->noteid; 1723e12c5d1SDavid du Colombier 1733e12c5d1SDavid du Colombier p->fpstate = parent->fpstate; 1743e12c5d1SDavid du Colombier pid = p->pid; 1753e12c5d1SDavid du Colombier memset(p->time, 0, sizeof(p->time)); 1763e12c5d1SDavid du Colombier p->time[TReal] = MACHP(0)->ticks; 1773e12c5d1SDavid du Colombier memmove(p->text, parent->text, NAMELEN); 1783e12c5d1SDavid du Colombier memmove(p->user, parent->user, NAMELEN); 1793e12c5d1SDavid du Colombier /* 1803e12c5d1SDavid du Colombier * since the bss/data segments are now shareable, 1813e12c5d1SDavid du Colombier * any mmu info about this process is now stale 1823e12c5d1SDavid du Colombier * (i.e. has bad properties) and has to be discarded. 1833e12c5d1SDavid du Colombier */ 1843e12c5d1SDavid du Colombier flushmmu(); 185*219b2ee8SDavid du Colombier p->priority = u->p->priority; 186*219b2ee8SDavid du Colombier p->basepri = u->p->basepri; 187*219b2ee8SDavid du Colombier p->mp = u->p->mp; 1883e12c5d1SDavid du Colombier ready(p); 189*219b2ee8SDavid du Colombier sched(); 1903e12c5d1SDavid du Colombier return pid; 1913e12c5d1SDavid du Colombier } 1923e12c5d1SDavid du Colombier 1933e12c5d1SDavid du Colombier static ulong 1943e12c5d1SDavid du Colombier l2be(long l) 1953e12c5d1SDavid du Colombier { 1963e12c5d1SDavid du Colombier uchar *cp; 1973e12c5d1SDavid du Colombier 1983e12c5d1SDavid du Colombier cp = (uchar*)&l; 1993e12c5d1SDavid du Colombier return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3]; 2003e12c5d1SDavid du Colombier } 2013e12c5d1SDavid du Colombier 2023e12c5d1SDavid du Colombier long 2033e12c5d1SDavid du Colombier sysexec(ulong *arg) 2043e12c5d1SDavid du Colombier { 2053e12c5d1SDavid du Colombier Proc *p; 2063e12c5d1SDavid du Colombier Segment *s, *ts; 2073e12c5d1SDavid du Colombier ulong t, d, b; 2083e12c5d1SDavid du Colombier int i; 2093e12c5d1SDavid du Colombier Chan *tc; 2103e12c5d1SDavid du Colombier char **argv, **argp; 2113e12c5d1SDavid du Colombier char *a, *charp, *file; 2123e12c5d1SDavid du Colombier char *progarg[sizeof(Exec)/2+1], elem[NAMELEN]; 2133e12c5d1SDavid du Colombier ulong ssize, spage, nargs, nbytes, n, bssend; 2143e12c5d1SDavid du Colombier int indir; 2153e12c5d1SDavid du Colombier Exec exec; 2163e12c5d1SDavid du Colombier char line[sizeof(Exec)]; 2173e12c5d1SDavid du Colombier Fgrp *f; 2183e12c5d1SDavid du Colombier Image *img; 2193e12c5d1SDavid du Colombier ulong magic, text, entry, data, bss; 2203e12c5d1SDavid du Colombier 2213e12c5d1SDavid du Colombier p = u->p; 2223e12c5d1SDavid du Colombier validaddr(arg[0], 1, 0); 2233e12c5d1SDavid du Colombier file = (char*)arg[0]; 2243e12c5d1SDavid du Colombier indir = 0; 2253e12c5d1SDavid du Colombier Header: 2263e12c5d1SDavid du Colombier tc = namec(file, Aopen, OEXEC, 0); 2273e12c5d1SDavid du Colombier if(waserror()){ 2283e12c5d1SDavid du Colombier close(tc); 2293e12c5d1SDavid du Colombier nexterror(); 2303e12c5d1SDavid du Colombier } 2313e12c5d1SDavid du Colombier if(!indir) 2323e12c5d1SDavid du Colombier strcpy(elem, u->elem); 2333e12c5d1SDavid du Colombier 2343e12c5d1SDavid du Colombier n = (*devtab[tc->type].read)(tc, &exec, sizeof(Exec), 0); 2353e12c5d1SDavid du Colombier if(n < 2) 2363e12c5d1SDavid du Colombier Err: 2373e12c5d1SDavid du Colombier error(Ebadexec); 2383e12c5d1SDavid du Colombier magic = l2be(exec.magic); 2393e12c5d1SDavid du Colombier text = l2be(exec.text); 2403e12c5d1SDavid du Colombier entry = l2be(exec.entry); 2413e12c5d1SDavid du Colombier if(n==sizeof(Exec) && magic==AOUT_MAGIC){ 2423e12c5d1SDavid du Colombier if((text&KZERO) 2433e12c5d1SDavid du Colombier || entry < UTZERO+sizeof(Exec) 2443e12c5d1SDavid du Colombier || entry >= UTZERO+sizeof(Exec)+text) 2453e12c5d1SDavid du Colombier goto Err; 2463e12c5d1SDavid du Colombier goto Binary; 2473e12c5d1SDavid du Colombier } 2483e12c5d1SDavid du Colombier 2493e12c5d1SDavid du Colombier /* 2503e12c5d1SDavid du Colombier * Process #! /bin/sh args ... 2513e12c5d1SDavid du Colombier */ 2523e12c5d1SDavid du Colombier memmove(line, &exec, sizeof(Exec)); 2533e12c5d1SDavid du Colombier if(indir || line[0]!='#' || line[1]!='!') 2543e12c5d1SDavid du Colombier goto Err; 2553e12c5d1SDavid du Colombier n = shargs(line, n, progarg); 2563e12c5d1SDavid du Colombier if(n == 0) 2573e12c5d1SDavid du Colombier goto Err; 2583e12c5d1SDavid du Colombier indir = 1; 2593e12c5d1SDavid du Colombier /* 2603e12c5d1SDavid du Colombier * First arg becomes complete file name 2613e12c5d1SDavid du Colombier */ 2623e12c5d1SDavid du Colombier progarg[n++] = file; 2633e12c5d1SDavid du Colombier progarg[n] = 0; 2643e12c5d1SDavid du Colombier validaddr(arg[1], BY2WD, 1); 2653e12c5d1SDavid du Colombier arg[1] += BY2WD; 2663e12c5d1SDavid du Colombier file = progarg[0]; 2673e12c5d1SDavid du Colombier progarg[0] = elem; 2683e12c5d1SDavid du Colombier poperror(); 2693e12c5d1SDavid du Colombier close(tc); 2703e12c5d1SDavid du Colombier goto Header; 2713e12c5d1SDavid du Colombier 2723e12c5d1SDavid du Colombier Binary: 2733e12c5d1SDavid du Colombier poperror(); 2743e12c5d1SDavid du Colombier data = l2be(exec.data); 2753e12c5d1SDavid du Colombier bss = l2be(exec.bss); 2763e12c5d1SDavid du Colombier t = (UTZERO+sizeof(Exec)+text+(BY2PG-1)) & ~(BY2PG-1); 2773e12c5d1SDavid du Colombier d = (t + data + (BY2PG-1)) & ~(BY2PG-1); 2783e12c5d1SDavid du Colombier bssend = t + data + bss; 2793e12c5d1SDavid du Colombier b = (bssend + (BY2PG-1)) & ~(BY2PG-1); 2803e12c5d1SDavid du Colombier if((t|d|b) & KZERO) 2813e12c5d1SDavid du Colombier error(Ebadexec); 2823e12c5d1SDavid du Colombier 2833e12c5d1SDavid du Colombier /* 2843e12c5d1SDavid du Colombier * Args: pass 1: count 2853e12c5d1SDavid du Colombier */ 2863e12c5d1SDavid du Colombier nbytes = BY2WD; /* hole for profiling clock at top of stack */ 2873e12c5d1SDavid du Colombier nargs = 0; 2883e12c5d1SDavid du Colombier if(indir){ 2893e12c5d1SDavid du Colombier argp = progarg; 2903e12c5d1SDavid du Colombier while(*argp){ 2913e12c5d1SDavid du Colombier a = *argp++; 2923e12c5d1SDavid du Colombier nbytes += strlen(a) + 1; 2933e12c5d1SDavid du Colombier nargs++; 2943e12c5d1SDavid du Colombier } 2953e12c5d1SDavid du Colombier } 2963e12c5d1SDavid du Colombier evenaddr(arg[1]); 2973e12c5d1SDavid du Colombier argp = (char**)arg[1]; 2983e12c5d1SDavid du Colombier validaddr((ulong)argp, BY2WD, 0); 2993e12c5d1SDavid du Colombier while(*argp){ 3003e12c5d1SDavid du Colombier a = *argp++; 3013e12c5d1SDavid du Colombier if(((ulong)argp&(BY2PG-1)) < BY2WD) 3023e12c5d1SDavid du Colombier validaddr((ulong)argp, BY2WD, 0); 3033e12c5d1SDavid du Colombier validaddr((ulong)a, 1, 0); 304*219b2ee8SDavid du Colombier nbytes += (vmemchr(a, 0, 0x7FFFFFFF) - a) + 1; 3053e12c5d1SDavid du Colombier nargs++; 3063e12c5d1SDavid du Colombier } 3073e12c5d1SDavid du Colombier ssize = BY2WD*(nargs+1) + ((nbytes+(BY2WD-1)) & ~(BY2WD-1)); 308bd389b36SDavid du Colombier 3093e12c5d1SDavid du Colombier /* 3103e12c5d1SDavid du Colombier * 8-byte align SP for those (e.g. sparc) that need it. 3113e12c5d1SDavid du Colombier * execregs() will subtract another 4 bytes for argc. 3123e12c5d1SDavid du Colombier */ 3133e12c5d1SDavid du Colombier if((ssize+4) & 7) 3143e12c5d1SDavid du Colombier ssize += 4; 3153e12c5d1SDavid du Colombier spage = (ssize+(BY2PG-1)) >> PGSHIFT; 3163e12c5d1SDavid du Colombier /* 3173e12c5d1SDavid du Colombier * Build the stack segment, putting it in kernel virtual for the moment 3183e12c5d1SDavid du Colombier */ 3193e12c5d1SDavid du Colombier if(spage > TSTKSIZ) 3203e12c5d1SDavid du Colombier error(Enovmem); 3213e12c5d1SDavid du Colombier 3223e12c5d1SDavid du Colombier p->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG); 3233e12c5d1SDavid du Colombier 3243e12c5d1SDavid du Colombier /* 3253e12c5d1SDavid du Colombier * Args: pass 2: assemble; the pages will be faulted in 3263e12c5d1SDavid du Colombier */ 3273e12c5d1SDavid du Colombier argv = (char**)(TSTKTOP - ssize); 3283e12c5d1SDavid du Colombier charp = (char*)(TSTKTOP - nbytes); 3293e12c5d1SDavid du Colombier if(indir) 3303e12c5d1SDavid du Colombier argp = progarg; 3313e12c5d1SDavid du Colombier else 3323e12c5d1SDavid du Colombier argp = (char**)arg[1]; 3333e12c5d1SDavid du Colombier 3343e12c5d1SDavid du Colombier for(i=0; i<nargs; i++){ 3353e12c5d1SDavid du Colombier if(indir && *argp==0) { 3363e12c5d1SDavid du Colombier indir = 0; 3373e12c5d1SDavid du Colombier argp = (char**)arg[1]; 3383e12c5d1SDavid du Colombier } 3393e12c5d1SDavid du Colombier *argv++ = charp + (USTKTOP-TSTKTOP); 3403e12c5d1SDavid du Colombier n = strlen(*argp) + 1; 3413e12c5d1SDavid du Colombier memmove(charp, *argp++, n); 3423e12c5d1SDavid du Colombier charp += n; 3433e12c5d1SDavid du Colombier } 3443e12c5d1SDavid du Colombier 3453e12c5d1SDavid du Colombier memmove(p->text, elem, NAMELEN); 3463e12c5d1SDavid du Colombier 3473e12c5d1SDavid du Colombier /* 348bd389b36SDavid du Colombier * Committed. 349bd389b36SDavid du Colombier * Free old memory. 350bd389b36SDavid du Colombier * Special segments are maintained accross exec 3513e12c5d1SDavid du Colombier */ 3523e12c5d1SDavid du Colombier for(i = SSEG; i <= BSEG; i++) { 3533e12c5d1SDavid du Colombier putseg(p->seg[i]); 354*219b2ee8SDavid du Colombier /* prevent a second free if we have an error */ 355*219b2ee8SDavid du Colombier p->seg[i] = 0; 356*219b2ee8SDavid du Colombier } 357*219b2ee8SDavid du Colombier for(i = BSEG+1; i < NSEG; i++) { 358*219b2ee8SDavid du Colombier s = p->seg[i]; 359*219b2ee8SDavid du Colombier if(s != 0 && (s->type&SG_CEXEC)) { 360*219b2ee8SDavid du Colombier putseg(s); 361*219b2ee8SDavid du Colombier p->seg[i] = 0; 362*219b2ee8SDavid du Colombier } 3633e12c5d1SDavid du Colombier } 3643e12c5d1SDavid du Colombier 3653e12c5d1SDavid du Colombier /* 3663e12c5d1SDavid du Colombier * Close on exec 3673e12c5d1SDavid du Colombier */ 3683e12c5d1SDavid du Colombier f = u->p->fgrp; 3693e12c5d1SDavid du Colombier for(i=0; i<=f->maxfd; i++) 3703e12c5d1SDavid du Colombier fdclose(i, CCEXEC); 3713e12c5d1SDavid du Colombier 3723e12c5d1SDavid du Colombier /* Text. Shared. Attaches to cache image if possible */ 3733e12c5d1SDavid du Colombier /* attachimage returns a locked cache image */ 3743e12c5d1SDavid du Colombier img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (t-UTZERO)>>PGSHIFT); 3753e12c5d1SDavid du Colombier ts = img->s; 3763e12c5d1SDavid du Colombier p->seg[TSEG] = ts; 3773e12c5d1SDavid du Colombier ts->flushme = 1; 3783e12c5d1SDavid du Colombier ts->fstart = 0; 3793e12c5d1SDavid du Colombier ts->flen = sizeof(Exec)+text; 3803e12c5d1SDavid du Colombier unlock(img); 3813e12c5d1SDavid du Colombier 3823e12c5d1SDavid du Colombier /* Data. Shared. */ 3833e12c5d1SDavid du Colombier s = newseg(SG_DATA, t, (d-t)>>PGSHIFT); 3843e12c5d1SDavid du Colombier p->seg[DSEG] = s; 3853e12c5d1SDavid du Colombier 3863e12c5d1SDavid du Colombier /* Attached by hand */ 3873e12c5d1SDavid du Colombier incref(img); 3883e12c5d1SDavid du Colombier s->image = img; 3893e12c5d1SDavid du Colombier s->fstart = ts->fstart+ts->flen; 3903e12c5d1SDavid du Colombier s->flen = data; 3913e12c5d1SDavid du Colombier 3923e12c5d1SDavid du Colombier /* BSS. Zero fill on demand */ 3933e12c5d1SDavid du Colombier p->seg[BSEG] = newseg(SG_BSS, d, (b-d)>>PGSHIFT); 3943e12c5d1SDavid du Colombier 3953e12c5d1SDavid du Colombier /* 3963e12c5d1SDavid du Colombier * Move the stack 3973e12c5d1SDavid du Colombier */ 3983e12c5d1SDavid du Colombier s = p->seg[ESEG]; 3993e12c5d1SDavid du Colombier p->seg[ESEG] = 0; 4003e12c5d1SDavid du Colombier p->seg[SSEG] = s; 4013e12c5d1SDavid du Colombier s->base = USTKTOP-USTKSIZE; 4023e12c5d1SDavid du Colombier s->top = USTKTOP; 4033e12c5d1SDavid du Colombier relocateseg(s, TSTKTOP-USTKTOP); 4043e12c5d1SDavid du Colombier 405*219b2ee8SDavid du Colombier /* 406*219b2ee8SDavid du Colombier * '/' processes are higher priority (hack to make /ip more responsive). 407*219b2ee8SDavid du Colombier */ 408*219b2ee8SDavid du Colombier if(devchar[tc->type] == L'/') 409*219b2ee8SDavid du Colombier u->p->basepri = PriRoot; 410*219b2ee8SDavid du Colombier u->p->priority = u->p->basepri; 4113e12c5d1SDavid du Colombier close(tc); 4123e12c5d1SDavid du Colombier 4133e12c5d1SDavid du Colombier /* 4143e12c5d1SDavid du Colombier * At this point, the mmu contains info about the old address 4153e12c5d1SDavid du Colombier * space and needs to be flushed 4163e12c5d1SDavid du Colombier */ 4173e12c5d1SDavid du Colombier flushmmu(); 4183e12c5d1SDavid du Colombier qlock(&p->debug); 4193e12c5d1SDavid du Colombier u->nnote = 0; 4203e12c5d1SDavid du Colombier u->notify = 0; 4213e12c5d1SDavid du Colombier u->notified = 0; 4223e12c5d1SDavid du Colombier procsetup(p); 4233e12c5d1SDavid du Colombier qunlock(&p->debug); 4243e12c5d1SDavid du Colombier if(p->hang) 4253e12c5d1SDavid du Colombier p->procctl = Proc_stopme; 4263e12c5d1SDavid du Colombier 4273e12c5d1SDavid du Colombier return execregs(entry, ssize, nargs); 4283e12c5d1SDavid du Colombier } 4293e12c5d1SDavid du Colombier 4303e12c5d1SDavid du Colombier int 4313e12c5d1SDavid du Colombier shargs(char *s, int n, char **ap) 4323e12c5d1SDavid du Colombier { 4333e12c5d1SDavid du Colombier int i; 4343e12c5d1SDavid du Colombier 435bd389b36SDavid du Colombier s += 2; 436bd389b36SDavid du Colombier n -= 2; /* skip #! */ 4373e12c5d1SDavid du Colombier for(i=0; s[i]!='\n'; i++) 4383e12c5d1SDavid du Colombier if(i == n-1) 4393e12c5d1SDavid du Colombier return 0; 4403e12c5d1SDavid du Colombier s[i] = 0; 4413e12c5d1SDavid du Colombier *ap = 0; 4423e12c5d1SDavid du Colombier i = 0; 4433e12c5d1SDavid du Colombier for(;;){ 4443e12c5d1SDavid du Colombier while(*s==' ' || *s=='\t') 4453e12c5d1SDavid du Colombier s++; 4463e12c5d1SDavid du Colombier if(*s == 0) 4473e12c5d1SDavid du Colombier break; 4483e12c5d1SDavid du Colombier i++; 4493e12c5d1SDavid du Colombier *ap++ = s; 4503e12c5d1SDavid du Colombier *ap = 0; 4513e12c5d1SDavid du Colombier while(*s && *s!=' ' && *s!='\t') 4523e12c5d1SDavid du Colombier s++; 4533e12c5d1SDavid du Colombier if(*s == 0) 4543e12c5d1SDavid du Colombier break; 4553e12c5d1SDavid du Colombier else 4563e12c5d1SDavid du Colombier *s++ = 0; 4573e12c5d1SDavid du Colombier } 4583e12c5d1SDavid du Colombier return i; 4593e12c5d1SDavid du Colombier } 4603e12c5d1SDavid du Colombier 4613e12c5d1SDavid du Colombier int 4623e12c5d1SDavid du Colombier return0(void *a) 4633e12c5d1SDavid du Colombier { 4643e12c5d1SDavid du Colombier USED(a); 4653e12c5d1SDavid du Colombier return 0; 4663e12c5d1SDavid du Colombier } 4673e12c5d1SDavid du Colombier 4683e12c5d1SDavid du Colombier long 4693e12c5d1SDavid du Colombier syssleep(ulong *arg) 4703e12c5d1SDavid du Colombier { 471*219b2ee8SDavid du Colombier int n; 472*219b2ee8SDavid du Colombier 473*219b2ee8SDavid du Colombier n = arg[0]; 474*219b2ee8SDavid du Colombier if(n == 0){ 475*219b2ee8SDavid du Colombier sched(); /* yield */ 476*219b2ee8SDavid du Colombier return 0; 477*219b2ee8SDavid du Colombier } 478*219b2ee8SDavid du Colombier if(MS2TK(n) == 0) /* sleep for at least one tick */ 479*219b2ee8SDavid du Colombier n = TK2MS(1); 480*219b2ee8SDavid du Colombier tsleep(&u->p->sleep, return0, 0, n); 4813e12c5d1SDavid du Colombier 4823e12c5d1SDavid du Colombier return 0; 4833e12c5d1SDavid du Colombier } 4843e12c5d1SDavid du Colombier 4853e12c5d1SDavid du Colombier long 4863e12c5d1SDavid du Colombier sysalarm(ulong *arg) 4873e12c5d1SDavid du Colombier { 4883e12c5d1SDavid du Colombier return procalarm(arg[0]); 4893e12c5d1SDavid du Colombier } 4903e12c5d1SDavid du Colombier 4913e12c5d1SDavid du Colombier long 4923e12c5d1SDavid du Colombier sysexits(ulong *arg) 4933e12c5d1SDavid du Colombier { 4943e12c5d1SDavid du Colombier char *status; 4953e12c5d1SDavid du Colombier char *inval = "invalid exit string"; 496*219b2ee8SDavid du Colombier char buf[ERRLEN]; 4973e12c5d1SDavid du Colombier 4983e12c5d1SDavid du Colombier status = (char*)arg[0]; 4993e12c5d1SDavid du Colombier if(status){ 5003e12c5d1SDavid du Colombier if(waserror()) 5013e12c5d1SDavid du Colombier status = inval; 5023e12c5d1SDavid du Colombier else{ 5033e12c5d1SDavid du Colombier validaddr((ulong)status, 1, 0); 504*219b2ee8SDavid du Colombier if(vmemchr(status, 0, ERRLEN) == 0){ 505*219b2ee8SDavid du Colombier memmove(buf, status, ERRLEN); 506*219b2ee8SDavid du Colombier buf[ERRLEN-1] = 0; 507*219b2ee8SDavid du Colombier status = buf; 508*219b2ee8SDavid du Colombier } 5093e12c5d1SDavid du Colombier } 5103e12c5d1SDavid du Colombier poperror(); 5113e12c5d1SDavid du Colombier 5123e12c5d1SDavid du Colombier } 5133e12c5d1SDavid du Colombier pexit(status, 1); 5143e12c5d1SDavid du Colombier return 0; /* not reached */ 5153e12c5d1SDavid du Colombier } 5163e12c5d1SDavid du Colombier 5173e12c5d1SDavid du Colombier long 5183e12c5d1SDavid du Colombier syswait(ulong *arg) 5193e12c5d1SDavid du Colombier { 5203e12c5d1SDavid du Colombier if(arg[0]){ 5213e12c5d1SDavid du Colombier validaddr(arg[0], sizeof(Waitmsg), 1); 5223e12c5d1SDavid du Colombier evenaddr(arg[0]); 5233e12c5d1SDavid du Colombier } 5243e12c5d1SDavid du Colombier return pwait((Waitmsg*)arg[0]); 5253e12c5d1SDavid du Colombier } 5263e12c5d1SDavid du Colombier 5273e12c5d1SDavid du Colombier long 5283e12c5d1SDavid du Colombier sysdeath(ulong *arg) 5293e12c5d1SDavid du Colombier { 5303e12c5d1SDavid du Colombier USED(arg); 5313e12c5d1SDavid du Colombier pprint("deprecated system call\n"); 5323e12c5d1SDavid du Colombier pexit("Suicide", 0); 5333e12c5d1SDavid du Colombier return 0; /* not reached */ 5343e12c5d1SDavid du Colombier } 5353e12c5d1SDavid du Colombier 5363e12c5d1SDavid du Colombier long 5373e12c5d1SDavid du Colombier syserrstr(ulong *arg) 5383e12c5d1SDavid du Colombier { 539*219b2ee8SDavid du Colombier char tmp[ERRLEN]; 540*219b2ee8SDavid du Colombier 5413e12c5d1SDavid du Colombier validaddr(arg[0], ERRLEN, 1); 542*219b2ee8SDavid du Colombier memmove(tmp, (char*)arg[0], ERRLEN); 5433e12c5d1SDavid du Colombier memmove((char*)arg[0], u->error, ERRLEN); 544*219b2ee8SDavid du Colombier memmove(u->error, tmp, ERRLEN); 5453e12c5d1SDavid du Colombier return 0; 5463e12c5d1SDavid du Colombier } 5473e12c5d1SDavid du Colombier 5483e12c5d1SDavid du Colombier long 5493e12c5d1SDavid du Colombier sysnotify(ulong *arg) 5503e12c5d1SDavid du Colombier { 5513e12c5d1SDavid du Colombier USED(arg); 5523e12c5d1SDavid du Colombier if(arg[0] != 0) 5533e12c5d1SDavid du Colombier validaddr(arg[0], sizeof(ulong), 0); 5543e12c5d1SDavid du Colombier u->notify = (int(*)(void*, char*))(arg[0]); 5553e12c5d1SDavid du Colombier return 0; 5563e12c5d1SDavid du Colombier } 5573e12c5d1SDavid du Colombier 5583e12c5d1SDavid du Colombier long 5593e12c5d1SDavid du Colombier sysnoted(ulong *arg) 5603e12c5d1SDavid du Colombier { 561*219b2ee8SDavid du Colombier if(arg[0]!=NRSTR && !u->notified) 5623e12c5d1SDavid du Colombier error(Egreg); 5633e12c5d1SDavid du Colombier return 0; 5643e12c5d1SDavid du Colombier } 5653e12c5d1SDavid du Colombier 5663e12c5d1SDavid du Colombier long 5673e12c5d1SDavid du Colombier syssegbrk(ulong *arg) 5683e12c5d1SDavid du Colombier { 5693e12c5d1SDavid du Colombier Segment *s; 5703e12c5d1SDavid du Colombier int i; 5713e12c5d1SDavid du Colombier 572*219b2ee8SDavid du Colombier for(i = 0; i < NSEG; i++) { 5733e12c5d1SDavid du Colombier if(s = u->p->seg[i]) { 5743e12c5d1SDavid du Colombier if(arg[0] >= s->base && arg[0] < s->top) { 5753e12c5d1SDavid du Colombier switch(s->type&SG_TYPE) { 5763e12c5d1SDavid du Colombier case SG_TEXT: 5773e12c5d1SDavid du Colombier case SG_DATA: 578*219b2ee8SDavid du Colombier case SG_STACK: 5793e12c5d1SDavid du Colombier error(Ebadarg); 5803e12c5d1SDavid du Colombier default: 5813e12c5d1SDavid du Colombier return ibrk(arg[1], i); 5823e12c5d1SDavid du Colombier } 5833e12c5d1SDavid du Colombier } 5843e12c5d1SDavid du Colombier } 585*219b2ee8SDavid du Colombier } 5863e12c5d1SDavid du Colombier 5873e12c5d1SDavid du Colombier error(Ebadarg); 5883e12c5d1SDavid du Colombier return 0; /* not reached */ 5893e12c5d1SDavid du Colombier } 5903e12c5d1SDavid du Colombier 5913e12c5d1SDavid du Colombier long 5923e12c5d1SDavid du Colombier syssegattach(ulong *arg) 5933e12c5d1SDavid du Colombier { 5943e12c5d1SDavid du Colombier return segattach(u->p, arg[0], (char*)arg[1], arg[2], arg[3]); 5953e12c5d1SDavid du Colombier } 5963e12c5d1SDavid du Colombier 5973e12c5d1SDavid du Colombier long 5983e12c5d1SDavid du Colombier syssegdetach(ulong *arg) 5993e12c5d1SDavid du Colombier { 6003e12c5d1SDavid du Colombier int i; 6013e12c5d1SDavid du Colombier Segment *s; 6023e12c5d1SDavid du Colombier 6033e12c5d1SDavid du Colombier s = 0; 6043e12c5d1SDavid du Colombier for(i = 0; i < NSEG; i++) 6053e12c5d1SDavid du Colombier if(s = u->p->seg[i]) { 6063e12c5d1SDavid du Colombier qlock(&s->lk); 6073e12c5d1SDavid du Colombier if((arg[0] >= s->base && arg[0] < s->top) || 6083e12c5d1SDavid du Colombier (s->top == s->base && arg[0] == s->base)) 6093e12c5d1SDavid du Colombier goto found; 6103e12c5d1SDavid du Colombier qunlock(&s->lk); 6113e12c5d1SDavid du Colombier } 6123e12c5d1SDavid du Colombier 6133e12c5d1SDavid du Colombier error(Ebadarg); 6143e12c5d1SDavid du Colombier 6153e12c5d1SDavid du Colombier found: 6163e12c5d1SDavid du Colombier if((ulong)arg >= s->base && (ulong)arg < s->top) { 6173e12c5d1SDavid du Colombier qunlock(&s->lk); 6183e12c5d1SDavid du Colombier error(Ebadarg); 6193e12c5d1SDavid du Colombier } 6203e12c5d1SDavid du Colombier u->p->seg[i] = 0; 6213e12c5d1SDavid du Colombier qunlock(&s->lk); 6223e12c5d1SDavid du Colombier putseg(s); 6233e12c5d1SDavid du Colombier 6243e12c5d1SDavid du Colombier /* Ensure we flush any entries from the lost segment */ 6253e12c5d1SDavid du Colombier flushmmu(); 6263e12c5d1SDavid du Colombier return 0; 6273e12c5d1SDavid du Colombier } 6283e12c5d1SDavid du Colombier 6293e12c5d1SDavid du Colombier long 6303e12c5d1SDavid du Colombier syssegfree(ulong *arg) 6313e12c5d1SDavid du Colombier { 6323e12c5d1SDavid du Colombier Segment *s; 6333e12c5d1SDavid du Colombier ulong from, pages; 6343e12c5d1SDavid du Colombier 6353e12c5d1SDavid du Colombier from = PGROUND(arg[0]); 6363e12c5d1SDavid du Colombier s = seg(u->p, from, 1); 6373e12c5d1SDavid du Colombier if(s == 0) 6383e12c5d1SDavid du Colombier error(Ebadarg); 6393e12c5d1SDavid du Colombier 6403e12c5d1SDavid du Colombier pages = (arg[1]+BY2PG-1)/BY2PG; 6413e12c5d1SDavid du Colombier 6423e12c5d1SDavid du Colombier if(from+pages*BY2PG > s->top) { 6433e12c5d1SDavid du Colombier qunlock(&s->lk); 6443e12c5d1SDavid du Colombier error(Ebadarg); 6453e12c5d1SDavid du Colombier } 6463e12c5d1SDavid du Colombier 6473e12c5d1SDavid du Colombier mfreeseg(s, from, pages); 6483e12c5d1SDavid du Colombier qunlock(&s->lk); 649bd389b36SDavid du Colombier flushmmu(); 6503e12c5d1SDavid du Colombier 6513e12c5d1SDavid du Colombier return 0; 6523e12c5d1SDavid du Colombier } 6533e12c5d1SDavid du Colombier 6543e12c5d1SDavid du Colombier /* For binary compatability */ 6553e12c5d1SDavid du Colombier long 6563e12c5d1SDavid du Colombier sysbrk_(ulong *arg) 6573e12c5d1SDavid du Colombier { 6583e12c5d1SDavid du Colombier return ibrk(arg[0], BSEG); 6593e12c5d1SDavid du Colombier } 6603e12c5d1SDavid du Colombier 6613e12c5d1SDavid du Colombier long 6623e12c5d1SDavid du Colombier sysrendezvous(ulong *arg) 6633e12c5d1SDavid du Colombier { 6643e12c5d1SDavid du Colombier Proc *p, **l; 665*219b2ee8SDavid du Colombier int tag; 6663e12c5d1SDavid du Colombier ulong val; 6673e12c5d1SDavid du Colombier 6683e12c5d1SDavid du Colombier tag = arg[0]; 6693e12c5d1SDavid du Colombier l = &REND(u->p->pgrp, tag); 6703e12c5d1SDavid du Colombier 6713e12c5d1SDavid du Colombier lock(u->p->pgrp); 6723e12c5d1SDavid du Colombier for(p = *l; p; p = p->rendhash) { 6733e12c5d1SDavid du Colombier if(p->rendtag == tag) { 6743e12c5d1SDavid du Colombier *l = p->rendhash; 6753e12c5d1SDavid du Colombier val = p->rendval; 6763e12c5d1SDavid du Colombier p->rendval = arg[1]; 677*219b2ee8SDavid du Colombier /* Hard race avoidance */ 678*219b2ee8SDavid du Colombier while(p->mach != 0) 6793e12c5d1SDavid du Colombier ; 6803e12c5d1SDavid du Colombier ready(p); 6813e12c5d1SDavid du Colombier unlock(u->p->pgrp); 6823e12c5d1SDavid du Colombier return val; 6833e12c5d1SDavid du Colombier } 6843e12c5d1SDavid du Colombier l = &p->rendhash; 6853e12c5d1SDavid du Colombier } 6863e12c5d1SDavid du Colombier 6873e12c5d1SDavid du Colombier /* Going to sleep here */ 6883e12c5d1SDavid du Colombier p = u->p; 6893e12c5d1SDavid du Colombier p->rendtag = tag; 6903e12c5d1SDavid du Colombier p->rendval = arg[1]; 6913e12c5d1SDavid du Colombier p->rendhash = *l; 6923e12c5d1SDavid du Colombier *l = p; 6933e12c5d1SDavid du Colombier u->p->state = Rendezvous; 694*219b2ee8SDavid du Colombier unlock(p->pgrp); 695*219b2ee8SDavid du Colombier 6963e12c5d1SDavid du Colombier sched(); 6973e12c5d1SDavid du Colombier 6983e12c5d1SDavid du Colombier return u->p->rendval; 6993e12c5d1SDavid du Colombier } 700