xref: /plan9/sys/src/libthread/threadimpl.h (revision 3ff48bf5ed603850fcd251ddf13025d23d693782)
19a747e4fSDavid du Colombier /*
29a747e4fSDavid du Colombier  * Some notes on locking:
39a747e4fSDavid du Colombier  *
49a747e4fSDavid du Colombier  *	All the locking woes come from implementing
59a747e4fSDavid du Colombier  *	threadinterrupt (and threadkill).
69a747e4fSDavid du Colombier  *
79a747e4fSDavid du Colombier  *	_threadgetproc()->thread is always a live pointer.
89a747e4fSDavid du Colombier  *	p->threads, p->ready, and _threadrgrp also contain
99a747e4fSDavid du Colombier  * 	live thread pointers.  These may only be consulted
109a747e4fSDavid du Colombier  *	while holding p->lock or _threadrgrp.lock; in procs
119a747e4fSDavid du Colombier  *	other than p, the pointers are only guaranteed to be live
129a747e4fSDavid du Colombier  *	while the lock is still being held.
139a747e4fSDavid du Colombier  *
149a747e4fSDavid du Colombier  *	Thread structures can only be freed by the proc
159a747e4fSDavid du Colombier  *	they belong to.  Threads marked with t->inrendez
169a747e4fSDavid du Colombier  * 	need to be extracted from the _threadrgrp before
179a747e4fSDavid du Colombier  *	being freed.
189a747e4fSDavid du Colombier  *
199a747e4fSDavid du Colombier  *	_threadrgrp.lock cannot be acquired while holding p->lock.
209a747e4fSDavid du Colombier  */
217dd7cddfSDavid du Colombier 
229a747e4fSDavid du Colombier typedef struct Pqueue	Pqueue;
239a747e4fSDavid du Colombier typedef struct Rgrp		Rgrp;
249a747e4fSDavid du Colombier typedef struct Tqueue	Tqueue;
259a747e4fSDavid du Colombier typedef struct Thread	Thread;
269a747e4fSDavid du Colombier typedef struct Execargs	Execargs;
279a747e4fSDavid du Colombier typedef struct Proc		Proc;
289a747e4fSDavid du Colombier 
299a747e4fSDavid du Colombier /* must match list in sched.c */
309a747e4fSDavid du Colombier typedef enum
319a747e4fSDavid du Colombier {
329a747e4fSDavid du Colombier 	Dead,
337dd7cddfSDavid du Colombier 	Running,
349a747e4fSDavid du Colombier 	Ready,
357dd7cddfSDavid du Colombier 	Rendezvous,
367dd7cddfSDavid du Colombier } State;
377dd7cddfSDavid du Colombier 
389a747e4fSDavid du Colombier typedef enum
399a747e4fSDavid du Colombier {
409a747e4fSDavid du Colombier 	Channone,
419a747e4fSDavid du Colombier 	Chanalt,
429a747e4fSDavid du Colombier 	Chansend,
439a747e4fSDavid du Colombier 	Chanrecv,
449a747e4fSDavid du Colombier } Chanstate;
457dd7cddfSDavid du Colombier 
469a747e4fSDavid du Colombier enum
479a747e4fSDavid du Colombier {
489a747e4fSDavid du Colombier 	RENDHASH = 13,
499a747e4fSDavid du Colombier 	Printsize = 2048,
507dd7cddfSDavid du Colombier };
517dd7cddfSDavid du Colombier 
529a747e4fSDavid du Colombier struct Rgrp
539a747e4fSDavid du Colombier {
547dd7cddfSDavid du Colombier 	Lock		lock;
559a747e4fSDavid du Colombier 	Thread	*hash[RENDHASH];
569a747e4fSDavid du Colombier };
579a747e4fSDavid du Colombier 
589a747e4fSDavid du Colombier struct Tqueue		/* Thread queue */
599a747e4fSDavid du Colombier {
609a747e4fSDavid du Colombier 	int		asleep;
617dd7cddfSDavid du Colombier 	Thread	*head;
629a747e4fSDavid du Colombier 	Thread	**tail;
637dd7cddfSDavid du Colombier };
647dd7cddfSDavid du Colombier 
659a747e4fSDavid du Colombier struct Thread
669a747e4fSDavid du Colombier {
679a747e4fSDavid du Colombier 	Lock		lock;			/* protects thread data structure */
689a747e4fSDavid du Colombier 	jmp_buf	sched;		/* for context switches */
699a747e4fSDavid du Colombier 	int		id;			/* thread id */
709a747e4fSDavid du Colombier 	int 		grp;			/* thread group */
719a747e4fSDavid du Colombier 	int		moribund;	/* thread needs to die */
729a747e4fSDavid du Colombier 	State		state;		/* run state */
739a747e4fSDavid du Colombier 	State		nextstate;		/* next run state */
749a747e4fSDavid du Colombier 	uchar	*stk;			/* top of stack (lowest address of stack) */
759a747e4fSDavid du Colombier 	uint		stksize;		/* stack size */
769a747e4fSDavid du Colombier 	Thread	*next;		/* next on ready queue */
7780ee5cbfSDavid du Colombier 
789a747e4fSDavid du Colombier 	Proc		*proc;		/* proc of this thread */
799a747e4fSDavid du Colombier 	Thread	*nextt;		/* next on list of threads in this proc*/
809a747e4fSDavid du Colombier 	int		ret;			/* return value for Exec, Fork */
819a747e4fSDavid du Colombier 
829a747e4fSDavid du Colombier 	char		*cmdname;	/* ptr to name of thread */
839a747e4fSDavid du Colombier 
849a747e4fSDavid du Colombier 	int		inrendez;
859a747e4fSDavid du Colombier 	Thread	*rendhash;	/* Trgrp linked list */
869a747e4fSDavid du Colombier 	ulong	rendtag;		/* rendezvous tag */
879a747e4fSDavid du Colombier 	ulong	rendval;		/* rendezvous value */
889a747e4fSDavid du Colombier 	int		rendbreak;	/* rendezvous has been taken */
899a747e4fSDavid du Colombier 
909a747e4fSDavid du Colombier 	Chanstate	chan;		/* which channel operation is current */
919a747e4fSDavid du Colombier 	Alt		*alt;			/* pointer to current alt structure (debugging) */
929a747e4fSDavid du Colombier 
939a747e4fSDavid du Colombier 	void*	udata;		/* User per-thread data pointer */
947dd7cddfSDavid du Colombier };
957dd7cddfSDavid du Colombier 
969a747e4fSDavid du Colombier struct Execargs
979a747e4fSDavid du Colombier {
989a747e4fSDavid du Colombier 	char		*prog;
999a747e4fSDavid du Colombier 	char		**args;
1009a747e4fSDavid du Colombier 	int		fd[2];
1019a747e4fSDavid du Colombier };
1029a747e4fSDavid du Colombier 
1039a747e4fSDavid du Colombier struct Proc
1049a747e4fSDavid du Colombier {
1057dd7cddfSDavid du Colombier 	Lock		lock;
1069a747e4fSDavid du Colombier 	jmp_buf	sched;		/* for context switches */
1079a747e4fSDavid du Colombier 	int		pid;			/* process id */
1089a747e4fSDavid du Colombier 	int		splhi;		/* delay notes */
1099a747e4fSDavid du Colombier 	Thread	*thread;		/* running thread */
1107dd7cddfSDavid du Colombier 
1119a747e4fSDavid du Colombier 	int		needexec;
1129a747e4fSDavid du Colombier 	Execargs	exec;		/* exec argument */
1139a747e4fSDavid du Colombier 	Proc		*newproc;	/* fork argument */
1149a747e4fSDavid du Colombier 	char		exitstr[ERRMAX];	/* exit status */
1157dd7cddfSDavid du Colombier 
1169a747e4fSDavid du Colombier 	int		rforkflag;
1177dd7cddfSDavid du Colombier 	int		nthreads;
1189a747e4fSDavid du Colombier 	Tqueue	threads;		/* All threads of this proc */
1199a747e4fSDavid du Colombier 	Tqueue	ready;		/* Runnable threads */
1209a747e4fSDavid du Colombier 	Lock		readylock;
1217dd7cddfSDavid du Colombier 
1229a747e4fSDavid du Colombier 	char		printbuf[Printsize];
1239a747e4fSDavid du Colombier 	int		blocked;		/* In a rendezvous */
1249a747e4fSDavid du Colombier 	int		pending;		/* delayed note pending */
1259a747e4fSDavid du Colombier 	int		nonotes;		/*  delay notes */
1269a747e4fSDavid du Colombier 	uint		nextID;		/* ID of most recently created thread */
1279a747e4fSDavid du Colombier 	Proc		*next;		/* linked list of Procs */
1287dd7cddfSDavid du Colombier 
1299a747e4fSDavid du Colombier 	void		*arg;			/* passed between shared and unshared stk */
1309a747e4fSDavid du Colombier 	char		str[ERRMAX];	/* used by threadexits to avoid malloc */
1317dd7cddfSDavid du Colombier 
1329a747e4fSDavid du Colombier 	void*	udata;		/* User per-proc data pointer */
1337dd7cddfSDavid du Colombier };
1347dd7cddfSDavid du Colombier 
1359a747e4fSDavid du Colombier struct Pqueue {		/* Proc queue */
1367dd7cddfSDavid du Colombier 	Lock		lock;
1377dd7cddfSDavid du Colombier 	Proc		*head;
1389a747e4fSDavid du Colombier 	Proc		**tail;
1397dd7cddfSDavid du Colombier };
1407dd7cddfSDavid du Colombier 
141*3ff48bf5SDavid du Colombier struct Ioproc
142*3ff48bf5SDavid du Colombier {
143*3ff48bf5SDavid du Colombier 	int pid;
144*3ff48bf5SDavid du Colombier 	Channel *c;
145*3ff48bf5SDavid du Colombier 	int inuse;
146*3ff48bf5SDavid du Colombier 	long (*op)(va_list*);
147*3ff48bf5SDavid du Colombier 	va_list arg;
148*3ff48bf5SDavid du Colombier 	long ret;
149*3ff48bf5SDavid du Colombier 	char err[ERRMAX];
150*3ff48bf5SDavid du Colombier 	Ioproc *next;
151*3ff48bf5SDavid du Colombier };
152*3ff48bf5SDavid du Colombier 
1539a747e4fSDavid du Colombier void		_freeproc(Proc*);
1549a747e4fSDavid du Colombier void		_freethread(Thread*);
1559a747e4fSDavid du Colombier Proc*	_newproc(void(*)(void*), void*, uint, char*, int, int);
1569a747e4fSDavid du Colombier int		_procsplhi(void);
1579a747e4fSDavid du Colombier void		_procsplx(int);
1589a747e4fSDavid du Colombier void		_sched(void);
1599a747e4fSDavid du Colombier int		_schedexec(Execargs*);
1609a747e4fSDavid du Colombier void		_schedexecwait(void);
1619a747e4fSDavid du Colombier void		_schedexit(Proc*);
1629a747e4fSDavid du Colombier int		_schedfork(Proc*);
1639a747e4fSDavid du Colombier void		_schedinit(void*);
1649a747e4fSDavid du Colombier void		_systhreadinit(void);
1659a747e4fSDavid du Colombier void		_threadassert(char*);
1669a747e4fSDavid du Colombier void		_threadbreakrendez(void);
1679a747e4fSDavid du Colombier void		_threaddebug(ulong, char*, ...);
1689a747e4fSDavid du Colombier void		_threadexitsall(char*);
1699a747e4fSDavid du Colombier void		_threadflagrendez(Thread*);
1709a747e4fSDavid du Colombier Proc*	_threadgetproc(void);
1719a747e4fSDavid du Colombier void		_threadsetproc(Proc*);
1729a747e4fSDavid du Colombier void		_threadinitstack(Thread*, void(*)(void*), void*);
1739a747e4fSDavid du Colombier void*	_threadmalloc(long, int);
1749a747e4fSDavid du Colombier void		_threadnote(void*, char*);
1759a747e4fSDavid du Colombier void		_threadready(Thread*);
17659cc4ca5SDavid du Colombier ulong	_threadrendezvous(ulong, ulong);
1779a747e4fSDavid du Colombier void		_threadsignal(void);
1789a747e4fSDavid du Colombier void		_threadsysfatal(char*, va_list);
1797dd7cddfSDavid du Colombier long		_xdec(long*);
1809a747e4fSDavid du Colombier void		_xinc(long*);
1819a747e4fSDavid du Colombier 
1829a747e4fSDavid du Colombier extern int			_threaddebuglevel;
1839a747e4fSDavid du Colombier extern char*		_threadexitsallstatus;
1849a747e4fSDavid du Colombier extern Pqueue		_threadpq;
1859a747e4fSDavid du Colombier extern Channel*	_threadwaitchan;
1869a747e4fSDavid du Colombier extern Rgrp		_threadrgrp;
1879a747e4fSDavid du Colombier 
1889a747e4fSDavid du Colombier #define DBGAPPL	(1 << 0)
1899a747e4fSDavid du Colombier #define DBGSCHED	(1 << 16)
1909a747e4fSDavid du Colombier #define DBGCHAN	(1 << 17)
1919a747e4fSDavid du Colombier #define DBGREND	(1 << 18)
1929a747e4fSDavid du Colombier /* #define DBGKILL	(1 << 19) */
1939a747e4fSDavid du Colombier #define DBGNOTE	(1 << 20)
1949a747e4fSDavid du Colombier #define DBGEXEC	(1 << 21)
195*3ff48bf5SDavid du Colombier 
196*3ff48bf5SDavid du Colombier #define ioproc_arg(io, type)	(va_arg((io)->arg, type))
197