]> git.saurik.com Git - apple/libpthread.git/blob - kern/kern_internal.h
3c302136af87329cfd6eb4f52c14698e8ef90a05
[apple/libpthread.git] / kern / kern_internal.h
1 /*
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #ifndef _SYS_PTHREAD_INTERNAL_H_
30 #define _SYS_PTHREAD_INTERNAL_H_
31
32 #ifdef KERNEL
33 #include <kern/thread_call.h>
34 #include <sys/pthread_shims.h>
35 #include <sys/queue.h>
36 #endif
37
38 #include "kern/synch_internal.h"
39 #include "kern/workqueue_internal.h"
40 #include "kern/kern_trace.h"
41 #include "pthread/qos.h"
42 #include "private/qos_private.h"
43
44 /* pthread userspace SPI feature checking, these constants are returned from bsdthread_register,
45 * as a bitmask, to inform userspace of the supported feature set. Old releases of OS X return
46 * from this call either zero or -1, allowing us to return a positive number for feature bits.
47 */
48 #define PTHREAD_FEATURE_DISPATCHFUNC 0x01 /* same as WQOPS_QUEUE_NEWSPISUPP, checks for dispatch function support */
49 #define PTHREAD_FEATURE_FINEPRIO 0x02 /* are fine grained prioirities available */
50 #define PTHREAD_FEATURE_BSDTHREADCTL 0x04 /* is the bsdthread_ctl syscall available */
51 #define PTHREAD_FEATURE_SETSELF 0x08 /* is the BSDTHREAD_CTL_SET_SELF command of bsdthread_ctl available */
52 #define PTHREAD_FEATURE_QOS_MAINTENANCE 0x10 /* is QOS_CLASS_MAINTENANCE available */
53 #define PTHREAD_FEATURE_QOS_DEFAULT 0x40000000 /* the kernel supports QOS_CLASS_DEFAULT */
54
55 /* pthread bsdthread_ctl sysctl commands */
56 #define BSDTHREAD_CTL_SET_QOS 0x10 /* bsdthread_ctl(BSDTHREAD_CTL_SET_QOS, thread_port, tsd_entry_addr, 0) */
57 #define BSDTHREAD_CTL_GET_QOS 0x20 /* bsdthread_ctl(BSDTHREAD_CTL_GET_QOS, thread_port, 0, 0) */
58 #define BSDTHREAD_CTL_QOS_OVERRIDE_START 0x40 /* bsdthread_ctl(BSDTHREAD_CTL_QOS_OVERRIDE_START, thread_port, priority, 0) */
59 #define BSDTHREAD_CTL_QOS_OVERRIDE_END 0x80 /* bsdthread_ctl(BSDTHREAD_CTL_QOS_OVERRIDE_END, thread_port, 0, 0) */
60 #define BSDTHREAD_CTL_SET_SELF 0x100 /* bsdthread_ctl(BSDTHREAD_CTL_SET_SELF, priority, voucher, flags) */
61 #define BSDTHREAD_CTL_QOS_OVERRIDE_RESET 0x200 /* bsdthread_ctl(BSDTHREAD_CTL_QOS_OVERRIDE_RESET, 0, 0, 0) */
62 #define BSDTHREAD_CTL_QOS_OVERRIDE_DISPATCH 0x400 /* bsdthread_ctl(BSDTHREAD_CTL_QOS_OVERRIDE_DISPATCH, thread_port, priority, 0) */
63
64 /* qos_class_t is mapped into one of these bits in the bitfield, this mapping now exists here because
65 * libdispatch requires the QoS class mask of the pthread_priority_t to be a bitfield.
66 */
67 #define __PTHREAD_PRIORITY_CBIT_USER_INTERACTIVE 0x20
68 #define __PTHREAD_PRIORITY_CBIT_USER_INITIATED 0x10
69 #define __PTHREAD_PRIORITY_CBIT_DEFAULT 0x8
70 #define __PTHREAD_PRIORITY_CBIT_UTILITY 0x4
71 #define __PTHREAD_PRIORITY_CBIT_BACKGROUND 0x2
72 #define __PTHREAD_PRIORITY_CBIT_MAINTENANCE 0x1
73 #define __PTHREAD_PRIORITY_CBIT_UNSPECIFIED 0x0
74
75 /* Added support for QOS_CLASS_MAINTENANCE */
76 static inline pthread_priority_t
77 _pthread_priority_make_newest(qos_class_t qc, int rel, unsigned long flags)
78 {
79 pthread_priority_t cls;
80 switch (qc) {
81 case QOS_CLASS_USER_INTERACTIVE: cls = __PTHREAD_PRIORITY_CBIT_USER_INTERACTIVE; break;
82 case QOS_CLASS_USER_INITIATED: cls = __PTHREAD_PRIORITY_CBIT_USER_INITIATED; break;
83 case QOS_CLASS_DEFAULT: cls = __PTHREAD_PRIORITY_CBIT_DEFAULT; break;
84 case QOS_CLASS_UTILITY: cls = __PTHREAD_PRIORITY_CBIT_UTILITY; break;
85 case QOS_CLASS_BACKGROUND: cls = __PTHREAD_PRIORITY_CBIT_BACKGROUND; break;
86 case QOS_CLASS_MAINTENANCE: cls = __PTHREAD_PRIORITY_CBIT_MAINTENANCE; break;
87 case QOS_CLASS_UNSPECIFIED:
88 default:
89 cls = __PTHREAD_PRIORITY_CBIT_UNSPECIFIED;
90 rel = 1; // results in priority bits == 0 <rdar://problem/16184900>
91 break;
92 }
93
94 pthread_priority_t p =
95 (flags & _PTHREAD_PRIORITY_FLAGS_MASK) |
96 ((cls << _PTHREAD_PRIORITY_QOS_CLASS_SHIFT) & _PTHREAD_PRIORITY_QOS_CLASS_MASK) |
97 (((uint8_t)rel - 1) & _PTHREAD_PRIORITY_PRIORITY_MASK);
98
99 return p;
100 }
101
102 /* Added support for QOS_CLASS_LEGACY and QOS_CLASS_INHERIT */
103 static inline pthread_priority_t
104 _pthread_priority_make_version2(qos_class_t qc, int rel, unsigned long flags)
105 {
106 pthread_priority_t cls;
107 switch (qc) {
108 case QOS_CLASS_USER_INTERACTIVE: cls = __PTHREAD_PRIORITY_CBIT_USER_INTERACTIVE; break;
109 case QOS_CLASS_USER_INITIATED: cls = __PTHREAD_PRIORITY_CBIT_USER_INITIATED; break;
110 case QOS_CLASS_DEFAULT: cls = __PTHREAD_PRIORITY_CBIT_DEFAULT; break;
111 case QOS_CLASS_UTILITY: cls = __PTHREAD_PRIORITY_CBIT_UTILITY; break;
112 case QOS_CLASS_BACKGROUND: cls = __PTHREAD_PRIORITY_CBIT_BACKGROUND; break;
113 case QOS_CLASS_UNSPECIFIED:
114 default:
115 cls = __PTHREAD_PRIORITY_CBIT_UNSPECIFIED;
116 rel = 1; // results in priority bits == 0 <rdar://problem/16184900>
117 break;
118 }
119
120 /*
121 * __PTHREAD_PRIORITY_CBIT_MAINTENANCE was defined as the 0th bit by shifting all the
122 * existing bits to the left by one. So for backward compatiblity for kernels that does
123 * not support QOS_CLASS_MAINTENANCE, we have to make it up by shifting the cls bit to
124 * right by one.
125 */
126 cls >>= 1;
127
128 pthread_priority_t p =
129 (flags & _PTHREAD_PRIORITY_FLAGS_MASK) |
130 ((cls << _PTHREAD_PRIORITY_QOS_CLASS_SHIFT) & _PTHREAD_PRIORITY_QOS_CLASS_MASK) |
131 (((uint8_t)rel - 1) & _PTHREAD_PRIORITY_PRIORITY_MASK);
132
133 return p;
134 }
135
136 /* QOS_CLASS_MAINTENANCE is supported */
137 static inline qos_class_t
138 _pthread_priority_get_qos_newest(pthread_priority_t priority)
139 {
140 qos_class_t qc;
141 switch ((priority & _PTHREAD_PRIORITY_QOS_CLASS_MASK) >> _PTHREAD_PRIORITY_QOS_CLASS_SHIFT) {
142 case __PTHREAD_PRIORITY_CBIT_USER_INTERACTIVE: qc = QOS_CLASS_USER_INTERACTIVE; break;
143 case __PTHREAD_PRIORITY_CBIT_USER_INITIATED: qc = QOS_CLASS_USER_INITIATED; break;
144 case __PTHREAD_PRIORITY_CBIT_DEFAULT: qc = QOS_CLASS_DEFAULT; break;
145 case __PTHREAD_PRIORITY_CBIT_UTILITY: qc = QOS_CLASS_UTILITY; break;
146 case __PTHREAD_PRIORITY_CBIT_BACKGROUND: qc = QOS_CLASS_BACKGROUND; break;
147 case __PTHREAD_PRIORITY_CBIT_MAINTENANCE: qc = QOS_CLASS_MAINTENANCE; break;
148 case __PTHREAD_PRIORITY_CBIT_UNSPECIFIED:
149 default: qc = QOS_CLASS_UNSPECIFIED; break;
150 }
151 return qc;
152 }
153
154 /* QOS_CLASS_MAINTENANCE is not supported */
155 static inline qos_class_t
156 _pthread_priority_get_qos_version2(pthread_priority_t priority)
157 {
158 qos_class_t qc;
159 pthread_priority_t cls;
160
161 cls = (priority & _PTHREAD_PRIORITY_QOS_CLASS_MASK) >> _PTHREAD_PRIORITY_QOS_CLASS_SHIFT;
162
163 /*
164 * __PTHREAD_PRIORITY_CBIT_MAINTENANCE was defined as the 0th bit by shifting all the
165 * existing bits to the left by one. So for backward compatiblity for kernels that does
166 * not support QOS_CLASS_MAINTENANCE, pthread_priority_make() shifted the cls bit to the
167 * right by one. Therefore we have to shift it back during decoding the priority bit.
168 */
169 cls <<= 1;
170
171 switch (cls) {
172 case __PTHREAD_PRIORITY_CBIT_USER_INTERACTIVE: qc = QOS_CLASS_USER_INTERACTIVE; break;
173 case __PTHREAD_PRIORITY_CBIT_USER_INITIATED: qc = QOS_CLASS_USER_INITIATED; break;
174 case __PTHREAD_PRIORITY_CBIT_DEFAULT: qc = QOS_CLASS_DEFAULT; break;
175 case __PTHREAD_PRIORITY_CBIT_UTILITY: qc = QOS_CLASS_UTILITY; break;
176 case __PTHREAD_PRIORITY_CBIT_BACKGROUND: qc = QOS_CLASS_BACKGROUND; break;
177 case __PTHREAD_PRIORITY_CBIT_UNSPECIFIED:
178 default: qc = QOS_CLASS_UNSPECIFIED; break;
179 }
180 return qc;
181 }
182
183 #define _pthread_priority_get_relpri(priority) \
184 ((int8_t)((priority & _PTHREAD_PRIORITY_PRIORITY_MASK) >> _PTHREAD_PRIORITY_PRIORITY_SHIFT) + 1)
185
186 #define _pthread_priority_get_flags(priority) \
187 (priority & _PTHREAD_PRIORITY_FLAGS_MASK)
188
189 #define _pthread_priority_split_newest(priority, qos, relpri) \
190 ({ qos = _pthread_priority_get_qos_newest(priority); \
191 relpri = (qos == QOS_CLASS_UNSPECIFIED) ? 0 : \
192 _pthread_priority_get_relpri(priority); \
193 })
194
195 #define _pthread_priority_split_version2(priority, qos, relpri) \
196 ({ qos = _pthread_priority_get_qos_version2(priority); \
197 relpri = (qos == QOS_CLASS_UNSPECIFIED) ? 0 : \
198 _pthread_priority_get_relpri(priority); \
199 })
200
201 /* <rdar://problem/15969976> Required for backward compatibility on older kernels. */
202 #define _pthread_priority_make_version1(qos, relpri, flags) \
203 (((flags >> 15) & 0xffff0000) | \
204 ((qos << 8) & 0x0000ff00) | \
205 (((uint8_t)relpri - 1) & 0x000000ff))
206
207 /* userspace <-> kernel registration struct, for passing data to/from the kext during main thread init. */
208 struct _pthread_registration_data {
209 uint64_t version; /* copy-in */
210 uint64_t dispatch_queue_offset; /* copy-in */
211 pthread_priority_t main_qos; /* copy-out */
212 };
213
214 #ifdef KERNEL
215
216 /* The set of features, from the feature bits above, that we support. */
217 #define PTHREAD_FEATURE_SUPPORTED ( \
218 PTHREAD_FEATURE_DISPATCHFUNC | \
219 PTHREAD_FEATURE_FINEPRIO | \
220 PTHREAD_FEATURE_BSDTHREADCTL | \
221 PTHREAD_FEATURE_SETSELF | \
222 PTHREAD_FEATURE_QOS_MAINTENANCE | \
223 PTHREAD_FEATURE_QOS_DEFAULT)
224
225 extern pthread_callbacks_t pthread_kern;
226
227 struct ksyn_waitq_element {
228 TAILQ_ENTRY(ksyn_waitq_element) kwe_list; /* link to other list members */
229 void * kwe_kwqqueue; /* queue blocked on */
230 uint32_t kwe_state; /* state */
231 uint32_t kwe_lockseq; /* the sequence of the entry */
232 uint32_t kwe_count; /* upper bound on number of matches still pending */
233 uint32_t kwe_psynchretval; /* thread retval */
234 void *kwe_uth; /* uthread */
235 uint64_t kwe_tid; /* tid of waiter */
236 };
237 typedef struct ksyn_waitq_element * ksyn_waitq_element_t;
238
239 pthread_priority_t pthread_qos_class_get_priority(int qos);
240 int pthread_priority_get_qos_class(pthread_priority_t priority);
241 int pthread_priority_get_class_index(pthread_priority_t priority);
242 pthread_priority_t pthread_priority_from_class_index(int index);
243
244 #define PTH_DEFAULT_STACKSIZE 512*1024
245 #define MAX_PTHREAD_SIZE 64*1024
246
247 /* exported from the kernel but not present in any headers. */
248 extern thread_t port_name_to_thread(mach_port_name_t port_name);
249
250 /* function declarations for pthread_kext.c */
251 void pthread_init(void);
252 void psynch_zoneinit(void);
253 void _pth_proc_hashinit(proc_t p);
254 void _pth_proc_hashdelete(proc_t p);
255 void pth_global_hashinit(void);
256 void psynch_wq_cleanup(void*, void*);
257
258 void _pthread_init(void);
259 int _fill_procworkqueue(proc_t p, struct proc_workqueueinfo * pwqinfo);
260 void _workqueue_init_lock(proc_t p);
261 void _workqueue_destroy_lock(proc_t p);
262 void _workqueue_exit(struct proc *p);
263 void _workqueue_mark_exiting(struct proc *p);
264 void _workqueue_thread_yielded(void);
265 sched_call_t _workqueue_get_sched_callback(void);
266
267 int _bsdthread_create(struct proc *p, user_addr_t user_func, user_addr_t user_funcarg, user_addr_t user_stack, user_addr_t user_pthread, uint32_t flags, user_addr_t *retval);
268 int _bsdthread_register(struct proc *p, user_addr_t threadstart, user_addr_t wqthread, int pthsize, user_addr_t dummy_value, user_addr_t targetconc_ptr, uint64_t dispatchqueue_offset, int32_t *retval);
269 int _bsdthread_terminate(struct proc *p, user_addr_t stackaddr, size_t size, uint32_t kthport, uint32_t sem, int32_t *retval);
270 int _bsdthread_ctl_set_qos(struct proc *p, user_addr_t cmd, mach_port_name_t kport, user_addr_t tsd_priority_addr, user_addr_t arg3, int *retval);
271 int _bsdthread_ctl_set_self(struct proc *p, user_addr_t cmd, pthread_priority_t priority, mach_port_name_t voucher, _pthread_set_flags_t flags, int *retval);
272 int _bsdthread_ctl_qos_override_start(struct proc *p, user_addr_t cmd, mach_port_name_t kport, pthread_priority_t priority, user_addr_t arg3, int *retval);
273 int _bsdthread_ctl_qos_override_end(struct proc *p, user_addr_t cmd, mach_port_name_t kport, user_addr_t arg2, user_addr_t arg3, int *retval);
274 int _bsdthread_ctl_qos_override_dispatch(struct proc __unused *p, user_addr_t __unused cmd, mach_port_name_t kport, pthread_priority_t priority, user_addr_t arg3, int __unused *retval);
275 int _bsdthread_ctl_qos_override_reset(struct proc __unused *p, user_addr_t __unused cmd, user_addr_t arg1, user_addr_t arg2, user_addr_t arg3, int __unused *retval);
276 int _bsdthread_ctl(struct proc *p, user_addr_t cmd, user_addr_t arg1, user_addr_t arg2, user_addr_t arg3, int *retval);
277 int _thread_selfid(__unused struct proc *p, uint64_t *retval);
278 int _workq_kernreturn(struct proc *p, int options, user_addr_t item, int arg2, int arg3, int32_t *retval);
279 int _workq_open(struct proc *p, int32_t *retval);
280
281 int _psynch_mutexwait(proc_t p, user_addr_t mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags, uint32_t * retval);
282 int _psynch_mutexdrop(proc_t p, user_addr_t mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags, uint32_t * retval);
283 int _psynch_cvbroad(proc_t p, user_addr_t cv, uint64_t cvlsgen, uint64_t cvudgen, uint32_t flags, user_addr_t mutex, uint64_t mugen, uint64_t tid, uint32_t *retval);
284 int _psynch_cvsignal(proc_t p, user_addr_t cv, uint64_t cvlsgen, uint32_t cvugen, int thread_port, user_addr_t mutex, uint64_t mugen, uint64_t tid, uint32_t flags, uint32_t * retval);
285 int _psynch_cvwait(proc_t p, user_addr_t cv, uint64_t cvlsgen, uint32_t cvugen, user_addr_t mutex, uint64_t mugen, uint32_t flags, int64_t sec, uint32_t nsec, uint32_t * retval);
286 int _psynch_cvclrprepost(proc_t p, user_addr_t cv, uint32_t cvgen, uint32_t cvugen, uint32_t cvsgen, uint32_t prepocnt, uint32_t preposeq, uint32_t flags, int *retval);
287 int _psynch_rw_longrdlock(proc_t p, user_addr_t rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags, uint32_t * retval);
288 int _psynch_rw_rdlock(proc_t p, user_addr_t rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags, uint32_t *retval);
289 int _psynch_rw_unlock(proc_t p, user_addr_t rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags, uint32_t *retval);
290 int _psynch_rw_wrlock(proc_t p, user_addr_t rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags, uint32_t *retval);
291 int _psynch_rw_yieldwrlock(proc_t p, user_addr_t rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags, uint32_t *retval);
292
293 extern lck_grp_attr_t *pthread_lck_grp_attr;
294 extern lck_grp_t *pthread_lck_grp;
295 extern lck_attr_t *pthread_lck_attr;
296 extern lck_mtx_t *pthread_list_mlock;
297 extern thread_call_t psynch_thcall;
298
299 struct uthread* current_uthread(void);
300
301 #endif // KERNEL
302
303 #endif /* _SYS_PTHREAD_INTERNAL_H_ */
304