]>
Commit | Line | Data |
---|---|---|
d9a64523 A |
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 | ||
0a7de745 A |
96 | #define _PTHREAD_PRIORITY_FLAGS_MASK 0xff000000 |
97 | #define _PTHREAD_PRIORITY_FLAGS_SHIFT (24ull) | |
d9a64523 | 98 | |
0a7de745 A |
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 | |
d9a64523 | 110 | |
0a7de745 A |
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 */ | |
d9a64523 | 117 | |
0a7de745 A |
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) | |
d9a64523 | 121 | |
0a7de745 A |
122 | #define _PTHREAD_PRIORITY_PRIORITY_MASK 0x000000ff |
123 | #define _PTHREAD_PRIORITY_PRIORITY_SHIFT (0) | |
d9a64523 A |
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 | | |
0a7de745 A |
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; | |
d9a64523 A |
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, | |
0a7de745 | 151 | unsigned long flags) |
d9a64523 A |
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 | ||
cb323159 A |
182 | __attribute__((always_inline, const)) |
183 | static inline thread_qos_t | |
184 | _pthread_priority_thread_qos_fast(pthread_priority_t pp) | |
185 | { | |
186 | pp &= _PTHREAD_PRIORITY_QOS_CLASS_MASK; | |
187 | pp >>= _PTHREAD_PRIORITY_QOS_CLASS_SHIFT; | |
188 | return (thread_qos_t)__builtin_ffs((int)pp); | |
189 | } | |
190 | ||
d9a64523 A |
191 | __attribute__((always_inline, const)) |
192 | static inline thread_qos_t | |
193 | _pthread_priority_thread_qos(pthread_priority_t pp) | |
194 | { | |
195 | if (_pthread_priority_has_qos(pp)) { | |
cb323159 | 196 | return _pthread_priority_thread_qos_fast(pp); |
d9a64523 A |
197 | } |
198 | return THREAD_QOS_UNSPECIFIED; | |
199 | } | |
200 | ||
201 | __attribute__((always_inline, const)) | |
202 | static inline int | |
203 | _pthread_priority_relpri(pthread_priority_t pp) | |
204 | { | |
205 | if (_pthread_priority_has_qos(pp)) { | |
206 | pp &= _PTHREAD_PRIORITY_PRIORITY_MASK; | |
207 | pp >>= _PTHREAD_PRIORITY_PRIORITY_SHIFT; | |
208 | return (int8_t)pp + 1; | |
209 | } | |
210 | return 0; | |
211 | } | |
212 | ||
213 | #if KERNEL | |
214 | // Interfaces only used by the kernel and not implemented in userspace. | |
215 | ||
216 | /* | |
217 | * Keep managerness, overcomitness and fallback, discard other flags. | |
218 | * Normalize and validate QoS/relpri | |
219 | */ | |
220 | __attribute__((const)) | |
221 | pthread_priority_t | |
222 | _pthread_priority_normalize(pthread_priority_t pp); | |
223 | ||
224 | /* | |
225 | * Keep managerness, discard other flags. | |
226 | * Normalize and validate QoS/relpri | |
227 | */ | |
228 | __attribute__((const)) | |
229 | pthread_priority_t | |
230 | _pthread_priority_normalize_for_ipc(pthread_priority_t pp); | |
231 | ||
232 | /* | |
233 | * Keep the flags from base_pp and return the priority with the maximum priority | |
234 | * of base_pp and _pthread_priority_make_from_thread_qos(qos, 0, 0) | |
235 | */ | |
236 | __attribute__((const)) | |
237 | pthread_priority_t | |
238 | _pthread_priority_combine(pthread_priority_t base_pp, thread_qos_t qos); | |
239 | ||
240 | #endif // KERNEL | |
241 | #endif // __PTHREAD_EXPOSE_INTERNALS__ | |
242 | #endif // PRIVATE | |
243 | #endif // _PTHREAD_PRIORITY_PRIVATE_H_ |