xref: /plan9-contrib/sys/src/libthread/threadimpl.h (revision e7469f7cc458260881920c645908657cf1c4e7b7)
1 /*
2  * Some notes on locking:
3  *
4  *	All the locking woes come from implementing
5  *	threadinterrupt (and threadkill).
6  *
7  *	_threadgetproc()->thread is always a live pointer.
8  *	p->threads, p->ready, and _threadrgrp also contain
9  * 	live thread pointers.  These may only be consulted
10  *	while holding p->lock or _threadrgrp.lock; in procs
11  *	other than p, the pointers are only guaranteed to be live
12  *	while the lock is still being held.
13  *
14  *	Thread structures can only be freed by the proc
15  *	they belong to.  Threads marked with t->inrendez
16  * 	need to be extracted from the _threadrgrp before
17  *	being freed.
18  *
19  *	_threadrgrp.lock cannot be acquired while holding p->lock.
20  */
21 
22 typedef struct Pqueue	Pqueue;
23 typedef struct Rgrp		Rgrp;
24 typedef struct Tqueue	Tqueue;
25 typedef struct Thread	Thread;
26 typedef struct Execargs	Execargs;
27 typedef struct Execjob	Execjob;
28 typedef struct Proc		Proc;
29 
30 /* must match list in sched.c */
31 typedef enum
32 {
33 	Dead,
34 	Running,
35 	Ready,
36 	Rendezvous,
37 } State;
38 
39 typedef enum
40 {
41 	Channone,
42 	Chanalt,
43 	Chansend,
44 	Chanrecv,
45 } Chanstate;
46 
47 enum
48 {
49 	RENDHASH = 13,
50 	Printsize = 2048,
51 	NPRIV = 8,
52 };
53 
54 struct Rgrp
55 {
56 	Lock		lock;
57 	Thread	*hash[RENDHASH];
58 };
59 
60 struct Tqueue		/* Thread queue */
61 {
62 	int		asleep;
63 	Thread	*head;
64 	Thread	**tail;
65 };
66 
67 struct Thread
68 {
69 	Lock		lock;		/* protects thread data structure */
70 	jmp_buf		sched;		/* for context switches */
71 	int		id;		/* thread id */
72 	int 		grp;		/* thread group */
73 	int		moribund;	/* thread needs to die */
74 	State		state;		/* run state */
75 	State		nextstate;	/* next run state */
76 	uchar		*stk;		/* top of stack (lowest address of stack) */
77 	uint		stksize;	/* stack size */
78 	Thread		*next;		/* next on ready queue */
79 
80 	Proc		*proc;		/* proc of this thread */
81 	Thread		*nextt;		/* next on list of threads in this proc*/
82 	int		ret;		/* return value for Exec, Fork */
83 
84 	char		*cmdname;	/* ptr to name of thread */
85 
86 	int		inrendez;
87 	Thread		*rendhash;	/* Trgrp linked list */
88 	void*		rendtag;	/* rendezvous tag */
89 	void*		rendval;	/* rendezvous value */
90 	int		rendbreak;	/* rendezvous has been taken */
91 
92 	Chanstate	chan;		/* which channel operation is current */
93 	Alt		*alt;		/* pointer to current alt structure (debugging) */
94 
95 	void*	udata[NPRIV];	/* User per-thread data pointer */
96 };
97 
98 struct Execargs
99 {
100 	char		*prog;
101 	char		**args;
102 	int		fd[2];
103 };
104 
105 struct Execjob
106 {
107 	int *fd;
108 	char *cmd;
109 	char **argv;
110 	Channel *c;
111 };
112 
113 struct Proc
114 {
115 	Lock		lock;
116 	jmp_buf		sched;			/* for context switches */
117 	int		pid;			/* process id */
118 	int		splhi;			/* delay notes */
119 	Thread		*thread;		/* running thread */
120 
121 	int		needexec;
122 	Execargs	exec;			/* exec argument */
123 	Proc		*newproc;		/* fork argument */
124 	char		exitstr[ERRMAX];	/* exit status */
125 
126 	int		rforkflag;
127 	int		nthreads;
128 	Tqueue		threads;		/* All threads of this proc */
129 	Tqueue		ready;			/* Runnable threads */
130 	Lock		readylock;
131 
132 	char		printbuf[Printsize];
133 	int		blocked;		/* In a rendezvous */
134 	int		pending;		/* delayed note pending */
135 	int		nonotes;		/*  delay notes */
136 	uint		nextID;			/* ID of most recently created thread */
137 	Proc		*next;			/* linked list of Procs */
138 
139 	void		*arg;			/* passed between shared and unshared stk */
140 	char		str[ERRMAX];		/* used by threadexits to avoid malloc */
141 
142 	void*		wdata;			/* Lib(worker) per-proc data pointer */
143 	void*		udata;			/* User per-proc data pointer */
144 	char		threadint;		/* tag for threadexitsall() */
145 };
146 
147 struct Pqueue {		/* Proc queue */
148 	Lock		lock;
149 	Proc		*head;
150 	Proc		**tail;
151 };
152 
153 struct Ioproc
154 {
155 	int tid;
156 	Channel *c, *creply;
157 	int inuse;
158 	long (*op)(va_list*);
159 	va_list arg;
160 	long ret;
161 	char err[ERRMAX];
162 	Ioproc *next;
163 };
164 
165 void	_freeproc(Proc*);
166 void	_freethread(Thread*);
167 Proc*	_newproc(void(*)(void*), void*, uint, char*, int, int);
168 int	_procsplhi(void);
169 void	_procsplx(int);
170 void	_sched(void);
171 int	_schedexec(Execargs*);
172 void	_schedexecwait(void);
173 void	_schedexit(Proc*);
174 int	_schedfork(Proc*);
175 void	_schedinit(void*);
176 void	_systhreadinit(void);
177 void	_threadassert(char*);
178 void	_threadbreakrendez(void);
179 void	_threaddebug(ulong, char*, ...);
180 void	_threadexitsall(char*);
181 void	_threadflagrendez(Thread*);
182 Proc*	_threadgetproc(void);
183 void	_threadsetproc(Proc*);
184 void	_threadinitstack(Thread*, void(*)(void*), void*);
185 void*	_threadmalloc(long, int);
186 void	_threadnote(void*, char*);
187 void	_threadready(Thread*);
188 void*	_threadrendezvous(void*, void*);
189 void	_threadsignal(void);
190 void	_threadsysfatal(char*, va_list);
191 void**	_workerdata(void);
192 void	_xinc(long*);
193 long	_xdec(long*);
194 
195 extern int			_threaddebuglevel;
196 extern char*		_threadexitsallstatus;
197 extern Pqueue		_threadpq;
198 extern Channel*	_threadwaitchan;
199 extern Rgrp		_threadrgrp;
200 
201 #define DBGAPPL	(1 << 0)
202 #define DBGSCHED	(1 << 16)
203 #define DBGCHAN	(1 << 17)
204 #define DBGREND	(1 << 18)
205 /* #define DBGKILL	(1 << 19) */
206 #define DBGNOTE	(1 << 20)
207 #define DBGEXEC	(1 << 21)
208 
209 #define ioproc_arg(io, type)	(va_arg((io)->arg, type))
210