diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-09-03 17:30:04 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-09-03 17:30:04 +0000 |
commit | 3e115487969570445a58a5a351a7bf0e0ab5fc21 (patch) | |
tree | 98d03736051c50aee5b5b59250f35000532a8fd8 /sys/src/9/port | |
parent | 99529b80a3bbe35c5cd5dadf5f106632a2449e84 (diff) |
kernel: half NERR, refcount Note's to avoid excessive allocations for postnotepg()
Half NERR stack to 32.
When posing a note to a large group, avoid allocating Notes
for each individual process, but post the reference instread.
factor out process interruption into procinterrupt().
Avoid allocation of notes in alarmkproc, just posting the
same note to everyone.
Diffstat (limited to 'sys/src/9/port')
-rw-r--r-- | sys/src/9/port/alarm.c | 8 | ||||
-rw-r--r-- | sys/src/9/port/devproc.c | 32 | ||||
-rw-r--r-- | sys/src/9/port/portdat.h | 5 | ||||
-rw-r--r-- | sys/src/9/port/portfns.h | 4 | ||||
-rw-r--r-- | sys/src/9/port/proc.c | 213 | ||||
-rw-r--r-- | sys/src/9/port/sysproc.c | 2 |
6 files changed, 156 insertions, 108 deletions
diff --git a/sys/src/9/port/alarm.c b/sys/src/9/port/alarm.c index 233e88768..49dec2ccb 100644 --- a/sys/src/9/port/alarm.c +++ b/sys/src/9/port/alarm.c @@ -27,7 +27,13 @@ alarmkproc(void*) if(!canqlock(&rp->debug)) break; if(rp->alarm != 0){ - postnote(rp, 0, "alarm", NUser); + static Note alarm = { + "alarm", + NUser, + 1, + }; + incref(&alarm); + pushnote(rp, &alarm); rp->alarm = 0; } qunlock(&rp->debug); diff --git a/sys/src/9/port/devproc.c b/sys/src/9/port/devproc.c index 0d4ae5193..8c0f93454 100644 --- a/sys/src/9/port/devproc.c +++ b/sys/src/9/port/devproc.c @@ -351,24 +351,6 @@ changenoteid(Proc *p, ulong noteid) error(Eperm); } -static void -postnotepg(ulong noteid, char *n, int flag) -{ - Proc *p; - int i; - - for(i = 0; (p = proctab(i)) != nil; i++){ - if(p == up) - continue; - if(p->noteid != noteid || p->kp) - continue; - qlock(&p->debug); - if(p->noteid == noteid) - postnote(p, 0, n, flag); - qunlock(&p->debug); - } -} - static void clearwatchpt(Proc *p); static Chan* @@ -1421,6 +1403,12 @@ parsetime(vlong *rt, char *s) static void procctlreq(Proc *p, char *va, int n) { + static Note killnote = { + "sys: killed", + NExit, + 1, + }; + Segment *s; uintptr npc; int pri; @@ -1455,12 +1443,14 @@ procctlreq(Proc *p, char *va, int n) break; case Stopped: p->procctl = Proc_exitme; - postnote(p, 0, "sys: killed", NExit); + incref(&killnote); + pushnote(p, &killnote); ready(p); break; default: p->procctl = Proc_exitme; - postnote(p, 0, "sys: killed", NExit); + incref(&killnote); + pushnote(p, &killnote); } break; case CMnohang: @@ -1542,7 +1532,7 @@ procctlreq(Proc *p, char *va, int n) } break; case CMinterrupt: - postnote(p, 0, nil, NUser); + procinterrupt(p); break; case CMnointerrupt: if(p->nnote == 0) diff --git a/sys/src/9/port/portdat.h b/sys/src/9/port/portdat.h index e658346a1..45a39be8e 100644 --- a/sys/src/9/port/portdat.h +++ b/sys/src/9/port/portdat.h @@ -314,6 +314,7 @@ struct Note { char msg[ERRMAX]; int flag; /* whether system posted it */ + Ref; }; enum @@ -629,7 +630,7 @@ enum TCSys, TCReal, - NERR = 64, + NERR = 32, NNOTE = 5, Npriq = 20, /* number of scheduler priority levels */ @@ -714,7 +715,7 @@ struct Proc int procctl; /* Control for /proc debugging */ uintptr pc; /* DEBUG only */ - Lock rlock; /* sync sleep/wakeup with postnote */ + Lock rlock; /* sync sleep/wakeup with procinterrupt */ Rendez *r; /* rendezvous point slept on */ Rendez sleep; /* place for syssleep/debug */ int notepending; /* note issued but not acted on */ diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index 2b71625b7..c6877690d 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -121,6 +121,7 @@ void free(void*); void freeb(Block*); void freeblist(Block*); int freebroken(void); +void freenote(Note*); void freenotes(Proc*); void freepages(Page*, Page*, ulong); void freepte(Segment*, Pte*); @@ -238,6 +239,7 @@ ulong pidalloc(Proc*); void portcountpagerefs(ulong*, int); char* popnote(Ureg*); int postnote(Proc*, int, char*, int); +void postnotepg(ulong, char*, int); int pprint(char*, ...); int preempted(void); void prflush(void); @@ -250,6 +252,7 @@ void procflushpseg(Physseg*); void procflushothers(void); int procindex(ulong); void procinit0(void); +void procinterrupt(Proc*); ulong procpagecount(Proc*); void procpriority(Proc*, int, int); void procsetuser(char*); @@ -261,6 +264,7 @@ Pte* ptecpy(Pte*); int pullblock(Block**, int); Block* pullupblock(Block*, int); Block* pullupqueue(Queue*, int); +int pushnote(Proc*, Note*); void putimage(Image*); void putmhead(Mhead*); void putmmu(uintptr, uintptr, Page*); diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index 713e0818a..3cf0cea9d 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -899,96 +899,19 @@ wakeup(Rendez *r) } /* - * pop a note from the calling process or suicide if theres - * no note handler or notify during note handling. - * Called from notify() with up->debug lock held. - */ -char* -popnote(Ureg *u) -{ - assert(!canqlock(&up->debug)); - - up->notepending = 0; - if(up->nnote == 0) - return nil; - assert(up->nnote > 0); - assert(up->note[0] != nil); - - /* hold off user notes during note handling */ - if(up->notified && up->note[0]->flag == NUser) - return nil; - - free(up->lastnote); - up->lastnote = up->note[0]; - if(--up->nnote > 0) - memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note*)); - up->note[up->nnote] = nil; - - if(u != nil && strncmp(up->lastnote->msg, "sys:", 4) == 0){ - int l = strlen(up->lastnote->msg); - assert(l < ERRMAX); - snprint(up->lastnote->msg+l, ERRMAX-l, " pc=%#p", u->pc); - } - - if(up->notify == nil || up->notified){ - qunlock(&up->debug); - if(up->lastnote->flag == NDebug){ - up->fpstate &= ~FPillegal; - pprint("suicide: %s\n", up->lastnote->msg); - } - pexit(up->lastnote->msg, up->lastnote->flag!=NDebug); - } - up->notified = 1; - - return up->lastnote->msg; -} - -/* * if waking a sleeping process, this routine must hold both * p->rlock and r->lock. However, it can't know them in * the same order as wakeup causing a possible lock ordering * deadlock. We break the deadlock by giving up the p->rlock * lock if we can't get the r->lock and retrying. */ -int -postnote(Proc *p, int dolock, char *msg, int flag) +void +procinterrupt(Proc *p) { - int s, ret; QLock *q; - Note *n; - - if(p == nil) - return 0; - - if(dolock) - qlock(&p->debug); - - if(p->pid == 0){ - if(dolock) - qunlock(&p->debug); - return 0; - } + int s; - ret = 0; - if(msg != nil){ - if(flag != NUser && (p->notify == nil || p->notified)) - freenotes(p); - if(p->nnote < NNOTE){ - if(flag != NUser) - n = smalloc(sizeof(Note)); - else - n = malloc(sizeof(Note)); - if(n != nil){ - kstrcpy(n->msg, msg, ERRMAX); - n->flag = flag; - p->note[p->nnote++] = n; - ret = 1; - } - } - } p->notepending = 1; - if(dolock) - qunlock(&p->debug); /* this loop is to avoid lock ordering problems. */ for(;;){ @@ -1005,7 +928,7 @@ postnote(Proc *p, int dolock, char *msg, int flag) /* try for the second lock */ if(canlock(r)){ if(p->state != Wakeme || r->p != p) - panic("postnote: state %d %d %d", r->p != p, p->r != r, p->state); + panic("procinterrupt: state %d %d %d", r->p != p, p->r != r, p->state); p->r = nil; r->p = nil; ready(p); @@ -1067,9 +990,125 @@ postnote(Proc *p, int dolock, char *msg, int flag) unlock(p->rgrp); break; } +} + +/* + * pop a note from the calling process or suicide if theres + * no note handler or notify during note handling. + * Called from notify() with up->debug lock held. + */ +char* +popnote(Ureg *u) +{ + up->notepending = 0; + if(up->nnote == 0) + return nil; + assert(up->nnote > 0); + assert(up->note[0] != nil); + assert(up->note[0]->ref > 0); + + /* hold off user notes during note handling */ + if(up->notified && up->note[0]->flag == NUser) + return nil; + + freenote(up->lastnote); + up->lastnote = up->note[0]; + if(--up->nnote > 0) + memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note*)); + up->note[up->nnote] = nil; + + if(u != nil && up->lastnote->ref == 1 && strncmp(up->lastnote->msg, "sys:", 4) == 0){ + int l = strlen(up->lastnote->msg); + assert(l < ERRMAX); + snprint(up->lastnote->msg+l, ERRMAX-l, " pc=%#p", u->pc); + } + + if(up->notify == nil || up->notified){ + qunlock(&up->debug); + if(up->lastnote->flag == NDebug){ + up->fpstate &= ~FPillegal; + pprint("suicide: %s\n", up->lastnote->msg); + } + pexit(up->lastnote->msg, up->lastnote->flag!=NDebug); + } + up->notified = 1; + + return up->lastnote->msg; +} + +static Note* +mknote(char *msg, int flag) +{ + Note *n; + + n = smalloc(sizeof(Note)); + kstrcpy(n->msg, msg, ERRMAX); + n->flag = flag; + n->ref = 1; + return n; +} + +int +pushnote(Proc *p, Note *n) +{ + if(p->pid == 0){ + freenote(n); + return 0; + } + assert(n->ref > 0); + if(n->flag != NUser && (p->notify == nil || p->notified)) + freenotes(p); + if(p->nnote < NNOTE){ + p->note[p->nnote++] = n; + procinterrupt(p); + return 1; + } + freenote(n); + return 0; +} + +int +postnote(Proc *p, int dolock, char *msg, int flag) +{ + Note *n; + int ret; + + if(p == nil) + return 0; + + n = mknote(msg, flag); + if(dolock) + qlock(&p->debug); + ret = pushnote(p, n); + if(dolock) + qunlock(&p->debug); + return ret; } +void +postnotepg(ulong noteid, char *msg, int flag) +{ + Note *n; + Proc *p; + int i; + + n = mknote(msg, flag); + for(i = 0; (p = proctab(i)) != nil; i++){ + if(p == up) + continue; + if(p->noteid != noteid || p->kp) + continue; + qlock(&p->debug); + if(p->noteid == noteid){ + incref(n); + pushnote(p, n); + } + qunlock(&p->debug); + } + freenote(n); +} + /* * weird thing: keep at most NBROKEN around */ @@ -1133,10 +1172,18 @@ freebroken(void) } void +freenote(Note *n) +{ + if(n == nil || decref(n)) + return; + free(n); +} + +void freenotes(Proc *p) { while(p->nnote > 0){ - free(p->note[--p->nnote]); + freenote(p->note[--p->nnote]); up->note[p->nnote] = nil; } } @@ -1253,7 +1300,7 @@ pexit(char *exitstr, int freemem) } freenotes(up); - free(up->lastnote); + freenote(up->lastnote); up->lastnote = nil; up->notified = 0; diff --git a/sys/src/9/port/sysproc.c b/sys/src/9/port/sysproc.c index 16bcf90a1..c948cfcba 100644 --- a/sys/src/9/port/sysproc.c +++ b/sys/src/9/port/sysproc.c @@ -600,7 +600,7 @@ sysexec(va_list list) up->setargs = 0; freenotes(up); - free(up->lastnote); + freenote(up->lastnote); up->lastnote = nil; up->notify = nil; up->notified = 0; |