void tsleep(Rendez *r, int (*fn)(void*), void *arg, ulong ms) { if(up->tt != nil){ print("tsleep: timer active: mode %d, tf %#p\n", up->tmode, up->tf); timerdel(up); } up->tns = MS2NS(ms); up->tf = twakeup; up->tmode = Trelative; up->ta = up; up->trend = r; up->tfn = fn; timeradd(up); if(waserror()){ timerdel(up); nexterror(); } sleep(r, tfn, arg); if(up->tt != nil) timerdel(up); up->twhen = 0; poperror(); }
void tsleep(Rendez *r, int (*fn)(void*), void *arg, int32_t ms) { Mach *m = machp(); if (m->externup->tt){ print("tsleep: timer active: mode %d, tf %#p\n", m->externup->tmode, m->externup->tf); timerdel(m->externup); } m->externup->tns = MS2NS(ms); m->externup->tf = twakeup; m->externup->tmode = Trelative; m->externup->ta = m->externup; m->externup->trend = r; m->externup->tfn = fn; timeradd(m->externup); if(waserror()){ timerdel(m->externup); nexterror(); } sleep(r, tfn, arg); if (m->externup->tt) timerdel(m->externup); m->externup->twhen = 0; poperror(); }
void tsleep(Rendez *r, int (*fn)(void*), void *arg, int64_t ms) { Proc *up = externup(); if (up->Timer.tt){ print("tsleep: timer active: mode %d, tf %#p\n", up->Timer.tmode, up->Timer.tf); timerdel(&up->Timer); } up->Timer.tns = MS2NS(ms); up->Timer.tf = twakeup; up->Timer.tmode = Trelative; up->Timer.ta = up; up->trend = r; up->tfn = fn; timeradd(&up->Timer); if(waserror()){ timerdel(&up->Timer); nexterror(); } sleep(r, tfn, arg); if (up->Timer.tt) timerdel(&up->Timer); up->Timer.twhen = 0; poperror(); }
void edfstop(Proc *p) { Edf *e; if(e = edflock(p)){ DPRINT("%lu edfstop %d[%s]\n", now, p->pid, statename[p->state]); if(p->trace) proctrace(p, SExpel, 0); e->flags &= ~Admitted; if(e->Timer.tt) timerdel(&e->Timer); edfunlock(); } }
void edfstop(Proc *p) { Edf *e; void (*pt)(Proc*, int, vlong); if (e = edflock(p)){ DPRINT("%t edfstop %lud[%s]\n", now, p->pid, statename[p->state]); if(pt = proctrace) pt(p, SExpel, now); e->flags &= ~Admitted; if (e->tt) timerdel(e); edfunlock(); } }
static void setalarm(void) { Proc *p; ulong now; now = msec(); if(alarmtimer.tt) timerdel(&alarmtimer); while((p = alarms.head) && p->alarm == 0) alarms.head = p->palarm; if(p == nil) return; alarmtimer.tf = soundalarms; alarmtimer.tmode = Trelative; alarmtimer.tns = (p->alarm - now)*1000000LL; timeradd(&alarmtimer); }
/* * called with the Loop qlocked, * so only pushlink can mess with the queues */ static void closelink(Link *link, int dofree) { Queue *iq, *oq; Block *bp; ilock(link); iq = link->iq; oq = link->oq; bp = link->tq; link->tq = nil; link->tqtail = nil; link->tout = 0; link->tin = 0; timerdel(&link->ci); iunlock(link); if(iq != nil){ qclose(iq); if(dofree){ ilock(link); free(iq); link->iq = nil; iunlock(link); } } if(oq != nil){ qclose(oq); if(dofree){ ilock(link); free(oq); link->oq = nil; iunlock(link); } } freeblist(bp); }
/* * move blocks between queues if they are ready. * schedule an interrupt for the next interesting time. * * must be called with the link ilocked. */ static void pushlink(Link *link, vlong now) { Block *bp; vlong tout, tin; /* * put another block in the link queue */ ilock(link); if(link->iq == nil || link->oq == nil){ iunlock(link); return; } timerdel(&link->ci); /* * put more blocks into the xmit queue * use the time the last packet was supposed to go out * as the start time for the next packet, rather than * the current time. this more closely models a network * device which can queue multiple output packets. */ tout = link->tout; if(!tout) tout = now; while(tout <= now){ bp = qget(link->oq); if(bp == nil){ tout = 0; break; } /* * can't send the packet before it gets queued */ tin = gtime(bp->rp); if(tin > tout) tout = tin; tout = tout + (BLEN(bp) - Tmsize) * link->delayn; /* * drop packets */ if(link->droprate && nrand(link->droprate) == 0) link->drops++; else{ ptime(bp->rp, tout + link->delay0ns); if(link->tq == nil) link->tq = bp; else link->tqtail->next = bp; link->tqtail = bp; } } /* * record the next time a packet can be sent, * but don't schedule an interrupt if none is waiting */ link->tout = tout; if(!qcanread(link->oq)) tout = 0; /* * put more blocks into the receive queue */ tin = 0; while(bp = link->tq){ tin = gtime(bp->rp); if(tin > now) break; bp->rp += Tmsize; link->tq = bp->next; bp->next = nil; if(!link->indrop) qpassnolim(link->iq, bp); else if(qpass(link->iq, bp) < 0) link->soverflows++; tin = 0; } if(bp == nil && qisclosed(link->oq) && !qcanread(link->oq) && !qisclosed(link->iq)) qhangup(link->iq, nil); link->tin = tin; if(!tin || tin > tout && tout) tin = tout; link->ci.ns = tin - now; if(tin){ if(tin < now) panic("loopback unfinished business"); timeradd(&link->ci); } iunlock(link); }
void pexit(char *exitstr, int freemem) { Proc *p; Segment **s, **es; long utime, stime; Waitq *wq; Fgrp *fgrp; Egrp *egrp; Rgrp *rgrp; Pgrp *pgrp; Chan *dot; void (*pt)(Proc*, int, vlong); up->alarm = 0; if(up->tt != nil) timerdel(up); pt = proctrace; if(pt != nil) pt(up, SDead, 0); /* nil out all the resources under lock (free later) */ qlock(&up->debug); fgrp = up->fgrp; up->fgrp = nil; egrp = up->egrp; up->egrp = nil; rgrp = up->rgrp; up->rgrp = nil; pgrp = up->pgrp; up->pgrp = nil; dot = up->dot; up->dot = nil; qunlock(&up->debug); if(fgrp != nil) closefgrp(fgrp); if(egrp != nil) closeegrp(egrp); if(rgrp != nil) closergrp(rgrp); if(dot != nil) cclose(dot); if(pgrp != nil) closepgrp(pgrp); /* * if not a kernel process and have a parent, * do some housekeeping. */ if(up->kp == 0 && up->parentpid != 0) { wq = smalloc(sizeof(Waitq)); wq->w.pid = up->pid; utime = up->time[TUser] + up->time[TCUser]; stime = up->time[TSys] + up->time[TCSys]; wq->w.time[TUser] = tk2ms(utime); wq->w.time[TSys] = tk2ms(stime); wq->w.time[TReal] = tk2ms(MACHP(0)->ticks - up->time[TReal]); if(exitstr != nil && exitstr[0]) snprint(wq->w.msg, sizeof(wq->w.msg), "%s %lud: %s", up->text, up->pid, exitstr); else wq->w.msg[0] = '\0'; p = up->parent; lock(&p->exl); /* * Check that parent is still alive. */ if(p->pid == up->parentpid && p->state != Broken) { p->nchild--; p->time[TCUser] += utime; p->time[TCSys] += stime; /* * If there would be more than 128 wait records * processes for my parent, then don't leave a wait * record behind. This helps prevent badly written * daemon processes from accumulating lots of wait * records. */ if(p->nwait < 128) { wq->next = p->waitq; p->waitq = wq; p->nwait++; wq = nil; wakeup(&p->waitr); } } unlock(&p->exl); if(wq != nil) free(wq); } else if(up->kp == 0 && up->parent == nil){ if(exitstr == nil) exitstr = "unknown"; panic("boot process died: %s", exitstr); } if(!freemem) addbroken(up); qlock(&up->seglock); es = &up->seg[NSEG]; for(s = up->seg; s < es; s++) { if(*s != nil) { putseg(*s); *s = nil; } } qunlock(&up->seglock); lock(&up->exl); /* Prevent my children from leaving waits */ pidfree(up); up->pid = 0; wakeup(&up->waitr); unlock(&up->exl); while((wq = up->waitq) != nil){ up->waitq = wq->next; free(wq); } /* release debuggers */ qlock(&up->debug); if(up->pdbg != nil) { wakeup(&up->pdbg->sleep); up->pdbg = nil; } if(up->syscalltrace != nil) { free(up->syscalltrace); up->syscalltrace = nil; } qunlock(&up->debug); /* Sched must not loop for these locks */ lock(&procalloc); lock(&palloc); edfstop(up); up->state = Moribund; sched(); panic("pexit"); }
void pexit(char *exitstr, int freemem) { Mach *m = machp(); Proc *p; Segment **s, **es; int32_t utime, stime; Waitq *wq, *f, *next; Fgrp *fgrp; Egrp *egrp; Rgrp *rgrp; Pgrp *pgrp; Chan *dot; if(0 && m->externup->nfullq > 0) iprint(" %s=%d", m->externup->text, m->externup->nfullq); if(0 && m->externup->nicc > 0) iprint(" [%s nicc %ud tctime %ulld actime %ulld]\n", m->externup->text, m->externup->nicc, m->externup->tctime, m->externup->actime); if(m->externup->syscalltrace != nil) free(m->externup->syscalltrace); m->externup->syscalltrace = nil; m->externup->alarm = 0; if (m->externup->tt) timerdel(m->externup); if(m->externup->trace) proctrace(m->externup, SDead, 0); /* nil out all the resources under lock (free later) */ qlock(&m->externup->debug); fgrp = m->externup->fgrp; m->externup->fgrp = nil; egrp = m->externup->egrp; m->externup->egrp = nil; rgrp = m->externup->rgrp; m->externup->rgrp = nil; pgrp = m->externup->pgrp; m->externup->pgrp = nil; dot = m->externup->dot; m->externup->dot = nil; qunlock(&m->externup->debug); if(fgrp) closefgrp(fgrp); if(egrp) closeegrp(egrp); if(rgrp) closergrp(rgrp); if(dot) cclose(dot); if(pgrp) closepgrp(pgrp); /* * if not a kernel process and have a parent, * do some housekeeping. */ if(m->externup->kp == 0) { p = m->externup->parent; if(p == 0) { if(exitstr == 0) exitstr = "unknown"; //die("bootprocessdeath"); panic("boot process died: %s", exitstr); } while(waserror()) ; wq = smalloc(sizeof(Waitq)); poperror(); wq->w.pid = m->externup->pid; utime = m->externup->time[TUser] + m->externup->time[TCUser]; stime = m->externup->time[TSys] + m->externup->time[TCSys]; wq->w.time[TUser] = tk2ms(utime); wq->w.time[TSys] = tk2ms(stime); wq->w.time[TReal] = tk2ms(sys->machptr[0]->ticks - m->externup->time[TReal]); if(exitstr && exitstr[0]) snprint(wq->w.msg, sizeof(wq->w.msg), "%s %d: %s", m->externup->text, m->externup->pid, exitstr); else wq->w.msg[0] = '\0'; lock(&p->exl); /* * Check that parent is still alive. */ if(p->pid == m->externup->parentpid && p->state != Broken) { p->nchild--; p->time[TCUser] += utime; p->time[TCSys] += stime; /* * If there would be more than 128 wait records * processes for my parent, then don't leave a wait * record behind. This helps prevent badly written * daemon processes from accumulating lots of wait * records. */ if(p->nwait < 128) { wq->next = p->waitq; p->waitq = wq; p->nwait++; wq = nil; wakeup(&p->waitr); } } unlock(&p->exl); if(wq) free(wq); } if(!freemem) addbroken(m->externup); qlock(&m->externup->seglock); es = &m->externup->seg[NSEG]; for(s = m->externup->seg; s < es; s++) { if(*s) { putseg(*s); *s = 0; } } qunlock(&m->externup->seglock); lock(&m->externup->exl); /* Prevent my children from leaving waits */ psunhash(m->externup); m->externup->pid = 0; wakeup(&m->externup->waitr); unlock(&m->externup->exl); for(f = m->externup->waitq; f; f = next) { next = f->next; free(f); } /* release debuggers */ qlock(&m->externup->debug); if(m->externup->pdbg) { wakeup(&m->externup->pdbg->sleep); m->externup->pdbg = 0; } qunlock(&m->externup->debug); /* Sched must not loop for these locks */ lock(&procalloc); lock(&pga); stopac(); edfstop(m->externup); m->externup->state = Moribund; sched(); panic("pexit"); }