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