194 lines · 4.3 KB · C
RawDownload
/*  * Some notes on locking: * *	All the locking woes come from implementing *	threadinterrupt (and threadkill). * *	_threadgetproc()->thread is always a live pointer. *	p->threads, p->ready, and _threadrgrp also contain * 	live thread pointers.  These may only be consulted *	while holding p->lock or _threadrgrp.lock; in procs *	other than p, the pointers are only guaranteed to be live *	while the lock is still being held. * *	Thread structures can only be freed by the proc *	they belong to.  Threads marked with t->inrendez * 	need to be extracted from the _threadrgrp before *	being freed. * *	_threadrgrp.lock cannot be acquired while holding p->lock. */ typedef struct Pqueue	Pqueue;typedef struct Rgrp		Rgrp;typedef struct Tqueue	Tqueue;typedef struct Thread	Thread;typedef struct Execargs	Execargs;typedef struct Proc		Proc;typedef struct Iocall	Iocall; /* must match list in sched.c */typedef enum{	Dead,	Running,	Ready,	Rendezvous,} State;	typedef enum{	Channone,	Chanalt,	Chansend,	Chanrecv,} Chanstate; enum{	RENDHASH = 13,}; struct Rgrp{	Lock		lock;	Thread	*hash[RENDHASH];}; struct Tqueue		/* Thread queue */{	int		asleep;	Thread	*head;	Thread	**tail;}; struct Thread{	Lock		lock;		/* protects thread data structure */	jmp_buf		sched;		/* for context switches */	int		id;		/* thread id */	int 		grp;		/* thread group */	int		moribund;	/* thread needs to die */	State		state;		/* run state */	State		nextstate;	/* next run state */	uchar		*stk;		/* top of stack (lowest address of stack) */	uint		stksize;	/* stack size */	Thread		*next;		/* next on ready queue */ 	Proc		*proc;		/* proc of this thread */	Thread		*nextt;		/* next on list of threads in this proc*/	int		ret;		/* return value for Exec, Fork */ 	char		*cmdname;	/* ptr to name of thread */ 	int		inrendez;	Thread		*rendhash;	/* Trgrp linked list */	void*		rendtag;	/* rendezvous tag */	void*		rendval;	/* rendezvous value */	int		rendbreak;	/* rendezvous has been taken */ 	Chanstate	chan;		/* which channel operation is current */	Alt		*alt;		/* pointer to current alt structure (debugging) */ 	void*		udata;		/* User per-thread data pointer */}; struct Execargs{	char		*prog;	char		**args;	int		fd[2];}; struct Proc{	Lock		lock;	jmp_buf		sched;			/* for context switches */	int		pid;			/* process id */	int		splhi;			/* delay notes */	Thread		*thread;		/* running thread */ 	int		needexec;	Execargs	exec;			/* exec argument */	Proc		*newproc;		/* fork argument */	char		exitstr[ERRMAX];	/* exit status */ 	int		rforkflag;	int		nthreads;	Tqueue		threads;		/* All threads of this proc */	Tqueue		ready;			/* Runnable threads */	Lock		readylock; 	int		pending;		/* delayed note pending */	Proc		*next;			/* linked list of Procs */ 	void*		udata;			/* User per-proc data pointer */	char		threadint;		/* tag for threadexitsall() */}; struct Pqueue		/* Proc queue */{	Lock		lock;	Proc		*head;	Proc		**tail;}; struct Ioproc{	QLock;	int		intr;	int		ctl;	Channel		*c, *creply;}; struct Iocall{	long		(*op)(va_list*);	va_list		arg;	long		ret;	char		err[ERRMAX];}; Proc*	_newproc(void(*)(void*), void*, uint, char*, int, int);int	_procsplhi(void);void	_procsplx(int);void	_sched(void);int	_schedexec(Execargs*);void	_schedexecwait(void);void	_schedexit(Proc*);int	_schedfork(Proc*);void	_schedinit(void);void	_threadassert(char*);void	_threadbreakrendez(void);void	_threadprint(char*, ...);void	_threadexitsall(char*);void	_threadflagrendez(Thread*);void	_threadinitstack(Thread*, void(*)(void*), void*);void*	_threadmalloc(long, int);void	_threadnote(void*, char*);void	_threadready(Thread*);void*	_threadrendezvous(void*, void*);void	_threadsysfatal(char*, va_list); Proc	**_threadprocp;#define	_threadgetproc()	(*_threadprocp)#define	_threadsetproc(p)	(*_threadprocp = (p)) extern int			_threaddebuglevel;extern char*		_threadexitsallstatus;extern Pqueue		_threadpq;extern Channel*	_threadwaitchan;extern Rgrp		_threadrgrp; #define DBGAPPL	(1 << 0)#define DBGSCHED	(1 << 16)#define DBGCHAN	(1 << 17)#define DBGREND	(1 << 18)/* #define DBGKILL	(1 << 19) */#define DBGNOTE	(1 << 20)#define DBGEXEC	(1 << 21) #pragma	varargck argpos _threadprint 1#define	_threaddebug(flag, ...)	if((_threaddebuglevel&(flag))==0){}else _threadprint(__VA_ARGS__) #define ioproc_arg(io, type)	(va_arg((io)->arg, type))