xref: /openbsd-src/lib/librthread/rthread.h (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: rthread.h,v 1.60 2016/09/04 10:13:35 akfaew Exp $ */
2 /*
3  * Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 /*
19  * Private data structures that back up the typedefs in pthread.h.
20  * Since only the thread library cares about their size or arrangement,
21  * it should be possible to switch libraries without relinking.
22  *
23  * Do not reorder _atomic_lock_t and sem_t variables in the structs.
24  * This is due to alignment requirements of certain arches like hppa.
25  * The current requirement is 16 bytes.
26  *
27  * THE MACHINE DEPENDENT CERROR CODE HAS HARD CODED OFFSETS INTO PTHREAD_T!
28  */
29 
30 #include <sys/queue.h>
31 #include <semaphore.h>
32 #include <machine/spinlock.h>
33 
34 #ifdef __LP64__
35 #define RTHREAD_STACK_SIZE_DEF (512 * 1024)
36 #else
37 #define RTHREAD_STACK_SIZE_DEF (256 * 1024)
38 #endif
39 
40 #define	_SPINLOCK_UNLOCKED _ATOMIC_LOCK_UNLOCKED
41 
42 struct stack {
43 	SLIST_ENTRY(stack)	link;	/* link for free default stacks */
44 	void	*sp;			/* machine stack pointer */
45 	void	*base;			/* bottom of allocated area */
46 	size_t	guardsize;		/* size of PROT_NONE zone or */
47 					/* ==1 if application alloced */
48 	size_t	len;			/* total size of allocated stack */
49 };
50 
51 struct __sem {
52 	_atomic_lock_t lock;
53 	volatile int waitcount;
54 	volatile int value;
55 	int shared;
56 };
57 
58 TAILQ_HEAD(pthread_queue, pthread);
59 
60 struct pthread_mutex {
61 	_atomic_lock_t lock;
62 	struct pthread_queue lockers;
63 	int type;
64 	pthread_t owner;
65 	int count;
66 	int prioceiling;
67 };
68 
69 struct pthread_mutex_attr {
70 	int ma_type;
71 	int ma_protocol;
72 	int ma_prioceiling;
73 };
74 
75 struct pthread_cond {
76 	_atomic_lock_t lock;
77 	struct pthread_queue waiters;
78 	struct pthread_mutex *mutex;
79 	clockid_t clock;
80 };
81 
82 struct pthread_cond_attr {
83 	clockid_t ca_clock;
84 };
85 
86 struct pthread_rwlock {
87 	_atomic_lock_t lock;
88 	pthread_t owner;
89 	struct pthread_queue writers;
90 	int readers;
91 };
92 
93 struct pthread_rwlockattr {
94 	int pshared;
95 };
96 
97 struct pthread_attr {
98 	void *stack_addr;
99 	size_t stack_size;
100 	size_t guard_size;
101 	int detach_state;
102 	int contention_scope;
103 	int sched_policy;
104 	struct sched_param sched_param;
105 	int sched_inherit;
106 };
107 
108 #define	PTHREAD_MIN_PRIORITY	0
109 #define	PTHREAD_MAX_PRIORITY	31
110 
111 struct rthread_key {
112 	int used;
113 	void (*destructor)(void *);
114 };
115 
116 struct rthread_storage {
117 	int keyid;
118 	struct rthread_storage *next;
119 	void *data;
120 };
121 
122 struct rthread_cleanup_fn {
123 	void (*fn)(void *);
124 	void *arg;
125 	struct rthread_cleanup_fn *next;
126 };
127 
128 struct pthread_barrier {
129 	pthread_mutex_t mutex;
130 	pthread_cond_t cond;
131 	int threshold;
132 	int in;
133 	int out;
134 	int generation;
135 };
136 
137 struct pthread_barrierattr {
138 	int pshared;
139 };
140 
141 struct pthread_spinlock {
142 	_atomic_lock_t lock;
143 	pthread_t owner;
144 };
145 
146 struct tib;
147 struct pthread {
148 	struct __sem donesem;
149 	unsigned int flags;
150 	_atomic_lock_t flags_lock;
151 	struct tib *tib;
152 	void *retval;
153 	void *(*fn)(void *);
154 	void *arg;
155 	char name[32];
156 	struct stack *stack;
157 	LIST_ENTRY(pthread) threads;
158 	TAILQ_ENTRY(pthread) waiting;
159 	pthread_cond_t blocking_cond;
160 	struct pthread_attr attr;
161 	struct rthread_storage *local_storage;
162 	struct rthread_cleanup_fn *cleanup_fns;
163 	int myerrno;
164 
165 	/* cancel received in a delayed cancel block? */
166 	int delayed_cancel;
167 };
168 /* flags in pthread->flags */
169 #define	THREAD_DONE		0x001
170 #define	THREAD_DETACHED		0x002
171 
172 /* flags in tib->tib_thread_flags */
173 #define	TIB_THREAD_ASYNC_CANCEL		0x001
174 #define	TIB_THREAD_INITIAL_STACK	0x002	/* has stack from exec */
175 
176 #define ENTER_DELAYED_CANCEL_POINT(tib, self)				\
177 	(self)->delayed_cancel = 0;					\
178 	ENTER_CANCEL_POINT_INNER(tib, 1, 1)
179 
180 #define	ROUND_TO_PAGE(size) \
181 	(((size) + (_thread_pagesize - 1)) & ~(_thread_pagesize - 1))
182 
183 __BEGIN_HIDDEN_DECLS
184 void	_spinlock(volatile _atomic_lock_t *);
185 int	_spinlocktry(volatile _atomic_lock_t *);
186 void	_spinunlock(volatile _atomic_lock_t *);
187 int	_sem_wait(sem_t, int, const struct timespec *, int *);
188 int	_sem_post(sem_t);
189 
190 void	_rthread_init(void);
191 struct stack *_rthread_alloc_stack(pthread_t);
192 void	_rthread_free_stack(struct stack *);
193 void	_rthread_tls_destructors(pthread_t);
194 void	_rthread_debug(int, const char *, ...)
195 		__attribute__((__format__ (printf, 2, 3)));
196 void	_rthread_debug_init(void);
197 #ifndef NO_PIC
198 void	_rthread_dl_lock(int what);
199 #endif
200 void	_thread_malloc_reinit(void);
201 
202 extern int _threads_ready;
203 extern size_t _thread_pagesize;
204 extern LIST_HEAD(listhead, pthread) _thread_list;
205 extern _atomic_lock_t _thread_lock;
206 extern struct pthread_attr _rthread_attr_default;
207 __END_HIDDEN_DECLS
208 
209 void	_thread_dump_info(void);
210 
211 /* syscalls not declared in system headers */
212 #define REDIRECT_SYSCALL(x)		typeof(x) x asm("_thread_sys_"#x)
213 void	__threxit(pid_t *);
214 int	__thrsleep(const volatile void *, clockid_t, const struct timespec *,
215 	    volatile void *, const int *);
216 int	__thrwakeup(const volatile void *, int n);
217 int	__thrsigdivert(sigset_t, siginfo_t *, const struct timespec *);
218