ref: 3e115487969570445a58a5a351a7bf0e0ab5fc21
parent: 99529b80a3bbe35c5cd5dadf5f106632a2449e84
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Sep 3 13:30:04 EDT 2022
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.
--- a/sys/src/9/port/alarm.c
+++ b/sys/src/9/port/alarm.c
@@ -27,7 +27,13 @@
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);
--- a/sys/src/9/port/devproc.c
+++ b/sys/src/9/port/devproc.c
@@ -351,24 +351,6 @@
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 @@
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 @@
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 @@
}
break;
case CMinterrupt:
- postnote(p, 0, nil, NUser);
+ procinterrupt(p);
break;
case CMnointerrupt:
if(p->nnote == 0)
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -314,6 +314,7 @@
{
char msg[ERRMAX];
int flag; /* whether system posted it */
+ Ref;
};
enum
@@ -629,7 +630,7 @@
TCSys,
TCReal,
- NERR = 64,
+ NERR = 32,
NNOTE = 5,
Npriq = 20, /* number of scheduler priority levels */
@@ -714,7 +715,7 @@
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 */
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -121,6 +121,7 @@
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 @@
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 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 @@
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*);
--- a/sys/src/9/port/proc.c
+++ b/sys/src/9/port/proc.c
@@ -899,51 +899,6 @@
}
/*
- * 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
@@ -950,45 +905,13 @@
* 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;
+ int s;
- if(p == nil)
- return 0;
-
- if(dolock)
- qlock(&p->debug);
-
- if(p->pid == 0){
- if(dolock)
- qunlock(&p->debug);
- return 0;
- }
-
- 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 @@
/* 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 @@
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 @@
}
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 @@
}
freenotes(up);
- free(up->lastnote);
+ freenote(up->lastnote);
up->lastnote = nil;
up->notified = 0;
--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -600,7 +600,7 @@
up->setargs = 0;
freenotes(up);
- free(up->lastnote);
+ freenote(up->lastnote);
up->lastnote = nil;
up->notify = nil;
up->notified = 0;