ref: 9c00c613885deba1ed19e905604571ef432cab11
dir: /kern/postnote.c/
#include "u.h"
#include "lib.h"
#include "dat.h"
#include "fns.h"
#include "error.h"
void
freenote(Note *n)
{
if(n == nil || decref(&n->ref))
return;
free(n);
}
void
freenotes(Proc *p)
{
while(p->nnote > 0){
freenote(p->note[--p->nnote]);
up->note[p->nnote] = nil;
}
}
/*
* 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;
/* 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.ref == 1 && strncmp(up->lastnote->msg, "sys:", 4) == 0){
int l = strlen(up->lastnote->msg);
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)
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.ref = 1;
return n;
}
static int
pushnote(Proc *p, Note *n)
{
if(p->state <= New || p->state == Broken || p->pid == 0){
freenote(n);
return 0;
}
assert(n->ref.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;
}