1 /*
2  * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by John Birrell.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * Private thread definitions for the uthread kernel.
33  *
34  * $FreeBSD: src/lib/libpthread/thread/thr_private.h,v 1.120 2004/11/01 10:49:34 davidxu Exp $
35  * $DragonFly: src/lib/libthread_xu/thread/thr_private.h,v 1.7 2005/06/21 07:47:01 davidxu Exp $
36  */
37 
38 #ifndef _THR_PRIVATE_H
39 #define _THR_PRIVATE_H
40 
41 /*
42  * Include files.
43  */
44 #include <sys/types.h>
45 #include <sys/time.h>
46 #include <sys/cdefs.h>
47 #include <sys/queue.h>
48 #include <machine/atomic.h>
49 #include <errno.h>
50 #include <limits.h>
51 #include <signal.h>
52 #include <stdio.h>
53 #include <sched.h>
54 #include <unistd.h>
55 #include <pthread.h>
56 #include <pthread_np.h>
57 
58 #include "pthread_md.h"
59 #include "thr_umtx.h"
60 #include "thread_db.h"
61 
62 /*
63  * Evaluate the storage class specifier.
64  */
65 #ifdef GLOBAL_PTHREAD_PRIVATE
66 #define SCLASS
67 #define SCLASS_PRESET(x...)	= x
68 #else
69 #define SCLASS			extern
70 #define SCLASS_PRESET(x...)
71 #endif
72 
73 /* Signal to do cancellation */
74 #define	SIGCANCEL		32
75 
76 /*
77  * Kernel fatal error handler macro.
78  */
79 #define PANIC(string)		_thread_exit(__FILE__,__LINE__,string)
80 
81 /* Output debug messages like this: */
82 #define stdout_debug(args...)	_thread_printf(STDOUT_FILENO, ##args)
83 #define stderr_debug(args...)	_thread_printf(STDOUT_FILENO, ##args)
84 
85 #ifdef __DragonFly__
86 #define __predict_true(exp)	(exp)
87 #define	__predict_false(exp)	(exp)
88 #endif
89 
90 #ifdef _PTHREADS_INVARIANTS
91 #define THR_ASSERT(cond, msg) do {	\
92 	if (__predict_false(!(cond)))	\
93 		PANIC(msg);		\
94 } while (0)
95 #else
96 #define THR_ASSERT(cond, msg)
97 #endif
98 
99 #define	TIMESPEC_ADD(dst, src, val)				\
100 	do { 							\
101 		(dst)->tv_sec = (src)->tv_sec + (val)->tv_sec;	\
102 		(dst)->tv_nsec = (src)->tv_nsec + (val)->tv_nsec; \
103 		if ((dst)->tv_nsec >= 1000000000) {		\
104 			(dst)->tv_sec++;			\
105 			(dst)->tv_nsec -= 1000000000;		\
106 		}						\
107 	} while (0)
108 
109 #define	TIMESPEC_SUB(dst, src, val)				\
110 	do { 							\
111 		(dst)->tv_sec = (src)->tv_sec - (val)->tv_sec;	\
112 		(dst)->tv_nsec = (src)->tv_nsec - (val)->tv_nsec; \
113 		if ((dst)->tv_nsec < 0) {			\
114 			(dst)->tv_sec--;			\
115 			(dst)->tv_nsec += 1000000000;		\
116 		}						\
117 	} while (0)
118 
119 struct pthread_mutex {
120 	/*
121 	 * Lock for accesses to this structure.
122 	 */
123 	volatile umtx_t			m_lock;
124 	enum pthread_mutextype		m_type;
125 	int				m_protocol;
126 	TAILQ_HEAD(mutex_head, pthread)	m_queue;
127 	struct pthread			*m_owner;
128 	long				m_flags;
129 	int				m_count;
130 	int				m_refcount;
131 
132 	/*
133 	 * Used for priority inheritence and protection.
134 	 *
135 	 *   m_prio       - For priority inheritence, the highest active
136 	 *                  priority (threads locking the mutex inherit
137 	 *                  this priority).  For priority protection, the
138 	 *                  ceiling priority of this mutex.
139 	 *   m_saved_prio - mutex owners inherited priority before
140 	 *                  taking the mutex, restored when the owner
141 	 *                  unlocks the mutex.
142 	 */
143 	int				m_prio;
144 	int				m_saved_prio;
145 
146 	/*
147 	 * Link for list of all mutexes a thread currently owns.
148 	 */
149 	TAILQ_ENTRY(pthread_mutex)	m_qe;
150 };
151 
152 #define TAILQ_INITIALIZER	{ NULL, NULL }
153 
154 #define PTHREAD_MUTEX_STATIC_INITIALIZER   \
155 	{0, PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, TAILQ_INITIALIZER, \
156 	NULL, { NULL }, MUTEX_FLAGS_PRIVATE, 0, 0, 0, TAILQ_INITIALIZER }
157 /*
158  * Flags for mutexes.
159  */
160 #define MUTEX_FLAGS_PRIVATE	0x01
161 #define MUTEX_FLAGS_INITED	0x02
162 #define MUTEX_FLAGS_BUSY	0x04
163 
164 struct pthread_mutex_attr {
165 	enum pthread_mutextype	m_type;
166 	int			m_protocol;
167 	int			m_ceiling;
168 	long			m_flags;
169 };
170 
171 #define PTHREAD_MUTEXATTR_STATIC_INITIALIZER \
172 	{ PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, 0, MUTEX_FLAGS_PRIVATE }
173 
174 struct pthread_cond {
175 	/*
176 	 * Lock for accesses to this structure.
177 	 */
178 	volatile umtx_t	c_lock;
179 	volatile umtx_t	c_seqno;
180 	volatile int	c_waiters;
181 	volatile int	c_wakeups;
182 	int		c_pshared;
183 	int		c_clockid;
184 };
185 
186 struct pthread_cond_attr {
187 	int		c_pshared;
188 	int		c_clockid;
189 };
190 
191 struct pthread_barrier {
192 	volatile umtx_t	b_lock;
193 	volatile umtx_t	b_cycle;
194 	volatile int	b_count;
195 	volatile int	b_waiters;
196 };
197 
198 struct pthread_barrierattr {
199 	int		pshared;
200 };
201 
202 struct pthread_spinlock {
203 	volatile umtx_t	s_lock;
204 };
205 
206 /*
207  * Flags for condition variables.
208  */
209 #define COND_FLAGS_PRIVATE	0x01
210 #define COND_FLAGS_INITED	0x02
211 #define COND_FLAGS_BUSY		0x04
212 
213 /*
214  * Cleanup definitions.
215  */
216 struct pthread_cleanup {
217 	struct pthread_cleanup	*next;
218 	void			(*routine)();
219 	void			*routine_arg;
220 	int			onstack;
221 };
222 
223 #define	THR_CLEANUP_PUSH(td, func, arg) {		\
224 	struct pthread_cleanup __cup;			\
225 							\
226 	__cup.routine = func;				\
227 	__cup.routine_arg = arg;			\
228 	__cup.onstack = 1;				\
229 	__cup.next = (td)->cleanup;			\
230 	(td)->cleanup = &__cup;
231 
232 #define	THR_CLEANUP_POP(td, exec)			\
233 	(td)->cleanup = __cup.next;			\
234 	if ((exec) != 0)				\
235 		__cup.routine(__cup.routine_arg);	\
236 }
237 
238 struct pthread_atfork {
239 	TAILQ_ENTRY(pthread_atfork) qe;
240 	void (*prepare)(void);
241 	void (*parent)(void);
242 	void (*child)(void);
243 };
244 
245 struct pthread_attr {
246 	int	sched_policy;
247 	int	sched_inherit;
248 	int	sched_interval;
249 	int	prio;
250 	int	suspend;
251 #define	THR_STACK_USER		0x100	/* 0xFF reserved for <pthread.h> */
252 	int	flags;
253 	void	*arg_attr;
254 	void	(*cleanup_attr)();
255 	void	*stackaddr_attr;
256 	size_t	stacksize_attr;
257 	size_t	guardsize_attr;
258 };
259 
260 /*
261  * Thread creation state attributes.
262  */
263 #define THR_CREATE_RUNNING		0
264 #define THR_CREATE_SUSPENDED		1
265 
266 /*
267  * Miscellaneous definitions.
268  */
269 #define THR_STACK_DEFAULT		(sizeof(void *) / 4 * 1024 * 1024)
270 
271 /*
272  * Maximum size of initial thread's stack.  This perhaps deserves to be larger
273  * than the stacks of other threads, since many applications are likely to run
274  * almost entirely on this stack.
275  */
276 #define THR_STACK_INITIAL		(THR_STACK_DEFAULT * 2)
277 
278 /*
279  * Define the different priority ranges.  All applications have thread
280  * priorities constrained within 0-31.  The threads library raises the
281  * priority when delivering signals in order to ensure that signal
282  * delivery happens (from the POSIX spec) "as soon as possible".
283  * In the future, the threads library will also be able to map specific
284  * threads into real-time (cooperating) processes or kernel threads.
285  * The RT and SIGNAL priorities will be used internally and added to
286  * thread base priorities so that the scheduling queue can handle both
287  * normal and RT priority threads with and without signal handling.
288  *
289  * The approach taken is that, within each class, signal delivery
290  * always has priority over thread execution.
291  */
292 #define THR_DEFAULT_PRIORITY			15
293 #define THR_MIN_PRIORITY			0
294 #define THR_MAX_PRIORITY			31	/* 0x1F */
295 #define THR_SIGNAL_PRIORITY			32	/* 0x20 */
296 #define THR_RT_PRIORITY				64	/* 0x40 */
297 #define THR_FIRST_PRIORITY			THR_MIN_PRIORITY
298 #define THR_LAST_PRIORITY	\
299 	(THR_MAX_PRIORITY + THR_SIGNAL_PRIORITY + THR_RT_PRIORITY)
300 #define THR_BASE_PRIORITY(prio)	((prio) & THR_MAX_PRIORITY)
301 
302 /*
303  * Time slice period in microseconds.
304  */
305 #define TIMESLICE_USEC				20000
306 
307 struct pthread_rwlockattr {
308 	int		pshared;
309 };
310 
311 struct pthread_rwlock {
312 	pthread_mutex_t	lock;	/* monitor lock */
313 	pthread_cond_t	read_signal;
314 	pthread_cond_t	write_signal;
315 	int		state;	/* 0 = idle  >0 = # of readers  -1 = writer */
316 	int		blocked_writers;
317 };
318 
319 /*
320  * Thread states.
321  */
322 enum pthread_state {
323 	PS_RUNNING,
324 	PS_DEAD
325 };
326 
327 union pthread_wait_data {
328 	pthread_mutex_t	mutex;
329 };
330 
331 struct pthread_specific_elem {
332 	const void	*data;
333 	int		seqno;
334 };
335 
336 struct pthread_key {
337 	volatile int	allocated;
338 	volatile int	count;
339 	int		seqno;
340 	void            (*destructor)(void *);
341 };
342 
343 /*
344  * Thread structure.
345  */
346 struct pthread {
347 	/*
348 	 * Magic value to help recognize a valid thread structure
349 	 * from an invalid one:
350 	 */
351 #define	THR_MAGIC		((u_int32_t) 0xd09ba115)
352 	u_int32_t		magic;
353 	char			*name;
354 	u_int64_t		uniqueid; /* for gdb */
355 
356 	/*
357 	 * Lock for accesses to this thread structure.
358 	 */
359 	umtx_t			lock;
360 
361 	/* Thread is terminated in kernel, written by kernel. */
362 	long			terminated;
363 
364 	/* Kernel thread id. */
365 	long			tid;
366 
367 	/* Internal condition variable cycle number. */
368 	umtx_t			cycle;
369 
370 	/* How many low level locks the thread held. */
371 	int			locklevel;
372 
373 	/* Signal blocked counter. */
374 	int			sigblock;
375 
376 	/* Queue entry for list of all threads. */
377 	TAILQ_ENTRY(pthread)	tle;	/* link for all threads in process */
378 
379 	/* Queue entry for GC lists. */
380 	TAILQ_ENTRY(pthread)	gcle;
381 
382 	/* Hash queue entry. */
383 	LIST_ENTRY(pthread)	hle;
384 
385 	/* Threads reference count. */
386 	int			refcount;
387 
388 	/*
389 	 * Thread start routine, argument, stack pointer and thread
390 	 * attributes.
391 	 */
392 	void			*(*start_routine)(void *);
393 	void			*arg;
394 	struct pthread_attr	attr;
395 
396  	/*
397 	 * Cancelability flags
398 	 */
399 #define	THR_CANCEL_DISABLE		0x0001
400 #define	THR_CANCEL_EXITING		0x0002
401 #define THR_CANCEL_AT_POINT		0x0004
402 #define THR_CANCEL_NEEDED		0x0008
403 #define	SHOULD_CANCEL(val)					\
404 	(((val) & (THR_CANCEL_DISABLE | THR_CANCEL_EXITING |	\
405 		 THR_CANCEL_NEEDED)) == THR_CANCEL_NEEDED)
406 
407 #define	SHOULD_ASYNC_CANCEL(val)				\
408 	(((val) & (THR_CANCEL_DISABLE | THR_CANCEL_EXITING |	\
409 		 THR_CANCEL_NEEDED | THR_CANCEL_AT_POINT)) ==	\
410 		 (THR_CANCEL_NEEDED | THR_CANCEL_AT_POINT))
411 	int			cancelflags;
412 
413 	/* Thread temporary signal mask. */
414 	sigset_t		sigmask;
415 
416 	/* Thread state: */
417 	umtx_t			state;
418 
419 	/*
420 	 * Error variable used instead of errno, used for internal.
421 	 */
422 	int			error;
423 
424 	/*
425 	 * The joiner is the thread that is joining to this thread.  The
426 	 * join status keeps track of a join operation to another thread.
427 	 */
428 	struct pthread		*joiner;
429 
430 	/*
431 	 * The current thread can belong to a priority mutex queue.
432 	 * This is the synchronization queue link.
433 	 */
434 	TAILQ_ENTRY(pthread)	sqe;
435 
436 	/* Wait data. */
437 	union pthread_wait_data data;
438 
439 	int			sflags;
440 #define THR_FLAGS_IN_SYNCQ	0x0001
441 
442 	/* Miscellaneous flags; only set with scheduling lock held. */
443 	int			flags;
444 #define THR_FLAGS_PRIVATE	0x0001
445 #define	THR_FLAGS_NEED_SUSPEND	0x0002	/* thread should be suspended */
446 #define	THR_FLAGS_SUSPENDED	0x0004	/* thread is suspended */
447 
448 	/* Thread list flags; only set with thread list lock held. */
449 	int			tlflags;
450 #define	TLFLAGS_GC_SAFE		0x0001	/* thread safe for cleaning */
451 #define	TLFLAGS_IN_TDLIST	0x0002	/* thread in all thread list */
452 #define	TLFLAGS_IN_GCLIST	0x0004	/* thread in gc list */
453 #define	TLFLAGS_DETACHED	0x0008	/* thread is detached */
454 
455 	/*
456 	 * Base priority is the user setable and retrievable priority
457 	 * of the thread.  It is only affected by explicit calls to
458 	 * set thread priority and upon thread creation via a thread
459 	 * attribute or default priority.
460 	 */
461 	char			base_priority;
462 
463 	/*
464 	 * Inherited priority is the priority a thread inherits by
465 	 * taking a priority inheritence or protection mutex.  It
466 	 * is not affected by base priority changes.  Inherited
467 	 * priority defaults to and remains 0 until a mutex is taken
468 	 * that is being waited on by any other thread whose priority
469 	 * is non-zero.
470 	 */
471 	char			inherited_priority;
472 
473 	/*
474 	 * Active priority is always the maximum of the threads base
475 	 * priority and inherited priority.  When there is a change
476 	 * in either the base or inherited priority, the active
477 	 * priority must be recalculated.
478 	 */
479 	char			active_priority;
480 
481 	/* Number of priority ceiling or protection mutexes owned. */
482 	int			priority_mutex_count;
483 
484 	/* Queue of currently owned simple type mutexes. */
485 	TAILQ_HEAD(, pthread_mutex)	mutexq;
486 
487 	/* Queue of currently owned priority type mutexs. */
488 	TAILQ_HEAD(, pthread_mutex)	pri_mutexq;
489 
490 	void				*ret;
491 	struct pthread_specific_elem	*specific;
492 	int				specific_data_count;
493 
494 	/* Number rwlocks rdlocks held. */
495 	int			rdlock_count;
496 
497 	/*
498 	 * Current locks bitmap for rtld. */
499 	int			rtld_bits;
500 
501 	/* Thread control block */
502 	struct tls_tcb		*tcb;
503 
504 	/* Cleanup handlers Link List */
505 	struct pthread_cleanup *cleanup;
506 
507 	/* Enable event reporting */
508 	int			report_events;
509 
510 	/* Event mask */
511 	td_thr_events_t		event_mask;
512 
513 	/* Event */
514 	td_event_msg_t		event_buf;
515 };
516 
517 #define THR_UMTX_TRYLOCK(thrd, lck)			\
518 	_thr_umtx_trylock((lck), (thrd)->tid)
519 
520 #define	THR_UMTX_LOCK(thrd, lck)			\
521 	_thr_umtx_lock((lck), (thrd)->tid)
522 
523 #define	THR_UMTX_TIMEDLOCK(thrd, lck, timo)		\
524 	_thr_umtx_timedlock((lck), (thrd)->tid, (timo))
525 
526 #define	THR_UMTX_UNLOCK(thrd, lck)			\
527 	_thr_umtx_unlock((lck), (thrd)->tid)
528 
529 #define	THR_LOCK_ACQUIRE(thrd, lck)			\
530 do {							\
531 	(thrd)->locklevel++;				\
532 	_thr_umtx_lock(lck, (thrd)->tid);		\
533 } while (0)
534 
535 #define	THR_LOCK_RELEASE(thrd, lck)			\
536 do {							\
537 	if ((thrd)->locklevel > 0) {			\
538 		_thr_umtx_unlock((lck), (thrd)->tid);	\
539 		(thrd)->locklevel--;			\
540 	} else { 					\
541 		_thr_assert_lock_level();		\
542 	}						\
543 } while (0)
544 
545 #define	THR_LOCK(curthrd)		THR_LOCK_ACQUIRE(curthrd, &(curthrd)->lock)
546 #define	THR_UNLOCK(curthrd)		THR_LOCK_RELEASE(curthrd, &(curthrd)->lock)
547 #define	THR_THREAD_LOCK(curthrd, thr)	THR_LOCK_ACQUIRE(curthrd, &(thr)->lock)
548 #define	THR_THREAD_UNLOCK(curthrd, thr)	THR_LOCK_RELEASE(curthrd, &(thr)->lock)
549 
550 #define	THREAD_LIST_LOCK(curthrd)				\
551 do {								\
552 	THR_LOCK_ACQUIRE((curthrd), &_thr_list_lock);		\
553 } while (0)
554 
555 #define	THREAD_LIST_UNLOCK(curthrd)				\
556 do {								\
557 	THR_LOCK_RELEASE((curthrd), &_thr_list_lock);		\
558 } while (0)
559 
560 /*
561  * Macros to insert/remove threads to the all thread list and
562  * the gc list.
563  */
564 #define	THR_LIST_ADD(thrd) do {					\
565 	if (((thrd)->tlflags & TLFLAGS_IN_TDLIST) == 0) {	\
566 		TAILQ_INSERT_HEAD(&_thread_list, thrd, tle);	\
567 		_thr_hash_add(thrd);				\
568 		(thrd)->tlflags |= TLFLAGS_IN_TDLIST;		\
569 	}							\
570 } while (0)
571 #define	THR_LIST_REMOVE(thrd) do {				\
572 	if (((thrd)->tlflags & TLFLAGS_IN_TDLIST) != 0) {	\
573 		TAILQ_REMOVE(&_thread_list, thrd, tle);		\
574 		_thr_hash_remove(thrd);				\
575 		(thrd)->tlflags &= ~TLFLAGS_IN_TDLIST;		\
576 	}							\
577 } while (0)
578 #define	THR_GCLIST_ADD(thrd) do {				\
579 	if (((thrd)->tlflags & TLFLAGS_IN_GCLIST) == 0) {	\
580 		TAILQ_INSERT_HEAD(&_thread_gc_list, thrd, gcle);\
581 		(thrd)->tlflags |= TLFLAGS_IN_GCLIST;		\
582 		_gc_count++;					\
583 	}							\
584 } while (0)
585 #define	THR_GCLIST_REMOVE(thrd) do {				\
586 	if (((thrd)->tlflags & TLFLAGS_IN_GCLIST) != 0) {	\
587 		TAILQ_REMOVE(&_thread_gc_list, thrd, gcle);	\
588 		(thrd)->tlflags &= ~TLFLAGS_IN_GCLIST;		\
589 		_gc_count--;					\
590 	}							\
591 } while (0)
592 
593 #define GC_NEEDED()	(_gc_count >= 5)
594 
595 #define	THR_IN_SYNCQ(thrd)	(((thrd)->sflags & THR_FLAGS_IN_SYNCQ) != 0)
596 
597 #define SHOULD_REPORT_EVENT(curthr, e)			\
598 	(curthr->report_events && 			\
599 	 (((curthr)->event_mask | _thread_event_mask ) & e) != 0)
600 
601 extern int __isthreaded;
602 
603 /*
604  * Global variables for the pthread kernel.
605  */
606 
607 SCLASS void		*_usrstack	SCLASS_PRESET(NULL);
608 SCLASS struct pthread	*_thr_initial	SCLASS_PRESET(NULL);
609 SCLASS int		_thread_scope_system	SCLASS_PRESET(0);
610 
611 /* For debugger */
612 SCLASS int		_libthread_xu_debug	SCLASS_PRESET(0);
613 SCLASS int		_thread_event_mask	SCLASS_PRESET(0);
614 SCLASS struct pthread	*_thread_last_event;
615 
616 /* List of all threads: */
617 SCLASS TAILQ_HEAD(, pthread)	_thread_list
618     SCLASS_PRESET(TAILQ_HEAD_INITIALIZER(_thread_list));
619 
620 /* List of threads needing GC: */
621 SCLASS TAILQ_HEAD(, pthread)	_thread_gc_list
622     SCLASS_PRESET(TAILQ_HEAD_INITIALIZER(_thread_gc_list));
623 
624 SCLASS int	_thread_active_threads  SCLASS_PRESET(1);
625 
626 SCLASS TAILQ_HEAD(atfork_head, pthread_atfork) _thr_atfork_list;
627 SCLASS umtx_t	_thr_atfork_lock;
628 
629 /* Default thread attributes: */
630 SCLASS struct pthread_attr _pthread_attr_default
631     SCLASS_PRESET({
632 	.sched_policy = SCHED_RR,
633 	.sched_inherit = 0,
634 	.sched_interval = TIMESLICE_USEC,
635 	.prio = THR_DEFAULT_PRIORITY,
636 	.suspend = THR_CREATE_RUNNING,
637 	.flags = 0,
638 	.arg_attr = NULL,
639 	.cleanup_attr = NULL,
640 	.stackaddr_attr = NULL,
641 	.stacksize_attr = THR_STACK_DEFAULT,
642 	.guardsize_attr = 0
643     });
644 
645 /* Default mutex attributes: */
646 SCLASS struct pthread_mutex_attr _pthread_mutexattr_default
647     SCLASS_PRESET({
648 	.m_type = PTHREAD_MUTEX_DEFAULT,
649 	.m_protocol = PTHREAD_PRIO_NONE,
650 	.m_ceiling = 0,
651 	.m_flags = 0
652     });
653 
654 /* Default condition variable attributes: */
655 SCLASS struct pthread_cond_attr _pthread_condattr_default
656     SCLASS_PRESET({
657 	.c_pshared = PTHREAD_PROCESS_PRIVATE,
658 	.c_clockid = CLOCK_REALTIME
659     });
660 
661 SCLASS pid_t		_thr_pid		SCLASS_PRESET(0);
662 SCLASS int		_thr_guard_default;
663 SCLASS int		_thr_stack_default	SCLASS_PRESET(THR_STACK_DEFAULT);
664 SCLASS int		_thr_stack_initial	SCLASS_PRESET(THR_STACK_INITIAL);
665 SCLASS int		_thr_page_size;
666 /* Garbage thread count. */
667 SCLASS int              _gc_count               SCLASS_PRESET(0);
668 
669 SCLASS umtx_t		_mutex_static_lock;
670 SCLASS umtx_t		_cond_static_lock;
671 SCLASS umtx_t		_rwlock_static_lock;
672 SCLASS umtx_t		_keytable_lock;
673 SCLASS umtx_t		_thr_list_lock;
674 SCLASS umtx_t		_thr_event_lock;
675 
676 /* Undefine the storage class and preset specifiers: */
677 #undef  SCLASS
678 #undef	SCLASS_PRESET
679 
680 /*
681  * Function prototype definitions.
682  */
683 __BEGIN_DECLS
684 int	_thr_setthreaded(int);
685 int	_mutex_cv_lock(pthread_mutex_t *);
686 int	_mutex_cv_unlock(pthread_mutex_t *);
687 void	_mutex_notify_priochange(struct pthread *, struct pthread *, int);
688 int	_mutex_reinit(pthread_mutex_t *);
689 void	_mutex_fork(struct pthread *curthread);
690 void	_mutex_unlock_private(struct pthread *);
691 void	_libpthread_init(struct pthread *);
692 void	*_pthread_getspecific(pthread_key_t);
693 int	_pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
694 int	_pthread_cond_destroy(pthread_cond_t *);
695 int	_pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
696 int	_pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *,
697 	    const struct timespec *);
698 int	_pthread_cond_signal(pthread_cond_t *);
699 int	_pthread_cond_broadcast(pthread_cond_t *);
700 int	_pthread_key_create(pthread_key_t *, void (*) (void *));
701 int	_pthread_key_delete(pthread_key_t);
702 int	_pthread_mutex_destroy(pthread_mutex_t *);
703 int	_pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
704 int	_pthread_mutex_lock(pthread_mutex_t *);
705 int	_pthread_mutex_trylock(pthread_mutex_t *);
706 int	_pthread_mutex_unlock(pthread_mutex_t *);
707 int	_pthread_mutexattr_init(pthread_mutexattr_t *);
708 int	_pthread_mutexattr_destroy(pthread_mutexattr_t *);
709 int	_pthread_mutexattr_settype(pthread_mutexattr_t *, int);
710 int	_pthread_once(pthread_once_t *, void (*) (void));
711 int	_pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *);
712 int	_pthread_rwlock_destroy (pthread_rwlock_t *);
713 struct pthread *_pthread_self(void);
714 int	_pthread_setspecific(pthread_key_t, const void *);
715 void	_pthread_testcancel(void);
716 void	_pthread_yield(void);
717 void	_pthread_cleanup_push(void (*routine) (void *), void *routine_arg);
718 void	_pthread_cleanup_pop(int execute);
719 struct pthread *_thr_alloc(struct pthread *);
720 void	_thread_exit(char *, int, char *) __dead2;
721 void	_thr_exit_cleanup(void);
722 int	_thr_ref_add(struct pthread *, struct pthread *, int);
723 void	_thr_ref_delete(struct pthread *, struct pthread *);
724 int	_thr_find_thread(struct pthread *, struct pthread *, int);
725 void	_thr_rtld_init(void);
726 void	_thr_rtld_fini(void);
727 int	_thr_stack_alloc(struct pthread_attr *);
728 void	_thr_stack_free(struct pthread_attr *);
729 void	_thr_free(struct pthread *, struct pthread *);
730 void	_thr_gc(struct pthread *);
731 void    _thread_cleanupspecific(void);
732 void    _thread_dump_info(void);
733 void	_thread_printf(int, const char *, ...);
734 void	_thr_spinlock_init(void);
735 int	_thr_cancel_enter(struct pthread *);
736 void	_thr_cancel_leave(struct pthread *, int);
737 void	_thr_signal_block(struct pthread *);
738 void	_thr_signal_unblock(struct pthread *);
739 void	_thr_signal_init(void);
740 void	_thr_signal_deinit(void);
741 int	_thr_send_sig(struct pthread *, int sig);
742 void	_thr_list_init();
743 void	_thr_hash_add(struct pthread *);
744 void	_thr_hash_remove(struct pthread *);
745 struct pthread *_thr_hash_find(struct pthread *);
746 void	_thr_link(struct pthread *curthread, struct pthread *thread);
747 void	_thr_unlink(struct pthread *curthread, struct pthread *thread);
748 void	_thr_suspend_check(struct pthread *curthread);
749 void	_thr_assert_lock_level() __dead2;
750 int	_thr_get_tid(void);
751 void	_thr_report_creation(struct pthread *curthread,
752 			   struct pthread *newthread);
753 void	_thr_report_death(struct pthread *curthread);
754 void	_thread_bp_create(void);
755 void	_thread_bp_death(void);
756 
757 /* #include <sys/aio.h> */
758 #ifdef _SYS_AIO_H_
759 int	__sys_aio_suspend(const struct aiocb * const[], int, const struct timespec *);
760 #endif
761 
762 /* #include <fcntl.h> */
763 #ifdef  _SYS_FCNTL_H_
764 int     __sys_fcntl(int, int, ...);
765 int     __sys_open(const char *, int, ...);
766 #endif
767 
768 /* #include <sys/ioctl.h> */
769 #ifdef _SYS_IOCTL_H_
770 int	__sys_ioctl(int, unsigned long, ...);
771 #endif
772 
773 /* #inclde <sched.h> */
774 #ifdef	_SCHED_H_
775 int	__sys_sched_yield(void);
776 #endif
777 
778 /* #include <signal.h> */
779 #ifdef _SIGNAL_H_
780 int	__sys_kill(pid_t, int);
781 int     __sys_sigaction(int, const struct sigaction *, struct sigaction *);
782 int     __sys_sigpending(sigset_t *);
783 int     __sys_sigprocmask(int, const sigset_t *, sigset_t *);
784 int     __sys_sigsuspend(const sigset_t *);
785 int     __sys_sigreturn(ucontext_t *);
786 int     __sys_sigaltstack(const struct sigaltstack *, struct sigaltstack *);
787 #endif
788 
789 /* #include <sys/socket.h> */
790 #ifdef _SYS_SOCKET_H_
791 int	__sys_accept(int, struct sockaddr *, socklen_t *);
792 int	__sys_connect(int, const struct sockaddr *, socklen_t);
793 ssize_t __sys_recv(int, void *, size_t, int);
794 ssize_t __sys_recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *);
795 ssize_t __sys_recvmsg(int, struct msghdr *, int);
796 int	__sys_sendfile(int, int, off_t, size_t, struct sf_hdtr *,
797 	    off_t *, int);
798 ssize_t __sys_sendmsg(int, const struct msghdr *, int);
799 ssize_t __sys_sendto(int, const void *,size_t, int, const struct sockaddr *, socklen_t);
800 #endif
801 
802 /* #include <sys/uio.h> */
803 #ifdef  _SYS_UIO_H_
804 ssize_t __sys_readv(int, const struct iovec *, int);
805 ssize_t __sys_writev(int, const struct iovec *, int);
806 #endif
807 
808 /* #include <time.h> */
809 #ifdef	_TIME_H_
810 int	__sys_nanosleep(const struct timespec *, struct timespec *);
811 #endif
812 
813 /* #include <unistd.h> */
814 #ifdef  _UNISTD_H_
815 int     __sys_close(int);
816 int     __sys_execve(const char *, char * const *, char * const *);
817 int	__sys_fork(void);
818 int	__sys_fsync(int);
819 pid_t	__sys_getpid(void);
820 int     __sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
821 ssize_t __sys_read(int, void *, size_t);
822 ssize_t __sys_write(int, const void *, size_t);
823 void	__sys_exit(int);
824 int	__sys_sigwait(const sigset_t *, int *);
825 int	__sys_sigtimedwait(const sigset_t *, siginfo_t *,
826 		const struct timespec *);
827 int	__sys_sigwaitinfo(const sigset_t *set, siginfo_t *info);
828 #endif
829 
830 /* #include <poll.h> */
831 #ifdef _SYS_POLL_H_
832 int 	__sys_poll(struct pollfd *, unsigned, int);
833 #endif
834 
835 /* #include <sys/mman.h> */
836 #ifdef _SYS_MMAN_H_
837 int	__sys_msync(void *, size_t, int);
838 #endif
839 
840 static inline int
841 _thr_isthreaded(void)
842 {
843 	return (__isthreaded != 0);
844 }
845 
846 static inline int
847 _thr_is_inited(void)
848 {
849 	return (_thr_initial != 0);
850 }
851 
852 static inline void
853 _thr_check_init(void)
854 {
855 	if (_thr_initial == 0)
856 		_libpthread_init(0);
857 }
858 
859 __END_DECLS
860 
861 #endif  /* !_THR_PRIVATE_H */
862