1 | /* |
2 | * Copyright (c) 2000-2017 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 _PTHREAD_PRIORITY_PRIVATE_H_ |
30 | #define _PTHREAD_PRIORITY_PRIVATE_H_ |
31 | |
32 | /*! |
33 | * @typedef pthread_priority_t |
34 | * |
35 | * @abstract |
36 | * pthread_priority_t is an on opaque integer that is guaranteed to be ordered |
37 | * such that combations of QoS classes and relative priorities are ordered |
38 | * numerically, according to their combined priority. |
39 | * |
40 | * <b>xnu, pthread & libdispatch flags</b> |
41 | * |
42 | * @const _PTHREAD_PRIORITY_OVERCOMMIT_FLAG |
43 | * The thread this priority is applied to is overcommit (affects the workqueue |
44 | * creation policy for this priority). |
45 | * |
46 | * @const _PTHREAD_PRIORITY_FALLBACK_FLAG |
47 | * Indicates that this priority is is used only when incoming events have no |
48 | * priority at all. It is merely used as a fallback (hence the name) instead of |
49 | * a floor. |
50 | * |
51 | * This is usually used with QOS_CLASS_DEFAULT and a 0 relative priority. |
52 | * |
53 | * @const _PTHREAD_PRIORITY_EVENT_MANAGER_FLAG |
54 | * The event manager flag indicates that this thread/request is for a event |
55 | * manager thread. There can only ever be one event manager thread at a time |
56 | * and it is brought up at the highest of all event manager priorities pthread |
57 | * knows about. |
58 | * |
59 | * <b>pthread & dispatch only flags</b> |
60 | * |
61 | * @const _PTHREAD_PRIORITY_SCHED_PRI_FLAG |
62 | * @const _PTHREAD_PRIORITY_SCHED_PRI_MASK |
63 | * This flag indicates that the bits extracted using |
64 | * _PTHREAD_PRIORITY_SCHED_PRI_MASK represent a scheduler priority instead of |
65 | * a {qos, relative priority} pair. |
66 | * |
67 | * This flag is only used by the pthread kext to indicate libdispatch that the |
68 | * event manager queue priority is a scheduling priority and not a QoS. This |
69 | * flag is never used as an input by anything else and is why it can perform |
70 | * a double duty with _PTHREAD_PRIORITY_ROOTQUEUE_FLAG. |
71 | * |
72 | * @const _PTHREAD_PRIORITY_NEEDS_UNBIND_FLAG |
73 | * This flag is used for the priority of event delivery threads to indicate |
74 | * to libdispatch that this thread is bound to a kqueue. |
75 | * |
76 | * <b>dispatch only flags</b> |
77 | * |
78 | * @const _PTHREAD_PRIORITY_INHERIT_FLAG |
79 | * This flag is meaningful to libdispatch only and has no meanting for the |
80 | * kernel and/or pthread. |
81 | * |
82 | * @const _PTHREAD_PRIORITY_ROOTQUEUE_FLAG |
83 | * This flag is meaningful to libdispatch only and has no meanting for the |
84 | * kernel and/or pthread. |
85 | * |
86 | * @const _PTHREAD_PRIORITY_ENFORCE_FLAG |
87 | * This flag is used to indicate that this priority should be prefered for work |
88 | * submited asynchronously over the intrinsic priority of the queue/thread the |
89 | * work is submitted to. |
90 | * |
91 | * @const _PTHREAD_PRIORITY_OVERRIDE_FLAG |
92 | * No longer used |
93 | */ |
94 | typedef unsigned long pthread_priority_t; |
95 | |
96 | #define _PTHREAD_PRIORITY_FLAGS_MASK 0xff000000 |
97 | #define _PTHREAD_PRIORITY_FLAGS_SHIFT (24ull) |
98 | |
99 | #define _PTHREAD_PRIORITY_OVERCOMMIT_FLAG 0x80000000 |
100 | #define _PTHREAD_PRIORITY_INHERIT_FLAG 0x40000000 /* dispatch only */ |
101 | #define _PTHREAD_PRIORITY_ROOTQUEUE_FLAG 0x20000000 /* dispatch only */ |
102 | #define _PTHREAD_PRIORITY_SCHED_PRI_FLAG 0x20000000 |
103 | #define _PTHREAD_PRIORITY_SCHED_PRI_MASK 0x0000ffff |
104 | #define _PTHREAD_PRIORITY_ENFORCE_FLAG 0x10000000 /* dispatch only */ |
105 | #define _PTHREAD_PRIORITY_OVERRIDE_FLAG 0x08000000 /* unused */ |
106 | #define _PTHREAD_PRIORITY_FALLBACK_FLAG 0x04000000 |
107 | #define _PTHREAD_PRIORITY_EVENT_MANAGER_FLAG 0x02000000 |
108 | #define _PTHREAD_PRIORITY_NEEDS_UNBIND_FLAG 0x01000000 |
109 | #define _PTHREAD_PRIORITY_DEFAULTQUEUE_FLAG _PTHREAD_PRIORITY_FALLBACK_FLAG // compat |
110 | |
111 | #define _PTHREAD_PRIORITY_ENCODING_MASK 0x00a00000 |
112 | #define _PTHREAD_PRIORITY_ENCODING_SHIFT (22ull) |
113 | #define _PTHREAD_PRIORITY_ENCODING_V0 0x00000000 |
114 | #define _PTHREAD_PRIORITY_ENCODING_V1 0x00400000 /* unused */ |
115 | #define _PTHREAD_PRIORITY_ENCODING_V2 0x00800000 /* unused */ |
116 | #define _PTHREAD_PRIORITY_ENCODING_V3 0x00a00000 /* unused */ |
117 | |
118 | #define _PTHREAD_PRIORITY_QOS_CLASS_MASK 0x003fff00 |
119 | #define _PTHREAD_PRIORITY_VALID_QOS_CLASS_MASK 0x00003f00 |
120 | #define _PTHREAD_PRIORITY_QOS_CLASS_SHIFT (8ull) |
121 | |
122 | #define _PTHREAD_PRIORITY_PRIORITY_MASK 0x000000ff |
123 | #define _PTHREAD_PRIORITY_PRIORITY_SHIFT (0) |
124 | |
125 | #if PRIVATE |
126 | #if XNU_KERNEL_PRIVATE && !defined(__PTHREAD_EXPOSE_INTERNALS__) |
127 | #define __PTHREAD_EXPOSE_INTERNALS__ 1 |
128 | #endif // XNU_KERNEL_PRIVATE |
129 | #ifdef __PTHREAD_EXPOSE_INTERNALS__ |
130 | /* |
131 | * This exposes the encoding used for pthread_priority_t |
132 | * and is meant to be used by pthread and XNU only |
133 | */ |
134 | #include <mach/thread_policy.h> // THREAD_QOS_* |
135 | #include <stdbool.h> |
136 | |
137 | __attribute__((always_inline, const)) |
138 | static inline bool |
139 | _pthread_priority_has_qos(pthread_priority_t pp) |
140 | { |
141 | return (pp & (_PTHREAD_PRIORITY_SCHED_PRI_FLAG | |
142 | _PTHREAD_PRIORITY_EVENT_MANAGER_FLAG)) == 0 && |
143 | (pp & (_PTHREAD_PRIORITY_QOS_CLASS_MASK & |
144 | ~_PTHREAD_PRIORITY_VALID_QOS_CLASS_MASK)) == 0 && |
145 | (pp & _PTHREAD_PRIORITY_VALID_QOS_CLASS_MASK) != 0; |
146 | } |
147 | |
148 | __attribute__((always_inline, const)) |
149 | static inline pthread_priority_t |
150 | _pthread_priority_make_from_thread_qos(thread_qos_t qos, int relpri, |
151 | unsigned long flags) |
152 | { |
153 | pthread_priority_t pp = (flags & _PTHREAD_PRIORITY_FLAGS_MASK); |
154 | if (qos && qos < THREAD_QOS_LAST) { |
155 | pp |= (1 << (_PTHREAD_PRIORITY_QOS_CLASS_SHIFT + qos - 1)); |
156 | pp |= ((uint8_t)relpri - 1) & _PTHREAD_PRIORITY_PRIORITY_MASK; |
157 | } |
158 | return pp; |
159 | } |
160 | |
161 | __attribute__((always_inline, const)) |
162 | static inline pthread_priority_t |
163 | _pthread_event_manager_priority(void) |
164 | { |
165 | return _PTHREAD_PRIORITY_EVENT_MANAGER_FLAG; |
166 | } |
167 | |
168 | __attribute__((always_inline, const)) |
169 | static inline pthread_priority_t |
170 | _pthread_unspecified_priority(void) |
171 | { |
172 | return _pthread_priority_make_from_thread_qos(THREAD_QOS_UNSPECIFIED, 0, 0); |
173 | } |
174 | |
175 | __attribute__((always_inline, const)) |
176 | static inline pthread_priority_t |
177 | _pthread_default_priority(unsigned long flags) |
178 | { |
179 | return _pthread_priority_make_from_thread_qos(THREAD_QOS_LEGACY, 0, flags); |
180 | } |
181 | |
182 | __attribute__((always_inline, const)) |
183 | static inline thread_qos_t |
184 | _pthread_priority_thread_qos(pthread_priority_t pp) |
185 | { |
186 | if (_pthread_priority_has_qos(pp)) { |
187 | pp &= _PTHREAD_PRIORITY_QOS_CLASS_MASK; |
188 | pp >>= _PTHREAD_PRIORITY_QOS_CLASS_SHIFT; |
189 | return (thread_qos_t)__builtin_ffs((int)pp); |
190 | } |
191 | return THREAD_QOS_UNSPECIFIED; |
192 | } |
193 | |
194 | __attribute__((always_inline, const)) |
195 | static inline int |
196 | _pthread_priority_relpri(pthread_priority_t pp) |
197 | { |
198 | if (_pthread_priority_has_qos(pp)) { |
199 | pp &= _PTHREAD_PRIORITY_PRIORITY_MASK; |
200 | pp >>= _PTHREAD_PRIORITY_PRIORITY_SHIFT; |
201 | return (int8_t)pp + 1; |
202 | } |
203 | return 0; |
204 | } |
205 | |
206 | #if KERNEL |
207 | // Interfaces only used by the kernel and not implemented in userspace. |
208 | |
209 | /* |
210 | * Keep managerness, overcomitness and fallback, discard other flags. |
211 | * Normalize and validate QoS/relpri |
212 | */ |
213 | __attribute__((const)) |
214 | pthread_priority_t |
215 | _pthread_priority_normalize(pthread_priority_t pp); |
216 | |
217 | /* |
218 | * Keep managerness, discard other flags. |
219 | * Normalize and validate QoS/relpri |
220 | */ |
221 | __attribute__((const)) |
222 | pthread_priority_t |
223 | _pthread_priority_normalize_for_ipc(pthread_priority_t pp); |
224 | |
225 | /* |
226 | * Keep the flags from base_pp and return the priority with the maximum priority |
227 | * of base_pp and _pthread_priority_make_from_thread_qos(qos, 0, 0) |
228 | */ |
229 | __attribute__((const)) |
230 | pthread_priority_t |
231 | _pthread_priority_combine(pthread_priority_t base_pp, thread_qos_t qos); |
232 | |
233 | #endif // KERNEL |
234 | #endif // __PTHREAD_EXPOSE_INTERNALS__ |
235 | #endif // PRIVATE |
236 | #endif // _PTHREAD_PRIORITY_PRIVATE_H_ |
237 | |