]> git.saurik.com Git - apple/libpthread.git/blame - kern/kern_internal.h
libpthread-301.1.6.tar.gz
[apple/libpthread.git] / kern / kern_internal.h
CommitLineData
f1a1da6c
A
1/*
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
a0619f9c 5 *
f1a1da6c
A
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.
a0619f9c 14 *
f1a1da6c
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
a0619f9c 17 *
f1a1da6c
A
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.
a0619f9c 25 *
f1a1da6c
A
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#ifndef _SYS_PTHREAD_INTERNAL_H_
30#define _SYS_PTHREAD_INTERNAL_H_
31
32#ifdef KERNEL
a0619f9c 33#include <stdatomic.h>
f1a1da6c 34#include <kern/thread_call.h>
a0619f9c 35#include <kern/kcdata.h>
f1a1da6c
A
36#include <sys/pthread_shims.h>
37#include <sys/queue.h>
a0619f9c
A
38#include <sys/proc_info.h>
39
40#ifdef __arm64__
41#define PTHREAD_INLINE_RMW_ATOMICS 0
42#else
43#define PTHREAD_INLINE_RMW_ATOMICS 1
f1a1da6c 44#endif
a0619f9c 45#endif // KERNEL
f1a1da6c
A
46
47#include "kern/synch_internal.h"
48#include "kern/workqueue_internal.h"
49#include "kern/kern_trace.h"
50#include "pthread/qos.h"
51#include "private/qos_private.h"
52
53/* pthread userspace SPI feature checking, these constants are returned from bsdthread_register,
54 * as a bitmask, to inform userspace of the supported feature set. Old releases of OS X return
55 * from this call either zero or -1, allowing us to return a positive number for feature bits.
56 */
57#define PTHREAD_FEATURE_DISPATCHFUNC 0x01 /* same as WQOPS_QUEUE_NEWSPISUPP, checks for dispatch function support */
58#define PTHREAD_FEATURE_FINEPRIO 0x02 /* are fine grained prioirities available */
59#define PTHREAD_FEATURE_BSDTHREADCTL 0x04 /* is the bsdthread_ctl syscall available */
60#define PTHREAD_FEATURE_SETSELF 0x08 /* is the BSDTHREAD_CTL_SET_SELF command of bsdthread_ctl available */
61#define PTHREAD_FEATURE_QOS_MAINTENANCE 0x10 /* is QOS_CLASS_MAINTENANCE available */
2546420a
A
62#define PTHREAD_FEATURE_RESERVED 0x20 /* burnt, shipped in OSX 10.11 & iOS 9 with partial kevent delivery support */
63#define PTHREAD_FEATURE_KEVENT 0x40 /* supports direct kevent delivery */
a0619f9c 64#define PTHREAD_FEATURE_WORKLOOP 0x80 /* supports workloops */
f1a1da6c
A
65#define PTHREAD_FEATURE_QOS_DEFAULT 0x40000000 /* the kernel supports QOS_CLASS_DEFAULT */
66
67/* pthread bsdthread_ctl sysctl commands */
2546420a
A
68#define BSDTHREAD_CTL_SET_QOS 0x10 /* bsdthread_ctl(BSDTHREAD_CTL_SET_QOS, thread_port, tsd_entry_addr, 0) */
69#define BSDTHREAD_CTL_GET_QOS 0x20 /* bsdthread_ctl(BSDTHREAD_CTL_GET_QOS, thread_port, 0, 0) */
f1a1da6c
A
70#define BSDTHREAD_CTL_QOS_OVERRIDE_START 0x40 /* bsdthread_ctl(BSDTHREAD_CTL_QOS_OVERRIDE_START, thread_port, priority, 0) */
71#define BSDTHREAD_CTL_QOS_OVERRIDE_END 0x80 /* bsdthread_ctl(BSDTHREAD_CTL_QOS_OVERRIDE_END, thread_port, 0, 0) */
2546420a 72#define BSDTHREAD_CTL_SET_SELF 0x100 /* bsdthread_ctl(BSDTHREAD_CTL_SET_SELF, priority, voucher, flags) */
f1a1da6c
A
73#define BSDTHREAD_CTL_QOS_OVERRIDE_RESET 0x200 /* bsdthread_ctl(BSDTHREAD_CTL_QOS_OVERRIDE_RESET, 0, 0, 0) */
74#define BSDTHREAD_CTL_QOS_OVERRIDE_DISPATCH 0x400 /* bsdthread_ctl(BSDTHREAD_CTL_QOS_OVERRIDE_DISPATCH, thread_port, priority, 0) */
2546420a
A
75#define BSDTHREAD_CTL_QOS_DISPATCH_ASYNCHRONOUS_OVERRIDE_ADD 0x401 /* bsdthread_ctl(BSDTHREAD_CTL_QOS_DISPATCH_ASYNCHRONOUS_OVERRIDE_ADD, thread_port, priority, resource) */
76#define BSDTHREAD_CTL_QOS_DISPATCH_ASYNCHRONOUS_OVERRIDE_RESET 0x402 /* bsdthread_ctl(BSDTHREAD_CTL_QOS_DISPATCH_ASYNCHRONOUS_OVERRIDE_RESET, 0|1 (?reset_all), resource, 0) */
a0619f9c 77#define BSDTHREAD_CTL_QOS_MAX_PARALLELISM 0x800 /* bsdthread_ctl(BSDTHREAD_CTL_QOS_MAX_PARALLELISM, priority, flags, 0) */
f1a1da6c
A
78
79/* qos_class_t is mapped into one of these bits in the bitfield, this mapping now exists here because
80 * libdispatch requires the QoS class mask of the pthread_priority_t to be a bitfield.
81 */
82#define __PTHREAD_PRIORITY_CBIT_USER_INTERACTIVE 0x20
83#define __PTHREAD_PRIORITY_CBIT_USER_INITIATED 0x10
84#define __PTHREAD_PRIORITY_CBIT_DEFAULT 0x8
85#define __PTHREAD_PRIORITY_CBIT_UTILITY 0x4
86#define __PTHREAD_PRIORITY_CBIT_BACKGROUND 0x2
87#define __PTHREAD_PRIORITY_CBIT_MAINTENANCE 0x1
88#define __PTHREAD_PRIORITY_CBIT_UNSPECIFIED 0x0
89
a0619f9c
A
90static inline int
91_pthread_qos_class_to_thread_qos(qos_class_t qos)
f1a1da6c 92{
a0619f9c
A
93 switch (qos) {
94 case QOS_CLASS_USER_INTERACTIVE: return THREAD_QOS_USER_INTERACTIVE;
95 case QOS_CLASS_USER_INITIATED: return THREAD_QOS_USER_INITIATED;
96 case QOS_CLASS_DEFAULT: return THREAD_QOS_LEGACY;
97 case QOS_CLASS_UTILITY: return THREAD_QOS_UTILITY;
98 case QOS_CLASS_BACKGROUND: return THREAD_QOS_BACKGROUND;
99 case QOS_CLASS_MAINTENANCE: return THREAD_QOS_MAINTENANCE;
100 default: return THREAD_QOS_UNSPECIFIED;
f1a1da6c 101 }
f1a1da6c
A
102}
103
f1a1da6c 104static inline pthread_priority_t
a0619f9c 105_pthread_priority_make_newest(qos_class_t qc, int rel, unsigned long flags)
f1a1da6c
A
106{
107 pthread_priority_t cls;
108 switch (qc) {
109 case QOS_CLASS_USER_INTERACTIVE: cls = __PTHREAD_PRIORITY_CBIT_USER_INTERACTIVE; break;
110 case QOS_CLASS_USER_INITIATED: cls = __PTHREAD_PRIORITY_CBIT_USER_INITIATED; break;
111 case QOS_CLASS_DEFAULT: cls = __PTHREAD_PRIORITY_CBIT_DEFAULT; break;
112 case QOS_CLASS_UTILITY: cls = __PTHREAD_PRIORITY_CBIT_UTILITY; break;
113 case QOS_CLASS_BACKGROUND: cls = __PTHREAD_PRIORITY_CBIT_BACKGROUND; break;
a0619f9c 114 case QOS_CLASS_MAINTENANCE: cls = __PTHREAD_PRIORITY_CBIT_MAINTENANCE; break;
f1a1da6c
A
115 case QOS_CLASS_UNSPECIFIED:
116 default:
117 cls = __PTHREAD_PRIORITY_CBIT_UNSPECIFIED;
118 rel = 1; // results in priority bits == 0 <rdar://problem/16184900>
119 break;
120 }
121
f1a1da6c
A
122 pthread_priority_t p =
123 (flags & _PTHREAD_PRIORITY_FLAGS_MASK) |
124 ((cls << _PTHREAD_PRIORITY_QOS_CLASS_SHIFT) & _PTHREAD_PRIORITY_QOS_CLASS_MASK) |
125 (((uint8_t)rel - 1) & _PTHREAD_PRIORITY_PRIORITY_MASK);
126
127 return p;
128}
129
f1a1da6c
A
130static inline qos_class_t
131_pthread_priority_get_qos_newest(pthread_priority_t priority)
132{
133 qos_class_t qc;
134 switch ((priority & _PTHREAD_PRIORITY_QOS_CLASS_MASK) >> _PTHREAD_PRIORITY_QOS_CLASS_SHIFT) {
135 case __PTHREAD_PRIORITY_CBIT_USER_INTERACTIVE: qc = QOS_CLASS_USER_INTERACTIVE; break;
136 case __PTHREAD_PRIORITY_CBIT_USER_INITIATED: qc = QOS_CLASS_USER_INITIATED; break;
137 case __PTHREAD_PRIORITY_CBIT_DEFAULT: qc = QOS_CLASS_DEFAULT; break;
138 case __PTHREAD_PRIORITY_CBIT_UTILITY: qc = QOS_CLASS_UTILITY; break;
139 case __PTHREAD_PRIORITY_CBIT_BACKGROUND: qc = QOS_CLASS_BACKGROUND; break;
140 case __PTHREAD_PRIORITY_CBIT_MAINTENANCE: qc = QOS_CLASS_MAINTENANCE; break;
141 case __PTHREAD_PRIORITY_CBIT_UNSPECIFIED:
142 default: qc = QOS_CLASS_UNSPECIFIED; break;
143 }
144 return qc;
145}
146
f1a1da6c
A
147#define _pthread_priority_get_relpri(priority) \
148 ((int8_t)((priority & _PTHREAD_PRIORITY_PRIORITY_MASK) >> _PTHREAD_PRIORITY_PRIORITY_SHIFT) + 1)
149
150#define _pthread_priority_get_flags(priority) \
151 (priority & _PTHREAD_PRIORITY_FLAGS_MASK)
152
153#define _pthread_priority_split_newest(priority, qos, relpri) \
154 ({ qos = _pthread_priority_get_qos_newest(priority); \
155 relpri = (qos == QOS_CLASS_UNSPECIFIED) ? 0 : \
156 _pthread_priority_get_relpri(priority); \
157 })
158
a0619f9c
A
159#define _PTHREAD_QOS_PARALLELISM_COUNT_LOGICAL 0x1
160#define _PTHREAD_QOS_PARALLELISM_REALTIME 0x2
f1a1da6c
A
161
162/* userspace <-> kernel registration struct, for passing data to/from the kext during main thread init. */
163struct _pthread_registration_data {
2546420a
A
164 /*
165 * version == sizeof(struct _pthread_registration_data)
166 *
167 * The structure can only grow, so we use its size as the version.
168 * Userspace initializes this to the size of its structure and the kext
169 * will copy out the version that was actually consumed.
170 *
171 * n.b. you must make sure the size of this structure isn't LP64-dependent
172 */
173 uint64_t version;
174
f1a1da6c 175 uint64_t dispatch_queue_offset; /* copy-in */
2546420a
A
176 uint64_t /* pthread_priority_t */ main_qos; /* copy-out */
177 uint32_t tsd_offset; /* copy-in */
a0619f9c
A
178 uint32_t return_to_kernel_offset; /* copy-in */
179 uint32_t mach_thread_self_offset; /* copy-in */
2546420a 180} __attribute__ ((packed));
f1a1da6c
A
181
182#ifdef KERNEL
183
184/* The set of features, from the feature bits above, that we support. */
185#define PTHREAD_FEATURE_SUPPORTED ( \
186 PTHREAD_FEATURE_DISPATCHFUNC | \
187 PTHREAD_FEATURE_FINEPRIO | \
188 PTHREAD_FEATURE_BSDTHREADCTL | \
189 PTHREAD_FEATURE_SETSELF | \
190 PTHREAD_FEATURE_QOS_MAINTENANCE | \
964d3577 191 PTHREAD_FEATURE_QOS_DEFAULT | \
a0619f9c
A
192 PTHREAD_FEATURE_KEVENT | \
193 PTHREAD_FEATURE_WORKLOOP )
f1a1da6c
A
194
195extern pthread_callbacks_t pthread_kern;
196
197struct ksyn_waitq_element {
198 TAILQ_ENTRY(ksyn_waitq_element) kwe_list; /* link to other list members */
199 void * kwe_kwqqueue; /* queue blocked on */
200 uint32_t kwe_state; /* state */
201 uint32_t kwe_lockseq; /* the sequence of the entry */
202 uint32_t kwe_count; /* upper bound on number of matches still pending */
203 uint32_t kwe_psynchretval; /* thread retval */
204 void *kwe_uth; /* uthread */
205 uint64_t kwe_tid; /* tid of waiter */
206};
207typedef struct ksyn_waitq_element * ksyn_waitq_element_t;
208
2546420a
A
209pthread_priority_t thread_qos_get_pthread_priority(int qos) __attribute__((const));
210int thread_qos_get_class_index(int qos) __attribute__((const));
211int pthread_priority_get_thread_qos(pthread_priority_t priority) __attribute__((const));
964d3577 212int pthread_priority_get_class_index(pthread_priority_t priority) __attribute__((const));
2546420a
A
213pthread_priority_t class_index_get_pthread_priority(int index) __attribute__((const));
214int class_index_get_thread_qos(int index) __attribute__((const));
215int qos_class_get_class_index(int qos) __attribute__((const));
f1a1da6c
A
216
217#define PTH_DEFAULT_STACKSIZE 512*1024
218#define MAX_PTHREAD_SIZE 64*1024
219
220/* exported from the kernel but not present in any headers. */
221extern thread_t port_name_to_thread(mach_port_name_t port_name);
222
223/* function declarations for pthread_kext.c */
224void pthread_init(void);
225void psynch_zoneinit(void);
226void _pth_proc_hashinit(proc_t p);
227void _pth_proc_hashdelete(proc_t p);
228void pth_global_hashinit(void);
229void psynch_wq_cleanup(void*, void*);
230
231void _pthread_init(void);
232int _fill_procworkqueue(proc_t p, struct proc_workqueueinfo * pwqinfo);
2546420a 233uint32_t _get_pwq_state_kdp(proc_t p);
f1a1da6c
A
234void _workqueue_exit(struct proc *p);
235void _workqueue_mark_exiting(struct proc *p);
236void _workqueue_thread_yielded(void);
237sched_call_t _workqueue_get_sched_callback(void);
238
239int _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);
240int _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);
241int _bsdthread_terminate(struct proc *p, user_addr_t stackaddr, size_t size, uint32_t kthport, uint32_t sem, int32_t *retval);
242int _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);
243int _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);
215aeb03
A
244int _bsdthread_ctl_qos_override_start(struct proc *p, user_addr_t cmd, mach_port_name_t kport, pthread_priority_t priority, user_addr_t resource, int *retval);
245int _bsdthread_ctl_qos_override_end(struct proc *p, user_addr_t cmd, mach_port_name_t kport, user_addr_t resource, user_addr_t arg3, int *retval);
f1a1da6c
A
246int _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);
247int _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);
215aeb03
A
248int _bsdthread_ctl_qos_dispatch_asynchronous_override_add(struct proc __unused *p, user_addr_t __unused cmd, mach_port_name_t kport, pthread_priority_t priority, user_addr_t resource, int __unused *retval);
249int _bsdthread_ctl_qos_dispatch_asynchronous_override_reset(struct proc __unused *p, user_addr_t __unused cmd, int reset_all, user_addr_t resource, user_addr_t arg3, int __unused *retval);
f1a1da6c
A
250int _bsdthread_ctl(struct proc *p, user_addr_t cmd, user_addr_t arg1, user_addr_t arg2, user_addr_t arg3, int *retval);
251int _thread_selfid(__unused struct proc *p, uint64_t *retval);
252int _workq_kernreturn(struct proc *p, int options, user_addr_t item, int arg2, int arg3, int32_t *retval);
253int _workq_open(struct proc *p, int32_t *retval);
254
255int _psynch_mutexwait(proc_t p, user_addr_t mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags, uint32_t * retval);
256int _psynch_mutexdrop(proc_t p, user_addr_t mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags, uint32_t * retval);
257int _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);
258int _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);
259int _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);
260int _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);
261int _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);
262int _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);
263int _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);
264int _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);
265int _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);
266
010efe49
A
267void _pthread_find_owner(thread_t thread, struct stackshot_thread_waitinfo *waitinfo);
268void * _pthread_get_thread_kwq(thread_t thread);
269
f1a1da6c
A
270extern lck_grp_attr_t *pthread_lck_grp_attr;
271extern lck_grp_t *pthread_lck_grp;
272extern lck_attr_t *pthread_lck_attr;
273extern lck_mtx_t *pthread_list_mlock;
274extern thread_call_t psynch_thcall;
275
276struct uthread* current_uthread(void);
277
a0619f9c
A
278#define WORKQ_REQTHREADS_THREADREQ 0x1
279#define WORKQ_REQTHREADS_NOEMERGENCY 0x2
280
964d3577
A
281// Call for the kernel's kevent system to request threads. A list of QoS/event
282// counts should be provided, sorted by flags and then QoS class. If the
283// identity of the thread to handle the request is known, it will be returned.
284// If a new thread must be created, NULL will be returned.
285thread_t _workq_reqthreads(struct proc *p, int requests_count,
286 workq_reqthreads_req_t requests);
287
288// Resolve a pthread_priority_t to a QoS/relative pri
289integer_t _thread_qos_from_pthread_priority(unsigned long pri, unsigned long *flags);
2546420a
A
290// Clear out extraneous flags/pri info for putting in voucher
291pthread_priority_t _pthread_priority_canonicalize(pthread_priority_t pri, boolean_t for_propagation);
964d3577 292
a0619f9c
A
293boolean_t _workq_thread_has_been_unbound(thread_t th, int qos_class);
294
295int workq_kern_threadreq(struct proc *p, workq_threadreq_t req,
296 enum workq_threadreq_type, unsigned long priority, int flags);
297
298int workq_kern_threadreq_modify(struct proc *p, workq_threadreq_t req,
299 enum workq_threadreq_op operation,
300 unsigned long arg1, unsigned long arg2);
301
f1a1da6c
A
302#endif // KERNEL
303
304#endif /* _SYS_PTHREAD_INTERNAL_H_ */
305