void kproc(char *name, void (*func)(void *), void *arg) { Mach *m = machp(); Proc *p; static Pgrp *kpgrp; p = newproc(); p->psstate = 0; p->procmode = 0640; p->kp = 1; p->noswap = 1; p->scallnr = m->externup->scallnr; memmove(p->arg, m->externup->arg, sizeof(m->externup->arg)); p->nerrlab = 0; p->slash = m->externup->slash; p->dot = m->externup->dot; if(p->dot) incref(p->dot); memmove(p->note, m->externup->note, sizeof(p->note)); p->nnote = m->externup->nnote; p->notified = 0; p->lastnote = m->externup->lastnote; p->notify = m->externup->notify; p->ureg = 0; p->dbgreg = 0; procpriority(p, PriKproc, 0); kprocchild(p, func, arg); kstrdup(&p->user, eve); kstrdup(&p->text, name); if(kpgrp == 0) kpgrp = newpgrp(); p->pgrp = kpgrp; incref(kpgrp); memset(p->time, 0, sizeof(p->time)); p->time[TReal] = sys->ticks; ready(p); /* * since the bss/data segments are now shareable, * any mmu info about this process is now stale * and has to be discarded. */ p->newtlb = 1; mmuflush(); }
void kproc(char *name, void (*func)(void *), void *arg) { Proc *p; static Pgrp *kpgrp; p = newproc(); p->psstate = 0; p->procmode = 0640; p->kp = 1; p->noswap = 1; p->fpsave = up->fpsave; p->scallnr = up->scallnr; p->s = up->s; p->nerrlab = 0; p->slash = up->slash; p->dot = up->dot; if(p->dot) incref(p->dot); memmove(p->note, up->note, sizeof(p->note)); p->nnote = up->nnote; p->notified = 0; p->lastnote = up->lastnote; p->notify = up->notify; p->ureg = 0; p->dbgreg = 0; procpriority(p, PriKproc, 0); kprocchild(p, func, arg); kstrdup(&p->user, eve); kstrdup(&p->text, name); if(kpgrp == 0) kpgrp = newpgrp(); p->pgrp = kpgrp; incref(kpgrp); memset(p->time, 0, sizeof(p->time)); p->time[TReal] = MACHP(0)->ticks; ready(p); }
Proc* newproc(void) { char msg[64]; Proc *p; lock(&procalloc); for(;;) { if((p = procalloc.free) != nil) break; snprint(msg, sizeof msg, "no procs; %s forking", up != nil ? up->text: "kernel"); unlock(&procalloc); resrcwait(msg); lock(&procalloc); } procalloc.free = p->qnext; unlock(&procalloc); p->state = Scheding; p->psstate = "New"; p->mach = nil; p->eql = nil; p->qnext = nil; p->nchild = 0; p->nwait = 0; p->waitq = nil; p->parent = nil; p->pgrp = nil; p->egrp = nil; p->fgrp = nil; p->rgrp = nil; p->pdbg = nil; p->fpstate = FPinit; p->kp = 0; p->procctl = 0; p->syscalltrace = nil; p->notepending = 0; p->ureg = nil; p->privatemem = 0; p->noswap = 0; p->errstr = p->errbuf0; p->syserrstr = p->errbuf1; p->errbuf0[0] = '\0'; p->errbuf1[0] = '\0'; p->nlocks = 0; p->delaysched = 0; p->trace = 0; kstrdup(&p->user, "*nouser"); kstrdup(&p->text, "*notext"); kstrdup(&p->args, ""); p->nargs = 0; p->setargs = 0; memset(p->seg, 0, sizeof p->seg); p->parentpid = 0; p->noteid = pidalloc(p); if(p->kstack == nil) p->kstack = smalloc(KSTACK); /* sched params */ p->mp = nil; p->wired = nil; procpriority(p, PriNormal, 0); p->cpu = 0; p->lastupdate = MACHP(0)->ticks*Scaling; p->edf = nil; return p; }
/* * Move the current process to an application core. * This is performed at the end of execac(), and * we pretend to be returning to user-space, but instead we * dispatch the process to another core. * 1. We do the final bookkeeping that syscall() would do after * a return from sysexec(), because we are not returning. * 2. We dispatch the process to an AC using an ICC. * * This function won't return unless the process is reclaimed back * to the time-sharing core, and is the handler for the process * to deal with traps and system calls until the process dies. * * Remember that this function is the "line" between user and kernel * space, it's not expected to raise|handle any error. * * We install a safety error label, just in case we raise errors, * which we shouldn't. (noerrorsleft knows that for exotic processes * there is an error label pushed by us). */ void runacore(void) { Proc *up = externup(); Ureg *ureg; void (*fn)(void); int rc, flush, s; char *n; uint64_t t1; if(waserror()) panic("runacore: error: %s\n", up->errstr); ureg = up->dbgreg; fakeretfromsyscall(ureg); fpusysrfork(ureg); procpriority(up, PriKproc, 1); rc = runac(up->ac, actouser, 1, nil, 0); procpriority(up, PriNormal, 0); for(;;){ t1 = fastticks(nil); flush = 0; fn = nil; switch(rc){ case ICCTRAP: s = splhi(); machp()->MMU.cr2 = up->ac->MMU.cr2; DBG("runacore: trap %llu cr2 %#llx ureg %#p\n", ureg->type, machp()->MMU.cr2, ureg); switch(ureg->type){ case IdtIPI: if(up->procctl || up->nnote) notify(up->dbgreg); if(up->ac == nil) goto ToTC; kexit(up->dbgreg); break; case IdtNM: case IdtMF: case IdtXF: /* these are handled in the AC; * If we get here, they left in m->NIX.icc->data * a note to be posted to the process. * Post it, and make the vector a NOP. */ n = up->ac->NIX.icc->note; if(n != nil) postnote(up, 1, n, NDebug); ureg->type = IdtIPI; /* NOP */ break; default: cr3put(machp()->MMU.pml4->pa); if(0 && ureg->type == IdtPF){ print("before PF:\n"); print("AC:\n"); dumpptepg(4, up->ac->MMU.pml4->pa); print("\n%s:\n", rolename[NIXTC]); dumpptepg(4, machp()->MMU.pml4->pa); } trap(ureg); } splx(s); flush = 1; fn = actrapret; break; case ICCSYSCALL: DBG("runacore: syscall ax %#llx ureg %#p\n", ureg->ax, ureg); cr3put(machp()->MMU.pml4->pa); //syscall(ureg->ax, ureg); flush = 1; fn = acsysret; if(0) if(up->nqtrap > 2 || up->nsyscall > 1) goto ToTC; if(up->ac == nil) goto ToTC; break; default: panic("runacore: unexpected rc = %d", rc); } up->tctime += fastticks2us(fastticks(nil) - t1); procpriority(up, PriExtra, 1); rc = runac(up->ac, fn, flush, nil, 0); procpriority(up, PriNormal, 0); } ToTC: /* * to procctl, then syscall, to * be back in the TC */ DBG("runacore: up %#p: return\n", up); }
Proc* newproc(void) { Mach *m = machp(); Proc *p; p = psalloc(); p->state = Scheding; p->psstate = "New"; p->mach = 0; p->qnext = 0; p->nchild = 0; p->nwait = 0; p->waitq = 0; p->parent = 0; p->pgrp = 0; p->egrp = 0; p->fgrp = 0; p->rgrp = 0; p->pdbg = 0; p->kp = 0; if(m->externup != nil && m->externup->procctl == Proc_tracesyscall) p->procctl = Proc_tracesyscall; else p->procctl = 0; p->syscalltrace = nil; p->notepending = 0; p->ureg = 0; p->privatemem = 0; p->noswap = 0; p->errstr = p->errbuf0; p->syserrstr = p->errbuf1; p->errbuf0[0] = '\0'; p->errbuf1[0] = '\0'; p->nlocks = 0; p->delaysched = 0; p->trace = 0; kstrdup(&p->user, "*nouser"); kstrdup(&p->text, "*notext"); kstrdup(&p->args, ""); p->nargs = 0; p->setargs = 0; memset(p->seg, 0, sizeof p->seg); p->pid = incref(&pidalloc); pshash(p); p->noteid = incref(¬eidalloc); if(p->pid <= 0 || p->noteid <= 0) panic("pidalloc"); if(p->kstack == 0){ p->kstack = smalloc(KSTACK); *(uintptr_t*)p->kstack = STACKGUARD; } /* sched params */ p->mp = 0; p->wired = 0; procpriority(p, PriNormal, 0); p->cpu = 0; p->lastupdate = sys->ticks*Scaling; p->edf = nil; p->ntrap = 0; p->nintr = 0; p->nsyscall = 0; p->nactrap = 0; p->nacsyscall = 0; p->nicc = 0; p->actime = 0ULL; p->tctime = 0ULL; p->ac = nil; p->nfullq = 0; p->req = nil; p->resp = nil; memset(&p->PMMU, 0, sizeof p->PMMU); return p; }
Proc* setupseg(int core) { Mach *m = machp(); Segment *s; uintptr_t ka; Proc *p; static Pgrp *kpgrp; Segment *tseg; int sno; // XXX: we're going to need this for locality domains. USED(core); p = newproc(); p->psstate = 0; p->procmode = 0640; p->kp = 1; p->noswap = 1; p->scallnr = m->externup->scallnr; memmove(p->arg, m->externup->arg, sizeof(m->externup->arg)); p->nerrlab = 0; p->slash = m->externup->slash; p->dot = m->externup->dot; if(p->dot) incref(p->dot); memmove(p->note, m->externup->note, sizeof(p->note)); p->nnote = m->externup->nnote; p->notified = 0; p->lastnote = m->externup->lastnote; p->notify = m->externup->notify; p->ureg = 0; p->dbgreg = 0; kstrdup(&p->user, eve); if(kpgrp == 0) kpgrp = newpgrp(); p->pgrp = kpgrp; incref(kpgrp); memset(p->time, 0, sizeof(p->time)); p->time[TReal] = sys->ticks; procpriority(p, PriKproc, 0); // XXX: kluge 4 pages of address space for this. // how will it expand up? gives us <50 kprocs as is. /* * we create the color and core at allocation time, not execution. This * is probably not the best idea but it's a start. */ sno = 0; // XXX: now that we are asmalloc we are no long proc. /* Stack */ ka = (uintptr_t)KADDR(asmalloc(0, BIGPGSZ, AsmMEMORY, 1)); tseg = newseg(SG_STACK|SG_READ|SG_WRITE, ka, 1); tseg = p->seg[sno++]; ka = (uintptr_t)KADDR(asmalloc(0, BIGPGSZ, AsmMEMORY, 1)); s = newseg(SG_TEXT|SG_READ|SG_EXEC, ka, 1); p->seg[sno++] = s; // s->color = acpicorecolor(core); /* Data. Shared. */ // XXX; Now that the address space is all funky how are we going to handle shared data segments? ka = (uintptr_t)KADDR(asmalloc(0, BIGPGSZ, AsmMEMORY, 2)); s = newseg(SG_DATA|SG_READ|SG_WRITE, ka, 1); p->seg[sno++] = s; s->color = tseg->color; /* BSS. Uses asm from data map. */ p->seg[sno++] = newseg(SG_BSS|SG_READ|SG_WRITE, ka+BIGPGSZ, 1); p->seg[sno++]->color= tseg->color; nixprepage(-1); return p; }
Proc* newproc(void) { char msg[64]; Proc *p; lock(&procalloc); while((p = procalloc.free) == nil) { unlock(&procalloc); snprint(msg, sizeof msg, "no procs; %s forking", up? up->text: "kernel"); /* * the situation is unlikely to heal itself. * dump the proc table and restart by default. * *noprocspersist in plan9.ini will yield the old * behaviour of trying forever. */ if(getconf("*noprocspersist") == nil) noprocpanic(msg); resrcwait(msg); lock(&procalloc); } procalloc.free = p->qnext; unlock(&procalloc); p->state = Scheding; p->psstate = "New"; p->mach = 0; p->qnext = 0; p->nchild = 0; p->nwait = 0; p->waitq = 0; p->parent = 0; p->pgrp = 0; p->egrp = 0; p->fgrp = 0; p->rgrp = 0; p->pdbg = 0; p->fpstate = FPinit; p->kp = 0; if(up && up->procctl == Proc_tracesyscall) p->procctl = Proc_tracesyscall; else p->procctl = 0; p->syscalltrace = 0; p->notepending = 0; p->ureg = 0; p->privatemem = 0; p->noswap = 0; p->errstr = p->errbuf0; p->syserrstr = p->errbuf1; p->errbuf0[0] = '\0'; p->errbuf1[0] = '\0'; p->nlocks.ref = 0; p->delaysched = 0; p->trace = 0; kstrdup(&p->user, "*nouser"); kstrdup(&p->text, "*notext"); kstrdup(&p->args, ""); p->nargs = 0; p->setargs = 0; memset(p->seg, 0, sizeof p->seg); p->pid = incref(&pidalloc); pidhash(p); p->noteid = incref(¬eidalloc); if(p->pid==0 || p->noteid==0) panic("pidalloc"); if(p->kstack == 0) p->kstack = smalloc(KSTACK); /* sched params */ p->mp = 0; p->wired = 0; procpriority(p, PriNormal, 0); p->cpu = 0; p->lastupdate = MACHP(0)->ticks*Scaling; p->edf = nil; return p; }