xref: /plan9/sys/src/libthread/note.c (revision dc5a79c1208f0704eeb474acc990728f8b4854f5)
19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <thread.h>
49a747e4fSDavid du Colombier #include "threadimpl.h"
59a747e4fSDavid du Colombier 
69a747e4fSDavid du Colombier int	_threadnopasser;
79a747e4fSDavid du Colombier 
89a747e4fSDavid du Colombier #define	NFN		33
99a747e4fSDavid du Colombier #define	ERRLEN	48
109a747e4fSDavid du Colombier typedef struct Note Note;
119a747e4fSDavid du Colombier struct Note
129a747e4fSDavid du Colombier {
139a747e4fSDavid du Colombier 	Lock		inuse;
149a747e4fSDavid du Colombier 	Proc		*proc;		/* recipient */
159a747e4fSDavid du Colombier 	char		s[ERRMAX];	/* arg2 */
169a747e4fSDavid du Colombier };
179a747e4fSDavid du Colombier 
189a747e4fSDavid du Colombier static Note	notes[128];
199a747e4fSDavid du Colombier static Note	*enotes = notes+nelem(notes);
209a747e4fSDavid du Colombier static int		(*onnote[NFN])(void*, char*);
219a747e4fSDavid du Colombier static int		onnotepid[NFN];
229a747e4fSDavid du Colombier static Lock	onnotelock;
239a747e4fSDavid du Colombier 
249a747e4fSDavid du Colombier int
threadnotify(int (* f)(void *,char *),int in)259a747e4fSDavid du Colombier threadnotify(int (*f)(void*, char*), int in)
269a747e4fSDavid du Colombier {
279a747e4fSDavid du Colombier 	int i, topid;
289a747e4fSDavid du Colombier 	int (*from)(void*, char*), (*to)(void*, char*);
299a747e4fSDavid du Colombier 
309a747e4fSDavid du Colombier 	if(in){
319a747e4fSDavid du Colombier 		from = nil;
329a747e4fSDavid du Colombier 		to = f;
339a747e4fSDavid du Colombier 		topid = _threadgetproc()->pid;
349a747e4fSDavid du Colombier 	}else{
359a747e4fSDavid du Colombier 		from = f;
369a747e4fSDavid du Colombier 		to = nil;
379a747e4fSDavid du Colombier 		topid = 0;
389a747e4fSDavid du Colombier 	}
399a747e4fSDavid du Colombier 	lock(&onnotelock);
409a747e4fSDavid du Colombier 	for(i=0; i<NFN; i++)
419a747e4fSDavid du Colombier 		if(onnote[i]==from){
429a747e4fSDavid du Colombier 			onnote[i] = to;
439a747e4fSDavid du Colombier 			onnotepid[i] = topid;
449a747e4fSDavid du Colombier 			break;
459a747e4fSDavid du Colombier 		}
469a747e4fSDavid du Colombier 	unlock(&onnotelock);
479a747e4fSDavid du Colombier 	return i<NFN;
489a747e4fSDavid du Colombier }
499a747e4fSDavid du Colombier 
509a747e4fSDavid du Colombier static void
delayednotes(Proc * p,void * v)519a747e4fSDavid du Colombier delayednotes(Proc *p, void *v)
529a747e4fSDavid du Colombier {
539a747e4fSDavid du Colombier 	int i;
549a747e4fSDavid du Colombier 	Note *n;
559a747e4fSDavid du Colombier 	int (*fn)(void*, char*);
569a747e4fSDavid du Colombier 
579a747e4fSDavid du Colombier 	if(!p->pending)
589a747e4fSDavid du Colombier 		return;
599a747e4fSDavid du Colombier 
609a747e4fSDavid du Colombier 	p->pending = 0;
619a747e4fSDavid du Colombier 	for(n=notes; n<enotes; n++){
629a747e4fSDavid du Colombier 		if(n->proc == p){
639a747e4fSDavid du Colombier 			for(i=0; i<NFN; i++){
649a747e4fSDavid du Colombier 				if(onnotepid[i]!=p->pid || (fn = onnote[i])==nil)
659a747e4fSDavid du Colombier 					continue;
669a747e4fSDavid du Colombier 				if((*fn)(v, n->s))
679a747e4fSDavid du Colombier 					break;
689a747e4fSDavid du Colombier 			}
699a747e4fSDavid du Colombier 			if(i==NFN){
709a747e4fSDavid du Colombier 				_threaddebug(DBGNOTE, "Unhandled note %s, proc %p\n", n->s, p);
719a747e4fSDavid du Colombier 				if(v != nil)
729a747e4fSDavid du Colombier 					noted(NDFLT);
739a747e4fSDavid du Colombier 				else if(strncmp(n->s, "sys:", 4)==0)
749a747e4fSDavid du Colombier 					abort();
759a747e4fSDavid du Colombier 				threadexitsall(n->s);
769a747e4fSDavid du Colombier 			}
779a747e4fSDavid du Colombier 			n->proc = nil;
789a747e4fSDavid du Colombier 			unlock(&n->inuse);
799a747e4fSDavid du Colombier 		}
809a747e4fSDavid du Colombier 	}
819a747e4fSDavid du Colombier }
829a747e4fSDavid du Colombier 
839a747e4fSDavid du Colombier void
_threadnote(void * v,char * s)849a747e4fSDavid du Colombier _threadnote(void *v, char *s)
859a747e4fSDavid du Colombier {
869a747e4fSDavid du Colombier 	Proc *p;
879a747e4fSDavid du Colombier 	Note *n;
889a747e4fSDavid du Colombier 
899a747e4fSDavid du Colombier 	_threaddebug(DBGNOTE, "Got note %s", s);
909a747e4fSDavid du Colombier 	if(strncmp(s, "sys:", 4) == 0)
919a747e4fSDavid du Colombier 		noted(NDFLT);
929a747e4fSDavid du Colombier 
93*dc5a79c1SDavid du Colombier 	if(_threadexitsallstatus){
94*dc5a79c1SDavid du Colombier 		_threaddebug(DBGNOTE, "Threadexitsallstatus = '%s'\n", _threadexitsallstatus);
95*dc5a79c1SDavid du Colombier 		_exits(_threadexitsallstatus);
96*dc5a79c1SDavid du Colombier 	}
979a747e4fSDavid du Colombier 
989a747e4fSDavid du Colombier 	if(strcmp(s, "threadint")==0)
999a747e4fSDavid du Colombier 		noted(NCONT);
1009a747e4fSDavid du Colombier 
1019a747e4fSDavid du Colombier 	p = _threadgetproc();
1029a747e4fSDavid du Colombier 	if(p == nil)
1039a747e4fSDavid du Colombier 		noted(NDFLT);
1049a747e4fSDavid du Colombier 
1059a747e4fSDavid du Colombier 	for(n=notes; n<enotes; n++)
1069a747e4fSDavid du Colombier 		if(canlock(&n->inuse))
1079a747e4fSDavid du Colombier 			break;
1089a747e4fSDavid du Colombier 	if(n==enotes)
1099a747e4fSDavid du Colombier 		sysfatal("libthread: too many delayed notes");
1109a747e4fSDavid du Colombier 	utfecpy(n->s, n->s+ERRMAX, s);
1119a747e4fSDavid du Colombier 	n->proc = p;
1129a747e4fSDavid du Colombier 	p->pending = 1;
1139a747e4fSDavid du Colombier 	if(!p->splhi)
1149a747e4fSDavid du Colombier 		delayednotes(p, v);
1159a747e4fSDavid du Colombier 	noted(NCONT);
1169a747e4fSDavid du Colombier }
1179a747e4fSDavid du Colombier 
1189a747e4fSDavid du Colombier int
_procsplhi(void)1199a747e4fSDavid du Colombier _procsplhi(void)
1209a747e4fSDavid du Colombier {
1219a747e4fSDavid du Colombier 	int s;
1229a747e4fSDavid du Colombier 	Proc *p;
1239a747e4fSDavid du Colombier 
1249a747e4fSDavid du Colombier 	p = _threadgetproc();
1259a747e4fSDavid du Colombier 	s = p->splhi;
1269a747e4fSDavid du Colombier 	p->splhi = 1;
1279a747e4fSDavid du Colombier 	return s;
1289a747e4fSDavid du Colombier }
1299a747e4fSDavid du Colombier 
1309a747e4fSDavid du Colombier void
_procsplx(int s)1319a747e4fSDavid du Colombier _procsplx(int s)
1329a747e4fSDavid du Colombier {
1339a747e4fSDavid du Colombier 	Proc *p;
1349a747e4fSDavid du Colombier 
1359a747e4fSDavid du Colombier 	p = _threadgetproc();
1369a747e4fSDavid du Colombier 	p->splhi = s;
1379a747e4fSDavid du Colombier 	if(s)
1389a747e4fSDavid du Colombier 		return;
1399a747e4fSDavid du Colombier 	if(p->pending)
1409a747e4fSDavid du Colombier 		delayednotes(p, nil);
1419a747e4fSDavid du Colombier }
1429a747e4fSDavid du Colombier 
143