shithub: drawcpu

ref: b527faa7af4f7198fd12acc67de845c0bb4c437f
dir: /kern/postnote.c/

View raw version
#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;
}

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;
}

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 || p->noteid != noteid || p->kp)
			continue;
		qlock(&p->debug);
		if(p->noteid == noteid && !p->kp){
			incref(&n->ref);
			pushnote(p, n);
		}
		qunlock(&p->debug);
	}
	freenote(n);
}