1 /* $OpenBSD: rthread.h,v 1.58 2016/05/07 19:05:22 guenther 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 struct _spinlock 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 _USING_TICKETS 0 41 /* 42 * tickets don't work yet? (or seem much slower, with lots of system time) 43 * until then, keep the struct around to avoid excessive changes going 44 * back and forth. 45 */ 46 struct _spinlock { 47 _atomic_lock_t ticket; 48 }; 49 50 #define _SPINLOCK_UNLOCKED { _ATOMIC_LOCK_UNLOCKED } 51 extern struct _spinlock _SPINLOCK_UNLOCKED_ASSIGN; 52 53 struct stack { 54 SLIST_ENTRY(stack) link; /* link for free default stacks */ 55 void *sp; /* machine stack pointer */ 56 void *base; /* bottom of allocated area */ 57 size_t guardsize; /* size of PROT_NONE zone or */ 58 /* ==1 if application alloced */ 59 size_t len; /* total size of allocated stack */ 60 }; 61 62 struct __sem { 63 struct _spinlock lock; 64 volatile int waitcount; 65 volatile int value; 66 int shared; 67 }; 68 69 TAILQ_HEAD(pthread_queue, pthread); 70 71 struct pthread_mutex { 72 struct _spinlock lock; 73 struct pthread_queue lockers; 74 int type; 75 pthread_t owner; 76 int count; 77 int prioceiling; 78 }; 79 80 struct pthread_mutex_attr { 81 int ma_type; 82 int ma_protocol; 83 int ma_prioceiling; 84 }; 85 86 struct pthread_cond { 87 struct _spinlock lock; 88 struct pthread_queue waiters; 89 struct pthread_mutex *mutex; 90 clockid_t clock; 91 }; 92 93 struct pthread_cond_attr { 94 clockid_t ca_clock; 95 }; 96 97 struct pthread_rwlock { 98 struct _spinlock lock; 99 pthread_t owner; 100 struct pthread_queue writers; 101 int readers; 102 }; 103 104 struct pthread_rwlockattr { 105 int pshared; 106 }; 107 108 struct pthread_attr { 109 void *stack_addr; 110 size_t stack_size; 111 size_t guard_size; 112 int detach_state; 113 int contention_scope; 114 int sched_policy; 115 struct sched_param sched_param; 116 int sched_inherit; 117 }; 118 119 #define PTHREAD_MIN_PRIORITY 0 120 #define PTHREAD_MAX_PRIORITY 31 121 122 struct rthread_key { 123 int used; 124 void (*destructor)(void *); 125 }; 126 127 struct rthread_storage { 128 int keyid; 129 struct rthread_storage *next; 130 void *data; 131 }; 132 133 struct rthread_cleanup_fn { 134 void (*fn)(void *); 135 void *arg; 136 struct rthread_cleanup_fn *next; 137 }; 138 139 struct pthread_barrier { 140 pthread_mutex_t mutex; 141 pthread_cond_t cond; 142 int threshold; 143 int in; 144 int out; 145 int generation; 146 }; 147 148 struct pthread_barrierattr { 149 int pshared; 150 }; 151 152 struct pthread_spinlock { 153 struct _spinlock lock; 154 pthread_t owner; 155 }; 156 157 struct tib; 158 struct pthread { 159 struct __sem donesem; 160 unsigned int flags; 161 struct _spinlock flags_lock; 162 struct tib *tib; 163 void *retval; 164 void *(*fn)(void *); 165 void *arg; 166 char name[32]; 167 struct stack *stack; 168 LIST_ENTRY(pthread) threads; 169 TAILQ_ENTRY(pthread) waiting; 170 pthread_cond_t blocking_cond; 171 struct pthread_attr attr; 172 struct rthread_storage *local_storage; 173 struct rthread_cleanup_fn *cleanup_fns; 174 int myerrno; 175 176 /* cancel received in a delayed cancel block? */ 177 int delayed_cancel; 178 }; 179 /* flags in pthread->flags */ 180 #define THREAD_DONE 0x001 181 #define THREAD_DETACHED 0x002 182 183 /* flags in tib->tib_thread_flags */ 184 #define TIB_THREAD_ASYNC_CANCEL 0x001 185 #define TIB_THREAD_INITIAL_STACK 0x002 /* has stack from exec */ 186 187 #define ENTER_DELAYED_CANCEL_POINT(tib, self) \ 188 (self)->delayed_cancel = 0; \ 189 ENTER_CANCEL_POINT_INNER(tib, 1, 1) 190 191 #define ROUND_TO_PAGE(size) \ 192 (((size) + (_thread_pagesize - 1)) & ~(_thread_pagesize - 1)) 193 194 __BEGIN_HIDDEN_DECLS 195 void _spinlock(volatile struct _spinlock *); 196 int _spinlocktry(volatile struct _spinlock *); 197 void _spinunlock(volatile struct _spinlock *); 198 int _sem_wait(sem_t, int, const struct timespec *, int *); 199 int _sem_post(sem_t); 200 201 void _rthread_init(void); 202 struct stack *_rthread_alloc_stack(pthread_t); 203 void _rthread_free_stack(struct stack *); 204 void _rthread_tls_destructors(pthread_t); 205 void _rthread_debug(int, const char *, ...) 206 __attribute__((__format__ (printf, 2, 3))); 207 void _rthread_debug_init(void); 208 #ifndef NO_PIC 209 void _rthread_dl_lock(int what); 210 #endif 211 void _thread_malloc_reinit(void); 212 213 extern int _threads_ready; 214 extern size_t _thread_pagesize; 215 extern LIST_HEAD(listhead, pthread) _thread_list; 216 extern struct _spinlock _thread_lock; 217 extern struct pthread_attr _rthread_attr_default; 218 __END_HIDDEN_DECLS 219 220 void _thread_dump_info(void); 221 222 /* syscalls not declared in system headers */ 223 #define REDIRECT_SYSCALL(x) typeof(x) x asm("_thread_sys_"#x) 224 void __threxit(pid_t *); 225 int __thrsleep(const volatile void *, clockid_t, const struct timespec *, 226 volatile void *, const int *); 227 int __thrwakeup(const volatile void *, int n); 228 int __thrsigdivert(sigset_t, siginfo_t *, const struct timespec *); 229