xref: /netbsd-src/lib/libpthread/pthread_int.h (revision 0920b4f20b78ab1ccd9f2312fbe10deaf000cbf3)
1 /*	$NetBSD: pthread_int.h,v 1.49 2007/08/16 13:54:16 ad Exp $	*/
2 
3 /*-
4  * Copyright (c) 2001, 2002, 2003, 2006, 2007 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Nathan J. Williams and Andrew Doran.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #ifndef _LIB_PTHREAD_INT_H
40 #define _LIB_PTHREAD_INT_H
41 
42 /* #define PTHREAD__DEBUG */
43 #define ERRORCHECK
44 
45 #include "pthread_types.h"
46 #include "pthread_queue.h"
47 #include "pthread_debug.h"
48 #include "pthread_md.h"
49 
50 #include <lwp.h>
51 #include <signal.h>
52 
53 #define PTHREAD_KEYS_MAX 256
54 /*
55  * The size of this structure needs to be no larger than struct
56  * __pthread_cleanup_store, defined in pthread.h.
57  */
58 struct pt_clean_t {
59 	PTQ_ENTRY(pt_clean_t)	ptc_next;
60 	void	(*ptc_cleanup)(void *);
61 	void	*ptc_arg;
62 };
63 
64 /* Private data for pthread_attr_t */
65 struct pthread_attr_private {
66 	char ptap_name[PTHREAD_MAX_NAMELEN_NP];
67 	void *ptap_namearg;
68 	void *ptap_stackaddr;
69 	size_t ptap_stacksize;
70 	size_t ptap_guardsize;
71 };
72 
73 struct	__pthread_st {
74 	unsigned int	pt_magic;	/* Magic number */
75 	int		pt_num;		/* ID XXX should die */
76 	int		pt_state;	/* running, blocked, etc. */
77 	pthread_spin_t	pt_lock;	/* lock on state */
78 	int		pt_flags;	/* see PT_FLAG_* below */
79 	int		pt_cancel;	/* Deferred cancellation */
80 	int		pt_spinlocks;	/* Number of spinlocks held. */
81 	void		*pt_mutexhint;	/* Last mutex held. */
82 	int		pt_errno;	/* Thread-specific errno. */
83 	stack_t		pt_stack;	/* Our stack */
84 	void		*pt_exitval;	/* Read by pthread_join() */
85 	char		*pt_name;	/* Thread's name, set by the app. */
86 	int		pt_willpark;	/* About to park */
87 	lwpid_t		pt_unpark;	/* Unpark this when parking */
88 	void		*pt_unparkhint;	/* Hint for the above */
89 
90 	/* Stack of cancellation cleanup handlers and their arguments */
91 	PTQ_HEAD(, pt_clean_t)	pt_cleanup_stack;
92 
93 	/* For debugger: LWPs waiting to join. */
94 	pthread_queue_t	pt_joiners;
95 	PTQ_ENTRY(__pthread_st) pt_joinq;
96 
97 	/* LWP ID and entry on the list of all threads. */
98 	lwpid_t		pt_lid;
99 	PTQ_ENTRY(__pthread_st)	pt_allq;
100 	PTQ_ENTRY(__pthread_st)	pt_deadq;
101 
102 	/*
103 	 * General synchronization data.  We try to align, as threads
104 	 * on other CPUs will access this data frequently.
105 	 */
106 	int		pt_dummy1 __aligned(128);
107 	int		pt_sleeponq;	/* on a sleep queue */
108 	int		pt_signalled;	/* Received pthread_cond_signal() */
109 	void		*pt_sleepobj;	/* object slept on */
110 	PTQ_ENTRY(__pthread_st)	pt_sleep;
111 	int		pt_dummy2 __aligned(128);
112 
113 	/* Thread-specific data.  Large so it sits close to the end. */
114 	int		pt_havespecific;
115 	void		*pt_specific[PTHREAD_KEYS_MAX];
116 
117 	/*
118 	 * Context for thread creation.  At the end as it's cached
119 	 * and then only ever passed to _lwp_create().
120 	 */
121 	ucontext_t	pt_uc;
122 };
123 
124 /* Thread states */
125 #define PT_STATE_RUNNING	1
126 #define PT_STATE_ZOMBIE		5
127 #define PT_STATE_DEAD		6
128 
129 /* Flag values */
130 
131 #define PT_FLAG_DETACHED	0x0001
132 #define PT_FLAG_CS_DISABLED	0x0004	/* Cancellation disabled */
133 #define PT_FLAG_CS_ASYNC	0x0008  /* Cancellation is async */
134 #define PT_FLAG_CS_PENDING	0x0010
135 #define PT_FLAG_SCOPE_SYSTEM	0x0040
136 #define PT_FLAG_EXPLICIT_SCHED	0x0080
137 #define PT_FLAG_SUSPENDED	0x0100	/* In the suspended queue */
138 
139 #define PT_MAGIC	0x11110001
140 #define PT_DEAD		0xDEAD0001
141 
142 #define PT_ATTR_MAGIC	0x22220002
143 #define PT_ATTR_DEAD	0xDEAD0002
144 
145 extern int	pthread__stacksize_lg;
146 extern size_t	pthread__stacksize;
147 extern vaddr_t	pthread__stackmask;
148 extern int	pthread__nspins;
149 extern int	pthread__concurrency;
150 extern int 	pthread__osrev;
151 
152 /* Flag to be used in a ucontext_t's uc_flags indicating that
153  * the saved register state is "user" state only, not full
154  * trap state.
155  */
156 #define _UC_USER_BIT		30
157 #define _UC_USER		(1LU << _UC_USER_BIT)
158 
159 void	pthread_init(void)  __attribute__ ((__constructor__));
160 
161 /* Utility functions */
162 void	pthread__unpark_all(pthread_t self, pthread_spin_t *lock,
163 			    pthread_queue_t *threadq);
164 void	pthread__unpark(pthread_t self, pthread_spin_t *lock,
165 			pthread_queue_t *queue, pthread_t target);
166 int	pthread__park(pthread_t self, pthread_spin_t *lock,
167 		      pthread_queue_t *threadq,
168 		      const struct timespec *abs_timeout,
169 		      int cancelpt, const void *hint);
170 
171 /* Internal locking primitives */
172 void	pthread__lockprim_init(void);
173 void	pthread_lockinit(pthread_spin_t *);
174 void	pthread_spinlock(pthread_spin_t *);
175 int	pthread_spintrylock(pthread_spin_t *);
176 void	pthread_spinunlock(pthread_spin_t *);
177 
178 extern const struct pthread_lock_ops *pthread__lock_ops;
179 
180 void	pthread__simple_lock_init(__cpu_simple_lock_t *);
181 int	pthread__simple_lock_try(__cpu_simple_lock_t *);
182 void	pthread__simple_unlock(__cpu_simple_lock_t *);
183 
184 #ifndef _getcontext_u
185 int	_getcontext_u(ucontext_t *);
186 #endif
187 #ifndef _setcontext_u
188 int	_setcontext_u(const ucontext_t *);
189 #endif
190 #ifndef _swapcontext_u
191 int	_swapcontext_u(ucontext_t *, const ucontext_t *);
192 #endif
193 
194 void	pthread__testcancel(pthread_t);
195 int	pthread__find(pthread_t);
196 
197 #ifndef PTHREAD_MD_INIT
198 #define PTHREAD_MD_INIT
199 #endif
200 
201 #ifndef _INITCONTEXT_U_MD
202 #define _INITCONTEXT_U_MD(ucp)
203 #endif
204 
205 #define _INITCONTEXT_U(ucp) do {					\
206 	(ucp)->uc_flags = _UC_CPU | _UC_STACK;				\
207 	_INITCONTEXT_U_MD(ucp)						\
208 	} while (/*CONSTCOND*/0)
209 
210 #ifdef PTHREAD_MACHINE_HAS_ID_REGISTER
211 #define pthread__id(reg) (reg)
212 #else
213 /* Stack location of pointer to a particular thread */
214 #define pthread__id(sp) \
215 	((pthread_t) (((vaddr_t)(sp)) & ~pthread__stackmask))
216 
217 #define pthread__id_reg() pthread__sp()
218 #endif
219 
220 #define pthread__self() (pthread__id(pthread__id_reg()))
221 
222 #define pthread__abort()						\
223 	pthread__assertfunc(__FILE__, __LINE__, __func__, "unreachable")
224 
225 #define pthread__assert(e) do {						\
226 	if (__predict_false(!(e)))					\
227        	       pthread__assertfunc(__FILE__, __LINE__, __func__, #e);	\
228         } while (/*CONSTCOND*/0)
229 
230 #define pthread__error(err, msg, e) do {				\
231 	if (__predict_false(!(e))) {					\
232        	       pthread__errorfunc(__FILE__, __LINE__, __func__, msg);	\
233 	       return (err);						\
234 	} 								\
235         } while (/*CONSTCOND*/0)
236 
237 void	pthread__destroy_tsd(pthread_t self);
238 void	pthread__assertfunc(const char *file, int line, const char *function,
239 		const char *expr);
240 void	pthread__errorfunc(const char *file, int line, const char *function,
241 		const char *msg);
242 
243 #if defined(i386) || defined(__x86_64__)
244 #define	pthread__smt_pause()	__asm __volatile("rep; nop" ::: "memory")
245 #define	PTHREAD__CHEAP_UNLOCK
246 #else
247 #define	pthread__smt_pause()	/* nothing */
248 #endif
249 
250 #endif /* _LIB_PTHREAD_INT_H */
251