1112918Sjeff/*
2153496Sdavidxu * Copyright (C) 2005 Daniel M. Eischen <deischen@freebsd.org>
3153496Sdavidxu * Copyright (c) 2005 David Xu <davidxu@freebsd.org>
4112918Sjeff * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>.
5153496Sdavidxu *
6112918Sjeff * All rights reserved.
7112918Sjeff *
8112918Sjeff * Redistribution and use in source and binary forms, with or without
9112918Sjeff * modification, are permitted provided that the following conditions
10112918Sjeff * are met:
11112918Sjeff * 1. Redistributions of source code must retain the above copyright
12153496Sdavidxu *    notice unmodified, this list of conditions, and the following
13153496Sdavidxu *    disclaimer.
14112918Sjeff * 2. Redistributions in binary form must reproduce the above copyright
15112918Sjeff *    notice, this list of conditions and the following disclaimer in the
16112918Sjeff *    documentation and/or other materials provided with the distribution.
17112918Sjeff *
18153496Sdavidxu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19153496Sdavidxu * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20153496Sdavidxu * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21153496Sdavidxu * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22153496Sdavidxu * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23153496Sdavidxu * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24153496Sdavidxu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25153496Sdavidxu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26153496Sdavidxu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27153496Sdavidxu * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28112918Sjeff *
29112918Sjeff * $FreeBSD$
30112918Sjeff */
31112918Sjeff
32112918Sjeff#ifndef _THR_PRIVATE_H
33112918Sjeff#define _THR_PRIVATE_H
34112918Sjeff
35112918Sjeff/*
36112918Sjeff * Include files.
37112918Sjeff */
38112918Sjeff#include <sys/types.h>
39144518Sdavidxu#include <sys/time.h>
40112918Sjeff#include <sys/cdefs.h>
41112918Sjeff#include <sys/queue.h>
42176783Sdavidxu#include <sys/param.h>
43176783Sdavidxu#include <sys/cpuset.h>
44144518Sdavidxu#include <machine/atomic.h>
45144518Sdavidxu#include <errno.h>
46144518Sdavidxu#include <limits.h>
47112918Sjeff#include <signal.h>
48144518Sdavidxu#include <stddef.h>
49112918Sjeff#include <stdio.h>
50144518Sdavidxu#include <unistd.h>
51112918Sjeff#include <ucontext.h>
52144518Sdavidxu#include <sys/thr.h>
53144518Sdavidxu#include <pthread.h>
54144518Sdavidxu
55201546Sdavidxu#define	SYM_FB10(sym)			__CONCAT(sym, _fb10)
56201546Sdavidxu#define	SYM_FBP10(sym)			__CONCAT(sym, _fbp10)
57201546Sdavidxu#define	WEAK_REF(sym, alias)		__weak_reference(sym, alias)
58201546Sdavidxu#define	SYM_COMPAT(sym, impl, ver)	__sym_compat(sym, impl, ver)
59201546Sdavidxu#define	SYM_DEFAULT(sym, impl, ver)	__sym_default(sym, impl, ver)
60201546Sdavidxu
61201546Sdavidxu#define	FB10_COMPAT(func, sym)				\
62201546Sdavidxu	WEAK_REF(func, SYM_FB10(sym));			\
63201546Sdavidxu	SYM_COMPAT(sym, SYM_FB10(sym), FBSD_1.0)
64201546Sdavidxu
65201546Sdavidxu#define	FB10_COMPAT_PRIVATE(func, sym)			\
66201546Sdavidxu	WEAK_REF(func, SYM_FBP10(sym));			\
67201546Sdavidxu	SYM_DEFAULT(sym, SYM_FBP10(sym), FBSDprivate_1.0)
68201546Sdavidxu
69144518Sdavidxu#include "pthread_md.h"
70144518Sdavidxu#include "thr_umtx.h"
71144921Sdavidxu#include "thread_db.h"
72144518Sdavidxu
73212630Sdavidxu#ifdef _PTHREAD_FORCED_UNWIND
74213297Sdavidxu#define _BSD_SOURCE
75213297Sdavidxu#include <unwind.h>
76212630Sdavidxu#endif
77212630Sdavidxu
78153593Sdavidxutypedef TAILQ_HEAD(pthreadlist, pthread) pthreadlist;
79153593Sdavidxutypedef TAILQ_HEAD(atfork_head, pthread_atfork) atfork_head;
80161681SdavidxuTAILQ_HEAD(mutex_queue, pthread_mutex);
81112918Sjeff
82144518Sdavidxu/* Signal to do cancellation */
83234424Sgnn#define	SIGCANCEL		SIGTHR
84112918Sjeff
85112918Sjeff/*
86112918Sjeff * Kernel fatal error handler macro.
87112918Sjeff */
88144518Sdavidxu#define PANIC(string)		_thread_exit(__FILE__,__LINE__,string)
89112918Sjeff
90144518Sdavidxu/* Output debug messages like this: */
91144518Sdavidxu#define stdout_debug(args...)	_thread_printf(STDOUT_FILENO, ##args)
92171763Sdavidxu#define stderr_debug(args...)	_thread_printf(STDERR_FILENO, ##args)
93144518Sdavidxu
94144518Sdavidxu#ifdef _PTHREADS_INVARIANTS
95144518Sdavidxu#define THR_ASSERT(cond, msg) do {	\
96144518Sdavidxu	if (__predict_false(!(cond)))	\
97123351Smtm		PANIC(msg);		\
98123351Smtm} while (0)
99144518Sdavidxu#else
100144518Sdavidxu#define THR_ASSERT(cond, msg)
101144518Sdavidxu#endif
102123351Smtm
103154160Sdavidxu#ifdef PIC
104154160Sdavidxu# define STATIC_LIB_REQUIRE(name)
105154160Sdavidxu#else
106154160Sdavidxu# define STATIC_LIB_REQUIRE(name) __asm (".globl " #name)
107154160Sdavidxu#endif
108154160Sdavidxu
109144518Sdavidxu#define	TIMESPEC_ADD(dst, src, val)				\
110144518Sdavidxu	do { 							\
111144518Sdavidxu		(dst)->tv_sec = (src)->tv_sec + (val)->tv_sec;	\
112144518Sdavidxu		(dst)->tv_nsec = (src)->tv_nsec + (val)->tv_nsec; \
113147534Sdavidxu		if ((dst)->tv_nsec >= 1000000000) {		\
114144518Sdavidxu			(dst)->tv_sec++;			\
115144518Sdavidxu			(dst)->tv_nsec -= 1000000000;		\
116144518Sdavidxu		}						\
117117048Smtm	} while (0)
118117048Smtm
119144518Sdavidxu#define	TIMESPEC_SUB(dst, src, val)				\
120144518Sdavidxu	do { 							\
121144518Sdavidxu		(dst)->tv_sec = (src)->tv_sec - (val)->tv_sec;	\
122144518Sdavidxu		(dst)->tv_nsec = (src)->tv_nsec - (val)->tv_nsec; \
123144518Sdavidxu		if ((dst)->tv_nsec < 0) {			\
124144518Sdavidxu			(dst)->tv_sec--;			\
125144518Sdavidxu			(dst)->tv_nsec += 1000000000;		\
126144518Sdavidxu		}						\
127117276Smtm	} while (0)
128117048Smtm
129213241Sdavidxu/* XXX These values should be same as those defined in pthread.h */
130213241Sdavidxu#define	THR_MUTEX_INITIALIZER		((struct pthread_mutex *)NULL)
131213241Sdavidxu#define	THR_ADAPTIVE_MUTEX_INITIALIZER	((struct pthread_mutex *)1)
132213241Sdavidxu#define	THR_MUTEX_DESTROYED		((struct pthread_mutex *)2)
133213241Sdavidxu#define	THR_COND_INITIALIZER		((struct pthread_cond *)NULL)
134213241Sdavidxu#define	THR_COND_DESTROYED		((struct pthread_cond *)1)
135213241Sdavidxu#define	THR_RWLOCK_INITIALIZER		((struct pthread_rwlock *)NULL)
136213241Sdavidxu#define	THR_RWLOCK_DESTROYED		((struct pthread_rwlock *)1)
137213241Sdavidxu
138216641Sdavidxu#define PMUTEX_FLAG_TYPE_MASK	0x0ff
139216641Sdavidxu#define PMUTEX_FLAG_PRIVATE	0x100
140216641Sdavidxu#define PMUTEX_FLAG_DEFERED	0x200
141216641Sdavidxu#define PMUTEX_TYPE(mtxflags)	((mtxflags) & PMUTEX_FLAG_TYPE_MASK)
142216641Sdavidxu
143216641Sdavidxu#define MAX_DEFER_WAITERS       50
144216641Sdavidxu
145144518Sdavidxustruct pthread_mutex {
146144518Sdavidxu	/*
147144518Sdavidxu	 * Lock for accesses to this structure.
148144518Sdavidxu	 */
149161681Sdavidxu	struct umutex			m_lock;
150216641Sdavidxu	int				m_flags;
151144518Sdavidxu	struct pthread			*m_owner;
152144518Sdavidxu	int				m_count;
153174585Sdavidxu	int				m_spinloops;
154174585Sdavidxu	int				m_yieldloops;
155144518Sdavidxu	/*
156161681Sdavidxu	 * Link for all mutexes a thread currently owns.
157144518Sdavidxu	 */
158144518Sdavidxu	TAILQ_ENTRY(pthread_mutex)	m_qe;
159144518Sdavidxu};
160112918Sjeff
161112918Sjeffstruct pthread_mutex_attr {
162112918Sjeff	enum pthread_mutextype	m_type;
163112918Sjeff	int			m_protocol;
164112918Sjeff	int			m_ceiling;
165112918Sjeff};
166112918Sjeff
167112918Sjeff#define PTHREAD_MUTEXATTR_STATIC_INITIALIZER \
168112918Sjeff	{ PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, 0, MUTEX_FLAGS_PRIVATE }
169112918Sjeff
170144518Sdavidxustruct pthread_cond {
171216641Sdavidxu	__uint32_t	__has_user_waiters;
172216641Sdavidxu	__uint32_t	__has_kern_waiters;
173216641Sdavidxu	__uint32_t	__flags;
174216641Sdavidxu	__uint32_t	__clock_id;
175112958Sjeff};
176112958Sjeff
177144518Sdavidxustruct pthread_cond_attr {
178144518Sdavidxu	int		c_pshared;
179144518Sdavidxu	int		c_clockid;
180112918Sjeff};
181112918Sjeff
182144518Sdavidxustruct pthread_barrier {
183164903Sdavidxu	struct umutex		b_lock;
184164903Sdavidxu	struct ucond		b_cv;
185233022Sdavidxu	int64_t			b_cycle;
186233022Sdavidxu	int			b_count;
187233022Sdavidxu	int			b_waiters;
188233022Sdavidxu	int			b_refcount;
189233022Sdavidxu	int			b_destroying;
190124837Smtm};
191124837Smtm
192144518Sdavidxustruct pthread_barrierattr {
193144518Sdavidxu	int		pshared;
194112918Sjeff};
195112918Sjeff
196144518Sdavidxustruct pthread_spinlock {
197162061Sdavidxu	struct umutex	s_lock;
198112918Sjeff};
199112918Sjeff
200112918Sjeff/*
201112918Sjeff * Flags for condition variables.
202112918Sjeff */
203144518Sdavidxu#define COND_FLAGS_PRIVATE	0x01
204144518Sdavidxu#define COND_FLAGS_INITED	0x02
205144518Sdavidxu#define COND_FLAGS_BUSY		0x04
206112918Sjeff
207112918Sjeff/*
208112918Sjeff * Cleanup definitions.
209112918Sjeff */
210112918Sjeffstruct pthread_cleanup {
211179662Sdavidxu	struct pthread_cleanup	*prev;
212179662Sdavidxu	void			(*routine)(void *);
213112918Sjeff	void			*routine_arg;
214179662Sdavidxu	int			onheap;
215112918Sjeff};
216112918Sjeff
217144518Sdavidxu#define	THR_CLEANUP_PUSH(td, func, arg) {		\
218144518Sdavidxu	struct pthread_cleanup __cup;			\
219144518Sdavidxu							\
220144518Sdavidxu	__cup.routine = func;				\
221144518Sdavidxu	__cup.routine_arg = arg;			\
222179662Sdavidxu	__cup.onheap = 0;				\
223179662Sdavidxu	__cup.prev = (td)->cleanup;			\
224144518Sdavidxu	(td)->cleanup = &__cup;
225144518Sdavidxu
226144518Sdavidxu#define	THR_CLEANUP_POP(td, exec)			\
227179662Sdavidxu	(td)->cleanup = __cup.prev;			\
228144518Sdavidxu	if ((exec) != 0)				\
229144518Sdavidxu		__cup.routine(__cup.routine_arg);	\
230144518Sdavidxu}
231144518Sdavidxu
232131181Smtmstruct pthread_atfork {
233131181Smtm	TAILQ_ENTRY(pthread_atfork) qe;
234131181Smtm	void (*prepare)(void);
235131181Smtm	void (*parent)(void);
236131181Smtm	void (*child)(void);
237131181Smtm};
238131181Smtm
239112918Sjeffstruct pthread_attr {
240214334Sdavidxu#define pthread_attr_start_copy	sched_policy
241112918Sjeff	int	sched_policy;
242112918Sjeff	int	sched_inherit;
243112918Sjeff	int	prio;
244112918Sjeff	int	suspend;
245144518Sdavidxu#define	THR_STACK_USER		0x100	/* 0xFF reserved for <pthread.h> */
246112918Sjeff	int	flags;
247112918Sjeff	void	*stackaddr_attr;
248112918Sjeff	size_t	stacksize_attr;
249112918Sjeff	size_t	guardsize_attr;
250214334Sdavidxu#define pthread_attr_end_copy	cpuset
251176781Sdavidxu	cpuset_t	*cpuset;
252176781Sdavidxu	size_t	cpusetsize;
253112918Sjeff};
254112918Sjeff
255216641Sdavidxustruct wake_addr {
256216641Sdavidxu	struct wake_addr *link;
257216641Sdavidxu	unsigned int	value;
258216641Sdavidxu	char		pad[12];
259216641Sdavidxu};
260216641Sdavidxu
261216641Sdavidxustruct sleepqueue {
262216641Sdavidxu	TAILQ_HEAD(, pthread)    sq_blocked;
263216641Sdavidxu	SLIST_HEAD(, sleepqueue) sq_freeq;
264216641Sdavidxu	LIST_ENTRY(sleepqueue)   sq_hash;
265216641Sdavidxu	SLIST_ENTRY(sleepqueue)  sq_flink;
266216641Sdavidxu	void			 *sq_wchan;
267216641Sdavidxu	int			 sq_type;
268216641Sdavidxu};
269216641Sdavidxu
270112918Sjeff/*
271112918Sjeff * Thread creation state attributes.
272112918Sjeff */
273144518Sdavidxu#define THR_CREATE_RUNNING		0
274144518Sdavidxu#define THR_CREATE_SUSPENDED		1
275112918Sjeff
276112918Sjeff/*
277112918Sjeff * Miscellaneous definitions.
278112918Sjeff */
279144518Sdavidxu#define THR_STACK_DEFAULT		(sizeof(void *) / 4 * 1024 * 1024)
280112918Sjeff
281112918Sjeff/*
282112918Sjeff * Maximum size of initial thread's stack.  This perhaps deserves to be larger
283112918Sjeff * than the stacks of other threads, since many applications are likely to run
284112918Sjeff * almost entirely on this stack.
285112918Sjeff */
286144518Sdavidxu#define THR_STACK_INITIAL		(THR_STACK_DEFAULT * 2)
287112918Sjeff
288112918Sjeff/*
289158073Sdavidxu * Define priorities returned by kernel.
290112918Sjeff */
291158073Sdavidxu#define THR_MIN_PRIORITY		(_thr_priorities[SCHED_OTHER-1].pri_min)
292160287Sdavidxu#define THR_MAX_PRIORITY		(_thr_priorities[SCHED_OTHER-1].pri_max)
293158073Sdavidxu#define THR_DEF_PRIORITY		(_thr_priorities[SCHED_OTHER-1].pri_default)
294112918Sjeff
295158073Sdavidxu#define THR_MIN_RR_PRIORITY		(_thr_priorities[SCHED_RR-1].pri_min)
296158073Sdavidxu#define THR_MAX_RR_PRIORITY		(_thr_priorities[SCHED_RR-1].pri_max)
297158073Sdavidxu#define THR_DEF_RR_PRIORITY		(_thr_priorities[SCHED_RR-1].pri_default)
298112918Sjeff
299158073Sdavidxu/* XXX The SCHED_FIFO should have same priority range as SCHED_RR */
300158073Sdavidxu#define THR_MIN_FIFO_PRIORITY		(_thr_priorities[SCHED_FIFO_1].pri_min)
301160287Sdavidxu#define THR_MAX_FIFO_PRIORITY		(_thr_priorities[SCHED_FIFO-1].pri_max)
302158073Sdavidxu#define THR_DEF_FIFO_PRIORITY		(_thr_priorities[SCHED_FIFO-1].pri_default)
303158073Sdavidxu
304158073Sdavidxustruct pthread_prio {
305158073Sdavidxu	int	pri_min;
306158073Sdavidxu	int	pri_max;
307158073Sdavidxu	int	pri_default;
308158073Sdavidxu};
309158073Sdavidxu
310112918Sjeffstruct pthread_rwlockattr {
311112918Sjeff	int		pshared;
312112918Sjeff};
313112918Sjeff
314112918Sjeffstruct pthread_rwlock {
315177850Sdavidxu	struct urwlock 	lock;
316177770Sdavidxu	struct pthread	*owner;
317112918Sjeff};
318112918Sjeff
319112918Sjeff/*
320112918Sjeff * Thread states.
321112918Sjeff */
322112918Sjeffenum pthread_state {
323112918Sjeff	PS_RUNNING,
324144518Sdavidxu	PS_DEAD
325112918Sjeff};
326112918Sjeff
327112918Sjeffstruct pthread_specific_elem {
328112918Sjeff	const void	*data;
329112918Sjeff	int		seqno;
330112918Sjeff};
331112918Sjeff
332144518Sdavidxustruct pthread_key {
333144518Sdavidxu	volatile int	allocated;
334144518Sdavidxu	int		seqno;
335144518Sdavidxu	void            (*destructor)(void *);
336124718Smtm};
337124718Smtm
338112918Sjeff/*
339161681Sdavidxu * lwpid_t is 32bit but kernel thr API exports tid as long type
340161681Sdavidxu * in very earily date.
341161681Sdavidxu */
342161681Sdavidxu#define TID(thread)	((uint32_t) ((thread)->tid))
343161681Sdavidxu
344161681Sdavidxu/*
345112918Sjeff * Thread structure.
346112918Sjeff */
347112918Sjeffstruct pthread {
348231106Sdavidxu#define _pthread_startzero	tid
349157194Sdavidxu	/* Kernel thread id. */
350157194Sdavidxu	long			tid;
351157194Sdavidxu#define	TID_TERMINATED		1
352112918Sjeff
353112918Sjeff	/*
354112918Sjeff	 * Lock for accesses to this thread structure.
355112918Sjeff	 */
356162061Sdavidxu	struct umutex		lock;
357112918Sjeff
358144518Sdavidxu	/* Internal condition variable cycle number. */
359178647Sdavidxu	uint32_t		cycle;
360144518Sdavidxu
361144518Sdavidxu	/* How many low level locks the thread held. */
362144518Sdavidxu	int			locklevel;
363144518Sdavidxu
364154055Sdavidxu	/*
365154055Sdavidxu	 * Set to non-zero when this thread has entered a critical
366154055Sdavidxu	 * region.  We allow for recursive entries into critical regions.
367154055Sdavidxu	 */
368154055Sdavidxu	int			critical_count;
369154055Sdavidxu
370144518Sdavidxu	/* Signal blocked counter. */
371144518Sdavidxu	int			sigblock;
372144518Sdavidxu
373144518Sdavidxu	/* Queue entry for list of all threads. */
374144518Sdavidxu	TAILQ_ENTRY(pthread)	tle;	/* link for all threads in process */
375144518Sdavidxu
376144518Sdavidxu	/* Queue entry for GC lists. */
377144518Sdavidxu	TAILQ_ENTRY(pthread)	gcle;
378144518Sdavidxu
379144518Sdavidxu	/* Hash queue entry. */
380144518Sdavidxu	LIST_ENTRY(pthread)	hle;
381144518Sdavidxu
382216641Sdavidxu	/* Sleep queue entry */
383216641Sdavidxu	TAILQ_ENTRY(pthread)    wle;
384216641Sdavidxu
385144518Sdavidxu	/* Threads reference count. */
386144518Sdavidxu	int			refcount;
387144518Sdavidxu
388112918Sjeff	/*
389112918Sjeff	 * Thread start routine, argument, stack pointer and thread
390112918Sjeff	 * attributes.
391112918Sjeff	 */
392112918Sjeff	void			*(*start_routine)(void *);
393112918Sjeff	void			*arg;
394112918Sjeff	struct pthread_attr	attr;
395112918Sjeff
396164583Sdavidxu#define	SHOULD_CANCEL(thr)					\
397212841Sdavidxu	((thr)->cancel_pending && (thr)->cancel_enable &&	\
398212841Sdavidxu	 (thr)->no_cancel == 0)
399112918Sjeff
400164583Sdavidxu	/* Cancellation is enabled */
401164583Sdavidxu	int			cancel_enable;
402112918Sjeff
403164583Sdavidxu	/* Cancellation request is pending */
404164583Sdavidxu	int			cancel_pending;
405164583Sdavidxu
406164583Sdavidxu	/* Thread is at cancellation point */
407164583Sdavidxu	int			cancel_point;
408164583Sdavidxu
409212841Sdavidxu	/* Cancellation is temporarily disabled */
410212841Sdavidxu	int			no_cancel;
411164877Sdavidxu
412164583Sdavidxu	/* Asynchronouse cancellation is enabled */
413164583Sdavidxu	int			cancel_async;
414164583Sdavidxu
415164583Sdavidxu	/* Cancellation is in progress */
416164583Sdavidxu	int			cancelling;
417164583Sdavidxu
418144518Sdavidxu	/* Thread temporary signal mask. */
419144518Sdavidxu	sigset_t		sigmask;
420112918Sjeff
421212076Sdavidxu	/* Thread should unblock SIGCANCEL. */
422176784Sdavidxu	int			unblock_sigcancel;
423176784Sdavidxu
424212076Sdavidxu	/* In sigsuspend state */
425212076Sdavidxu	int			in_sigsuspend;
426212076Sdavidxu
427212076Sdavidxu	/* deferred signal info	*/
428212076Sdavidxu	siginfo_t		deferred_siginfo;
429212076Sdavidxu
430212076Sdavidxu	/* signal mask to restore. */
431212076Sdavidxu	sigset_t		deferred_sigmask;
432212076Sdavidxu
433212076Sdavidxu	/* the sigaction should be used for deferred signal. */
434212076Sdavidxu	struct sigaction	deferred_sigact;
435212076Sdavidxu
436258766Skib	/* deferred signal delivery is performed, do not reenter. */
437258766Skib	int			deferred_run;
438258766Skib
439176817Sdavidxu	/* Force new thread to exit. */
440176817Sdavidxu	int			force_exit;
441176817Sdavidxu
442144518Sdavidxu	/* Thread state: */
443163307Sdavidxu	enum pthread_state 	state;
444144518Sdavidxu
445112918Sjeff	/*
446112918Sjeff	 * Error variable used instead of errno. The function __error()
447112918Sjeff	 * returns a pointer to this.
448112918Sjeff	 */
449144518Sdavidxu	int			error;
450112918Sjeff
451112918Sjeff	/*
452112918Sjeff	 * The joiner is the thread that is joining to this thread.  The
453112918Sjeff	 * join status keeps track of a join operation to another thread.
454112918Sjeff	 */
455112918Sjeff	struct pthread		*joiner;
456112918Sjeff
457144518Sdavidxu	/* Miscellaneous flags; only set with scheduling lock held. */
458144518Sdavidxu	int			flags;
459144518Sdavidxu#define THR_FLAGS_PRIVATE	0x0001
460144518Sdavidxu#define	THR_FLAGS_NEED_SUSPEND	0x0002	/* thread should be suspended */
461144518Sdavidxu#define	THR_FLAGS_SUSPENDED	0x0004	/* thread is suspended */
462212629Sdavidxu#define	THR_FLAGS_DETACHED	0x0008	/* thread is detached */
463144518Sdavidxu
464144518Sdavidxu	/* Thread list flags; only set with thread list lock held. */
465144518Sdavidxu	int			tlflags;
466144518Sdavidxu#define	TLFLAGS_GC_SAFE		0x0001	/* thread safe for cleaning */
467144518Sdavidxu#define	TLFLAGS_IN_TDLIST	0x0002	/* thread in all thread list */
468212629Sdavidxu#define	TLFLAGS_IN_GCLIST	0x0004	/* thread in gc list */
469144518Sdavidxu
470161681Sdavidxu	/* Queue of currently owned NORMAL or PRIO_INHERIT type mutexes. */
471161681Sdavidxu	struct mutex_queue	mutexq;
472112918Sjeff
473161681Sdavidxu	/* Queue of all owned PRIO_PROTECT mutexes. */
474161681Sdavidxu	struct mutex_queue	pp_mutexq;
475161681Sdavidxu
476112918Sjeff	void				*ret;
477112918Sjeff	struct pthread_specific_elem	*specific;
478112918Sjeff	int				specific_data_count;
479112918Sjeff
480144518Sdavidxu	/* Number rwlocks rdlocks held. */
481144518Sdavidxu	int			rdlock_count;
482144518Sdavidxu
483112918Sjeff	/*
484144518Sdavidxu	 * Current locks bitmap for rtld. */
485144518Sdavidxu	int			rtld_bits;
486112918Sjeff
487144518Sdavidxu	/* Thread control block */
488144518Sdavidxu	struct tcb		*tcb;
489144518Sdavidxu
490112918Sjeff	/* Cleanup handlers Link List */
491144518Sdavidxu	struct pthread_cleanup	*cleanup;
492144921Sdavidxu
493212630Sdavidxu#ifdef _PTHREAD_FORCED_UNWIND
494212630Sdavidxu	struct _Unwind_Exception	ex;
495212630Sdavidxu	void			*unwind_stackend;
496213161Sdavidxu	int			unwind_disabled;
497212630Sdavidxu#endif
498212630Sdavidxu
499157194Sdavidxu	/*
500157194Sdavidxu	 * Magic value to help recognize a valid thread structure
501157194Sdavidxu	 * from an invalid one:
502157194Sdavidxu	 */
503157194Sdavidxu#define	THR_MAGIC		((u_int32_t) 0xd09ba115)
504157194Sdavidxu	u_int32_t		magic;
505157194Sdavidxu
506144921Sdavidxu	/* Enable event reporting */
507144921Sdavidxu	int			report_events;
508144921Sdavidxu
509144921Sdavidxu	/* Event mask */
510144921Sdavidxu	int			event_mask;
511144921Sdavidxu
512144921Sdavidxu	/* Event */
513144921Sdavidxu	td_event_msg_t		event_buf;
514216641Sdavidxu
515216641Sdavidxu	/* Wait channel */
516216641Sdavidxu	void			*wchan;
517216641Sdavidxu
518216641Sdavidxu	/* Referenced mutex. */
519216641Sdavidxu	struct pthread_mutex	*mutex_obj;
520216641Sdavidxu
521216641Sdavidxu	/* Thread will sleep. */
522216641Sdavidxu	int			will_sleep;
523216641Sdavidxu
524216641Sdavidxu	/* Number of threads deferred. */
525216641Sdavidxu	int			nwaiter_defer;
526216641Sdavidxu
527216641Sdavidxu	/* Deferred threads from pthread_cond_signal. */
528216641Sdavidxu	unsigned int 		*defer_waiters[MAX_DEFER_WAITERS];
529231106Sdavidxu#define _pthread_endzero	wake_addr
530231106Sdavidxu
531231106Sdavidxu	struct wake_addr	*wake_addr;
532231106Sdavidxu#define WAKE_ADDR(td)           ((td)->wake_addr)
533231106Sdavidxu
534231106Sdavidxu	/* Sleep queue */
535231106Sdavidxu	struct	sleepqueue	*sleepqueue;
536231106Sdavidxu
537112918Sjeff};
538112918Sjeff
539212536Sdavidxu#define THR_SHOULD_GC(thrd) 						\
540212536Sdavidxu	((thrd)->refcount == 0 && (thrd)->state == PS_DEAD &&		\
541212536Sdavidxu	 ((thrd)->flags & THR_FLAGS_DETACHED) != 0)
542212536Sdavidxu
543154055Sdavidxu#define	THR_IN_CRITICAL(thrd)				\
544154055Sdavidxu	(((thrd)->locklevel > 0) ||			\
545154055Sdavidxu	((thrd)->critical_count > 0))
546154055Sdavidxu
547157111Sdavidxu#define	THR_CRITICAL_ENTER(thrd)			\
548157111Sdavidxu	(thrd)->critical_count++
549157111Sdavidxu
550157111Sdavidxu#define	THR_CRITICAL_LEAVE(thrd)			\
551177871Sdavidxu	do {						\
552177871Sdavidxu		(thrd)->critical_count--;		\
553177871Sdavidxu		_thr_ast(thrd);				\
554177871Sdavidxu	} while (0)
555157111Sdavidxu
556162061Sdavidxu#define THR_UMUTEX_TRYLOCK(thrd, lck)			\
557162061Sdavidxu	_thr_umutex_trylock((lck), TID(thrd))
558144518Sdavidxu
559162061Sdavidxu#define	THR_UMUTEX_LOCK(thrd, lck)			\
560162061Sdavidxu	_thr_umutex_lock((lck), TID(thrd))
561144518Sdavidxu
562162061Sdavidxu#define	THR_UMUTEX_TIMEDLOCK(thrd, lck, timo)		\
563162061Sdavidxu	_thr_umutex_timedlock((lck), TID(thrd), (timo))
564144518Sdavidxu
565162061Sdavidxu#define	THR_UMUTEX_UNLOCK(thrd, lck)			\
566162061Sdavidxu	_thr_umutex_unlock((lck), TID(thrd))
567144518Sdavidxu
568144518Sdavidxu#define	THR_LOCK_ACQUIRE(thrd, lck)			\
569144518Sdavidxudo {							\
570144518Sdavidxu	(thrd)->locklevel++;				\
571162061Sdavidxu	_thr_umutex_lock(lck, TID(thrd));		\
572144518Sdavidxu} while (0)
573144518Sdavidxu
574216641Sdavidxu#define	THR_LOCK_ACQUIRE_SPIN(thrd, lck)		\
575216641Sdavidxudo {							\
576216641Sdavidxu	(thrd)->locklevel++;				\
577216641Sdavidxu	_thr_umutex_lock_spin(lck, TID(thrd));		\
578216641Sdavidxu} while (0)
579216641Sdavidxu
580154129Sdavidxu#ifdef	_PTHREADS_INVARIANTS
581154129Sdavidxu#define	THR_ASSERT_LOCKLEVEL(thrd)			\
582144518Sdavidxudo {							\
583154129Sdavidxu	if (__predict_false((thrd)->locklevel <= 0))	\
584144518Sdavidxu		_thr_assert_lock_level();		\
585144518Sdavidxu} while (0)
586154129Sdavidxu#else
587154129Sdavidxu#define THR_ASSERT_LOCKLEVEL(thrd)
588154129Sdavidxu#endif
589144518Sdavidxu
590154129Sdavidxu#define	THR_LOCK_RELEASE(thrd, lck)			\
591154129Sdavidxudo {							\
592154129Sdavidxu	THR_ASSERT_LOCKLEVEL(thrd);			\
593162061Sdavidxu	_thr_umutex_unlock((lck), TID(thrd));		\
594154129Sdavidxu	(thrd)->locklevel--;				\
595154129Sdavidxu	_thr_ast(thrd);					\
596154129Sdavidxu} while (0)
597154129Sdavidxu
598144518Sdavidxu#define	THR_LOCK(curthrd)		THR_LOCK_ACQUIRE(curthrd, &(curthrd)->lock)
599144518Sdavidxu#define	THR_UNLOCK(curthrd)		THR_LOCK_RELEASE(curthrd, &(curthrd)->lock)
600144518Sdavidxu#define	THR_THREAD_LOCK(curthrd, thr)	THR_LOCK_ACQUIRE(curthrd, &(thr)->lock)
601144518Sdavidxu#define	THR_THREAD_UNLOCK(curthrd, thr)	THR_LOCK_RELEASE(curthrd, &(thr)->lock)
602144518Sdavidxu
603212536Sdavidxu#define	THREAD_LIST_RDLOCK(curthrd)				\
604144518Sdavidxudo {								\
605212536Sdavidxu	(curthrd)->locklevel++;					\
606212536Sdavidxu	_thr_rwl_rdlock(&_thr_list_lock);			\
607144518Sdavidxu} while (0)
608144518Sdavidxu
609212536Sdavidxu#define	THREAD_LIST_WRLOCK(curthrd)				\
610212536Sdavidxudo {								\
611212536Sdavidxu	(curthrd)->locklevel++;					\
612212536Sdavidxu	_thr_rwl_wrlock(&_thr_list_lock);			\
613212536Sdavidxu} while (0)
614212536Sdavidxu
615144518Sdavidxu#define	THREAD_LIST_UNLOCK(curthrd)				\
616144518Sdavidxudo {								\
617212536Sdavidxu	_thr_rwl_unlock(&_thr_list_lock);			\
618212536Sdavidxu	(curthrd)->locklevel--;					\
619212536Sdavidxu	_thr_ast(curthrd);					\
620144518Sdavidxu} while (0)
621144518Sdavidxu
622112918Sjeff/*
623144518Sdavidxu * Macros to insert/remove threads to the all thread list and
624144518Sdavidxu * the gc list.
625112918Sjeff */
626144518Sdavidxu#define	THR_LIST_ADD(thrd) do {					\
627144518Sdavidxu	if (((thrd)->tlflags & TLFLAGS_IN_TDLIST) == 0) {	\
628144518Sdavidxu		TAILQ_INSERT_HEAD(&_thread_list, thrd, tle);	\
629144518Sdavidxu		_thr_hash_add(thrd);				\
630144518Sdavidxu		(thrd)->tlflags |= TLFLAGS_IN_TDLIST;		\
631144518Sdavidxu	}							\
632144518Sdavidxu} while (0)
633144518Sdavidxu#define	THR_LIST_REMOVE(thrd) do {				\
634144518Sdavidxu	if (((thrd)->tlflags & TLFLAGS_IN_TDLIST) != 0) {	\
635144518Sdavidxu		TAILQ_REMOVE(&_thread_list, thrd, tle);		\
636144518Sdavidxu		_thr_hash_remove(thrd);				\
637144518Sdavidxu		(thrd)->tlflags &= ~TLFLAGS_IN_TDLIST;		\
638144518Sdavidxu	}							\
639144518Sdavidxu} while (0)
640144518Sdavidxu#define	THR_GCLIST_ADD(thrd) do {				\
641212629Sdavidxu	if (((thrd)->tlflags & TLFLAGS_IN_GCLIST) == 0) {	\
642144518Sdavidxu		TAILQ_INSERT_HEAD(&_thread_gc_list, thrd, gcle);\
643212629Sdavidxu		(thrd)->tlflags |= TLFLAGS_IN_GCLIST;		\
644144518Sdavidxu		_gc_count++;					\
645144518Sdavidxu	}							\
646144518Sdavidxu} while (0)
647144518Sdavidxu#define	THR_GCLIST_REMOVE(thrd) do {				\
648212629Sdavidxu	if (((thrd)->tlflags & TLFLAGS_IN_GCLIST) != 0) {	\
649144518Sdavidxu		TAILQ_REMOVE(&_thread_gc_list, thrd, gcle);	\
650212629Sdavidxu		(thrd)->tlflags &= ~TLFLAGS_IN_GCLIST;		\
651144518Sdavidxu		_gc_count--;					\
652144518Sdavidxu	}							\
653144518Sdavidxu} while (0)
654112918Sjeff
655212536Sdavidxu#define THR_REF_ADD(curthread, pthread) {			\
656212536Sdavidxu	THR_CRITICAL_ENTER(curthread);				\
657212536Sdavidxu	pthread->refcount++;					\
658212536Sdavidxu} while (0)
659212536Sdavidxu
660212536Sdavidxu#define THR_REF_DEL(curthread, pthread) {			\
661212536Sdavidxu	pthread->refcount--;					\
662212536Sdavidxu	THR_CRITICAL_LEAVE(curthread);				\
663212536Sdavidxu} while (0)
664212536Sdavidxu
665144518Sdavidxu#define GC_NEEDED()	(_gc_count >= 5)
666112918Sjeff
667144921Sdavidxu#define SHOULD_REPORT_EVENT(curthr, e)			\
668144921Sdavidxu	(curthr->report_events && 			\
669144921Sdavidxu	 (((curthr)->event_mask | _thread_event_mask ) & e) != 0)
670144921Sdavidxu
671144518Sdavidxuextern int __isthreaded;
672112918Sjeff
673115305Smtm/*
674144518Sdavidxu * Global variables for the pthread kernel.
675115305Smtm */
676115305Smtm
677157457Sdavidxuextern char		*_usrstack __hidden;
678153593Sdavidxuextern struct pthread	*_thr_initial __hidden;
679144921Sdavidxu
680144518Sdavidxu/* For debugger */
681153593Sdavidxuextern int		_libthr_debug;
682153593Sdavidxuextern int		_thread_event_mask;
683153593Sdavidxuextern struct pthread	*_thread_last_event;
684115305Smtm
685144518Sdavidxu/* List of all threads: */
686153593Sdavidxuextern pthreadlist	_thread_list;
687112918Sjeff
688144518Sdavidxu/* List of threads needing GC: */
689153593Sdavidxuextern pthreadlist	_thread_gc_list __hidden;
690131181Smtm
691153593Sdavidxuextern int		_thread_active_threads;
692153593Sdavidxuextern atfork_head	_thr_atfork_list __hidden;
693212077Sdavidxuextern struct urwlock	_thr_atfork_lock __hidden;
694144518Sdavidxu
695112918Sjeff/* Default thread attributes: */
696153593Sdavidxuextern struct pthread_attr _pthread_attr_default __hidden;
697112918Sjeff
698112918Sjeff/* Default mutex attributes: */
699153593Sdavidxuextern struct pthread_mutex_attr _pthread_mutexattr_default __hidden;
700213241Sdavidxuextern struct pthread_mutex_attr _pthread_mutexattr_adaptive_default __hidden;
701112918Sjeff
702112918Sjeff/* Default condition variable attributes: */
703153593Sdavidxuextern struct pthread_cond_attr _pthread_condattr_default __hidden;
704112918Sjeff
705158073Sdavidxuextern struct pthread_prio _thr_priorities[] __hidden;
706158073Sdavidxu
707153593Sdavidxuextern pid_t	_thr_pid __hidden;
708165241Sdavidxuextern int	_thr_is_smp __hidden;
709161068Sdavidxu
710157457Sdavidxuextern size_t	_thr_guard_default __hidden;
711157457Sdavidxuextern size_t	_thr_stack_default __hidden;
712157457Sdavidxuextern size_t	_thr_stack_initial __hidden;
713153593Sdavidxuextern int	_thr_page_size __hidden;
714173173Sdavidxuextern int	_thr_spinloops __hidden;
715173173Sdavidxuextern int	_thr_yieldloops __hidden;
716234947Sdavidxuextern int	_thr_queuefifo __hidden;
717173173Sdavidxu
718144518Sdavidxu/* Garbage thread count. */
719153593Sdavidxuextern int	_gc_count __hidden;
720112918Sjeff
721162061Sdavidxuextern struct umutex	_mutex_static_lock __hidden;
722162061Sdavidxuextern struct umutex	_cond_static_lock __hidden;
723162061Sdavidxuextern struct umutex	_rwlock_static_lock __hidden;
724162061Sdavidxuextern struct umutex	_keytable_lock __hidden;
725212536Sdavidxuextern struct urwlock	_thr_list_lock __hidden;
726162061Sdavidxuextern struct umutex	_thr_event_lock __hidden;
727239718Sdavidxuextern struct umutex	_suspend_all_lock __hidden;
728239718Sdavidxuextern int		_suspend_all_waiters __hidden;
729239718Sdavidxuextern int		_suspend_all_cycle __hidden;
730239718Sdavidxuextern struct pthread	*_single_thread __hidden;
731117026Sjdp
732112918Sjeff/*
733112918Sjeff * Function prototype definitions.
734112918Sjeff */
735112918Sjeff__BEGIN_DECLS
736153593Sdavidxuint	_thr_setthreaded(int) __hidden;
737239200Sdavidxuint	_mutex_cv_lock(struct pthread_mutex *, int) __hidden;
738239200Sdavidxuint	_mutex_cv_unlock(struct pthread_mutex *, int *, int *) __hidden;
739239200Sdavidxuint     _mutex_cv_attach(struct pthread_mutex *, int) __hidden;
740239200Sdavidxuint     _mutex_cv_detach(struct pthread_mutex *, int *) __hidden;
741216641Sdavidxuint     _mutex_owned(struct pthread *, const struct pthread_mutex *) __hidden;
742153593Sdavidxuint	_mutex_reinit(pthread_mutex_t *) __hidden;
743153593Sdavidxuvoid	_mutex_fork(struct pthread *curthread) __hidden;
744153593Sdavidxuvoid	_libpthread_init(struct pthread *) __hidden;
745153593Sdavidxustruct pthread *_thr_alloc(struct pthread *) __hidden;
746157457Sdavidxuvoid	_thread_exit(const char *, int, const char *) __hidden __dead2;
747153593Sdavidxuint	_thr_ref_add(struct pthread *, struct pthread *, int) __hidden;
748153593Sdavidxuvoid	_thr_ref_delete(struct pthread *, struct pthread *) __hidden;
749154055Sdavidxuvoid	_thr_ref_delete_unlocked(struct pthread *, struct pthread *) __hidden;
750153593Sdavidxuint	_thr_find_thread(struct pthread *, struct pthread *, int) __hidden;
751153593Sdavidxuvoid	_thr_rtld_init(void) __hidden;
752212076Sdavidxuvoid	_thr_rtld_postfork_child(void) __hidden;
753153593Sdavidxuint	_thr_stack_alloc(struct pthread_attr *) __hidden;
754153593Sdavidxuvoid	_thr_stack_free(struct pthread_attr *) __hidden;
755153593Sdavidxuvoid	_thr_free(struct pthread *, struct pthread *) __hidden;
756153593Sdavidxuvoid	_thr_gc(struct pthread *) __hidden;
757153593Sdavidxuvoid    _thread_cleanupspecific(void) __hidden;
758153593Sdavidxuvoid	_thread_printf(int, const char *, ...) __hidden;
759153593Sdavidxuvoid	_thr_spinlock_init(void) __hidden;
760164583Sdavidxuvoid	_thr_cancel_enter(struct pthread *) __hidden;
761212076Sdavidxuvoid	_thr_cancel_enter2(struct pthread *, int) __hidden;
762212076Sdavidxuvoid	_thr_cancel_leave(struct pthread *, int) __hidden;
763164583Sdavidxuvoid	_thr_testcancel(struct pthread *) __hidden;
764153593Sdavidxuvoid	_thr_signal_block(struct pthread *) __hidden;
765153593Sdavidxuvoid	_thr_signal_unblock(struct pthread *) __hidden;
766153593Sdavidxuvoid	_thr_signal_init(void) __hidden;
767153593Sdavidxuvoid	_thr_signal_deinit(void) __hidden;
768153593Sdavidxuint	_thr_send_sig(struct pthread *, int sig) __hidden;
769153593Sdavidxuvoid	_thr_list_init(void) __hidden;
770153593Sdavidxuvoid	_thr_hash_add(struct pthread *) __hidden;
771153593Sdavidxuvoid	_thr_hash_remove(struct pthread *) __hidden;
772153593Sdavidxustruct pthread *_thr_hash_find(struct pthread *) __hidden;
773154055Sdavidxuvoid	_thr_link(struct pthread *, struct pthread *) __hidden;
774154055Sdavidxuvoid	_thr_unlink(struct pthread *, struct pthread *) __hidden;
775153593Sdavidxuvoid	_thr_assert_lock_level(void) __hidden __dead2;
776154055Sdavidxuvoid	_thr_ast(struct pthread *) __hidden;
777155739Sdavidxuvoid	_thr_once_init(void) __hidden;
778144921Sdavidxuvoid	_thr_report_creation(struct pthread *curthread,
779157457Sdavidxu	    struct pthread *newthread) __hidden;
780153593Sdavidxuvoid	_thr_report_death(struct pthread *curthread) __hidden;
781162499Sdavidxuint	_thr_getscheduler(lwpid_t, int *, struct sched_param *) __hidden;
782162499Sdavidxuint	_thr_setscheduler(lwpid_t, int, const struct sched_param *) __hidden;
783212076Sdavidxuvoid	_thr_signal_prefork(void) __hidden;
784212076Sdavidxuvoid	_thr_signal_postfork(void) __hidden;
785212076Sdavidxuvoid	_thr_signal_postfork_child(void) __hidden;
786239718Sdavidxuvoid	_thr_suspend_all_lock(struct pthread *) __hidden;
787239718Sdavidxuvoid	_thr_suspend_all_unlock(struct pthread *) __hidden;
788212536Sdavidxuvoid	_thr_try_gc(struct pthread *, struct pthread *) __hidden;
789162499Sdavidxuint	_rtp_to_schedparam(const struct rtprio *rtp, int *policy,
790162499Sdavidxu		struct sched_param *param) __hidden;
791162499Sdavidxuint	_schedparam_to_rtp(int policy, const struct sched_param *param,
792162499Sdavidxu		struct rtprio *rtp) __hidden;
793144921Sdavidxuvoid	_thread_bp_create(void);
794144921Sdavidxuvoid	_thread_bp_death(void);
795173173Sdavidxuint	_sched_yield(void);
796112918Sjeff
797179662Sdavidxuvoid	_pthread_cleanup_push(void (*)(void *), void *);
798179662Sdavidxuvoid	_pthread_cleanup_pop(int);
799212076Sdavidxuvoid	_pthread_exit_mask(void *status, sigset_t *mask) __dead2 __hidden;
800213153Sdavidxuvoid	_pthread_cancel_enter(int maycancel);
801213153Sdavidxuvoid 	_pthread_cancel_leave(int maycancel);
802179662Sdavidxu
803144518Sdavidxu/* #include <fcntl.h> */
804144518Sdavidxu#ifdef  _SYS_FCNTL_H_
805144518Sdavidxuint     __sys_fcntl(int, int, ...);
806144518Sdavidxuint     __sys_open(const char *, int, ...);
807197968Sjillesint     __sys_openat(int, const char *, int, ...);
808112918Sjeff#endif
809112918Sjeff
810144518Sdavidxu/* #include <signal.h> */
811144518Sdavidxu#ifdef _SIGNAL_H_
812144518Sdavidxuint	__sys_kill(pid_t, int);
813144518Sdavidxuint     __sys_sigaction(int, const struct sigaction *, struct sigaction *);
814144518Sdavidxuint     __sys_sigpending(sigset_t *);
815144518Sdavidxuint     __sys_sigprocmask(int, const sigset_t *, sigset_t *);
816144518Sdavidxuint     __sys_sigsuspend(const sigset_t *);
817212076Sdavidxuint     __sys_sigreturn(const ucontext_t *);
818144518Sdavidxuint     __sys_sigaltstack(const struct sigaltstack *, struct sigaltstack *);
819157457Sdavidxuint	__sys_sigwait(const sigset_t *, int *);
820157457Sdavidxuint	__sys_sigtimedwait(const sigset_t *, siginfo_t *,
821157457Sdavidxu		const struct timespec *);
822157457Sdavidxuint	__sys_sigwaitinfo(const sigset_t *set, siginfo_t *info);
823112918Sjeff#endif
824112918Sjeff
825144518Sdavidxu/* #include <time.h> */
826144518Sdavidxu#ifdef	_TIME_H_
827144518Sdavidxuint	__sys_nanosleep(const struct timespec *, struct timespec *);
828112918Sjeff#endif
829112918Sjeff
830211737Sdavidxu/* #include <sys/ucontext.h> */
831211737Sdavidxu#ifdef _SYS_UCONTEXT_H_
832211737Sdavidxuint	__sys_setcontext(const ucontext_t *ucp);
833211737Sdavidxuint	__sys_swapcontext(ucontext_t *oucp, const ucontext_t *ucp);
834211737Sdavidxu#endif
835211737Sdavidxu
836144518Sdavidxu/* #include <unistd.h> */
837144518Sdavidxu#ifdef  _UNISTD_H_
838144518Sdavidxuint     __sys_close(int);
839144518Sdavidxuint	__sys_fork(void);
840144518Sdavidxupid_t	__sys_getpid(void);
841144518Sdavidxussize_t __sys_read(int, void *, size_t);
842144518Sdavidxussize_t __sys_write(int, const void *, size_t);
843144518Sdavidxuvoid	__sys_exit(int);
844112918Sjeff#endif
845112918Sjeff
846144518Sdavidxustatic inline int
847144518Sdavidxu_thr_isthreaded(void)
848144518Sdavidxu{
849144518Sdavidxu	return (__isthreaded != 0);
850144518Sdavidxu}
851112918Sjeff
852144518Sdavidxustatic inline int
853144518Sdavidxu_thr_is_inited(void)
854144518Sdavidxu{
855144518Sdavidxu	return (_thr_initial != NULL);
856144518Sdavidxu}
857112918Sjeff
858144518Sdavidxustatic inline void
859144518Sdavidxu_thr_check_init(void)
860144518Sdavidxu{
861144518Sdavidxu	if (_thr_initial == NULL)
862144518Sdavidxu		_libpthread_init(NULL);
863144518Sdavidxu}
864144518Sdavidxu
865216641Sdavidxustruct wake_addr *_thr_alloc_wake_addr(void);
866216641Sdavidxuvoid	_thr_release_wake_addr(struct wake_addr *);
867216641Sdavidxuint	_thr_sleep(struct pthread *, int, const struct timespec *);
868216641Sdavidxu
869216641Sdavidxuvoid _thr_wake_addr_init(void) __hidden;
870216641Sdavidxu
871216641Sdavidxustatic inline void
872216641Sdavidxu_thr_clear_wake(struct pthread *td)
873216641Sdavidxu{
874216641Sdavidxu	td->wake_addr->value = 0;
875216641Sdavidxu}
876216641Sdavidxu
877216641Sdavidxustatic inline int
878216641Sdavidxu_thr_is_woken(struct pthread *td)
879216641Sdavidxu{
880216641Sdavidxu	return td->wake_addr->value != 0;
881216641Sdavidxu}
882216641Sdavidxu
883216641Sdavidxustatic inline void
884216641Sdavidxu_thr_set_wake(unsigned int *waddr)
885216641Sdavidxu{
886216641Sdavidxu	*waddr = 1;
887216641Sdavidxu	_thr_umtx_wake(waddr, INT_MAX, 0);
888216641Sdavidxu}
889216641Sdavidxu
890216641Sdavidxuvoid _thr_wake_all(unsigned int *waddrs[], int) __hidden;
891216641Sdavidxu
892216641Sdavidxustatic inline struct pthread *
893216641Sdavidxu_sleepq_first(struct sleepqueue *sq)
894216641Sdavidxu{
895216641Sdavidxu	return TAILQ_FIRST(&sq->sq_blocked);
896216641Sdavidxu}
897216641Sdavidxu
898216641Sdavidxuvoid	_sleepq_init(void) __hidden;
899216641Sdavidxustruct sleepqueue *_sleepq_alloc(void) __hidden;
900216641Sdavidxuvoid	_sleepq_free(struct sleepqueue *) __hidden;
901216641Sdavidxuvoid	_sleepq_lock(void *) __hidden;
902216641Sdavidxuvoid	_sleepq_unlock(void *) __hidden;
903216641Sdavidxustruct sleepqueue *_sleepq_lookup(void *) __hidden;
904216641Sdavidxuvoid	_sleepq_add(void *, struct pthread *) __hidden;
905216641Sdavidxuint	_sleepq_remove(struct sleepqueue *, struct pthread *) __hidden;
906216641Sdavidxuvoid	_sleepq_drop(struct sleepqueue *,
907216641Sdavidxu		void (*cb)(struct pthread *, void *arg), void *) __hidden;
908216641Sdavidxu
909211706Skibstruct dl_phdr_info;
910211706Skibvoid __pthread_cxa_finalize(struct dl_phdr_info *phdr_info);
911211860Sdavidxuvoid _thr_tsd_unload(struct dl_phdr_info *phdr_info) __hidden;
912212076Sdavidxuvoid _thr_sigact_unload(struct dl_phdr_info *phdr_info) __hidden;
913217191Skibvoid _thr_stack_fix_protection(struct pthread *thrd);
914211706Skib
915112918Sjeff__END_DECLS
916112918Sjeff
917144518Sdavidxu#endif  /* !_THR_PRIVATE_H */
918