]> git.saurik.com Git - apple/libdispatch.git/blob - src/shims/priority.h
libdispatch-913.30.4.tar.gz
[apple/libdispatch.git] / src / shims / priority.h
1 /*
2 * Copyright (c) 2008-2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20
21 /*
22 * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
23 * which are subject to change in future releases of Mac OS X. Any applications
24 * relying on these interfaces WILL break.
25 */
26
27 #ifndef __DISPATCH_SHIMS_PRIORITY__
28 #define __DISPATCH_SHIMS_PRIORITY__
29
30 #if HAVE_PTHREAD_QOS_H && __has_include(<pthread/qos_private.h>)
31 #include <pthread/qos.h>
32 #include <pthread/qos_private.h>
33 #ifndef _PTHREAD_PRIORITY_OVERCOMMIT_FLAG
34 #define _PTHREAD_PRIORITY_OVERCOMMIT_FLAG 0x80000000
35 #endif
36 #ifndef _PTHREAD_PRIORITY_SCHED_PRI_FLAG
37 #define _PTHREAD_PRIORITY_SCHED_PRI_FLAG 0x20000000
38 #endif
39 #ifndef _PTHREAD_PRIORITY_DEFAULTQUEUE_FLAG
40 #define _PTHREAD_PRIORITY_DEFAULTQUEUE_FLAG 0x04000000
41 #endif
42 #ifndef _PTHREAD_PRIORITY_EVENT_MANAGER_FLAG
43 #define _PTHREAD_PRIORITY_EVENT_MANAGER_FLAG 0x02000000
44 #endif
45 #ifndef _PTHREAD_PRIORITY_NEEDS_UNBIND_FLAG
46 #define _PTHREAD_PRIORITY_NEEDS_UNBIND_FLAG 0x01000000
47 #endif
48 #else // HAVE_PTHREAD_QOS_H
49 OS_ENUM(qos_class, unsigned int,
50 QOS_CLASS_USER_INTERACTIVE = 0x21,
51 QOS_CLASS_USER_INITIATED = 0x19,
52 QOS_CLASS_DEFAULT = 0x15,
53 QOS_CLASS_UTILITY = 0x11,
54 QOS_CLASS_BACKGROUND = 0x09,
55 QOS_CLASS_MAINTENANCE = 0x05,
56 QOS_CLASS_UNSPECIFIED = 0x00,
57 );
58 typedef unsigned long pthread_priority_t;
59 #define QOS_MIN_RELATIVE_PRIORITY (-15)
60 #define _PTHREAD_PRIORITY_FLAGS_MASK (~0xffffff)
61 #define _PTHREAD_PRIORITY_QOS_CLASS_MASK 0x00ffff00
62 #define _PTHREAD_PRIORITY_QOS_CLASS_SHIFT (8ull)
63 #define _PTHREAD_PRIORITY_PRIORITY_MASK 0x000000ff
64 #define _PTHREAD_PRIORITY_OVERCOMMIT_FLAG 0x80000000
65 #define _PTHREAD_PRIORITY_SCHED_PRI_FLAG 0x20000000
66 #define _PTHREAD_PRIORITY_DEFAULTQUEUE_FLAG 0x04000000
67 #define _PTHREAD_PRIORITY_EVENT_MANAGER_FLAG 0x02000000
68 #define _PTHREAD_PRIORITY_NEEDS_UNBIND_FLAG 0x01000000
69 #define _PTHREAD_PRIORITY_ENFORCE_FLAG 0x10000000
70
71 #endif // HAVE_PTHREAD_QOS_H
72
73 typedef uint32_t dispatch_qos_t;
74 typedef uint32_t dispatch_priority_t;
75 typedef uint32_t dispatch_priority_t;
76 typedef uint16_t dispatch_priority_requested_t;
77
78 #define DISPATCH_QOS_UNSPECIFIED ((dispatch_qos_t)0)
79 #define DISPATCH_QOS_MAINTENANCE ((dispatch_qos_t)1)
80 #define DISPATCH_QOS_BACKGROUND ((dispatch_qos_t)2)
81 #define DISPATCH_QOS_UTILITY ((dispatch_qos_t)3)
82 #define DISPATCH_QOS_DEFAULT ((dispatch_qos_t)4)
83 #define DISPATCH_QOS_USER_INITIATED ((dispatch_qos_t)5)
84 #define DISPATCH_QOS_USER_INTERACTIVE ((dispatch_qos_t)6)
85 #define DISPATCH_QOS_MAX DISPATCH_QOS_USER_INTERACTIVE
86 #define DISPATCH_QOS_SATURATED ((dispatch_qos_t)15)
87
88 #define DISPATCH_PRIORITY_RELPRI_MASK ((dispatch_priority_t)0x000000ff)
89 #define DISPATCH_PRIORITY_RELPRI_SHIFT 0
90 #define DISPATCH_PRIORITY_QOS_MASK ((dispatch_priority_t)0x0000ff00)
91 #define DISPATCH_PRIORITY_QOS_SHIFT 8
92 #define DISPATCH_PRIORITY_REQUESTED_MASK ((dispatch_priority_t)0x0000ffff)
93 #define DISPATCH_PRIORITY_OVERRIDE_MASK ((dispatch_priority_t)0x00ff0000)
94 #define DISPATCH_PRIORITY_OVERRIDE_SHIFT 16
95 #define DISPATCH_PRIORITY_FLAGS_MASK ((dispatch_priority_t)0xff000000)
96
97 #define DISPATCH_PRIORITY_SATURATED_OVERRIDE ((dispatch_priority_t)0x000f0000)
98
99 #define DISPATCH_PRIORITY_FLAG_OVERCOMMIT ((dispatch_priority_t)0x80000000) // _PTHREAD_PRIORITY_OVERCOMMIT_FLAG
100 #define DISPATCH_PRIORITY_FLAG_DEFAULTQUEUE ((dispatch_priority_t)0x04000000) // _PTHREAD_PRIORITY_DEFAULTQUEUE_FLAG
101 #define DISPATCH_PRIORITY_FLAG_MANAGER ((dispatch_priority_t)0x02000000) // _PTHREAD_PRIORITY_EVENT_MANAGER_FLAG
102 #define DISPATCH_PRIORITY_PTHREAD_PRIORITY_FLAGS_MASK \
103 (DISPATCH_PRIORITY_FLAG_OVERCOMMIT | DISPATCH_PRIORITY_FLAG_DEFAULTQUEUE | \
104 DISPATCH_PRIORITY_FLAG_MANAGER)
105
106 // not passed to pthread
107 #define DISPATCH_PRIORITY_FLAG_INHERIT ((dispatch_priority_t)0x40000000) // _PTHREAD_PRIORITY_INHERIT_FLAG
108 #define DISPATCH_PRIORITY_FLAG_ENFORCE ((dispatch_priority_t)0x10000000) // _PTHREAD_PRIORITY_ENFORCE_FLAG
109 #define DISPATCH_PRIORITY_FLAG_ROOTQUEUE ((dispatch_priority_t)0x20000000) // _PTHREAD_PRIORITY_ROOTQUEUE_FLAG
110
111 #pragma mark dispatch_qos
112
113 DISPATCH_ALWAYS_INLINE
114 static inline dispatch_qos_t
115 _dispatch_qos_from_qos_class(qos_class_t cls)
116 {
117 switch ((unsigned int)cls) {
118 case QOS_CLASS_USER_INTERACTIVE: return DISPATCH_QOS_USER_INTERACTIVE;
119 case QOS_CLASS_USER_INITIATED: return DISPATCH_QOS_USER_INITIATED;
120 case QOS_CLASS_DEFAULT: return DISPATCH_QOS_DEFAULT;
121 case QOS_CLASS_UTILITY: return DISPATCH_QOS_UTILITY;
122 case QOS_CLASS_BACKGROUND: return DISPATCH_QOS_BACKGROUND;
123 case QOS_CLASS_MAINTENANCE: return DISPATCH_QOS_MAINTENANCE;
124 default: return DISPATCH_QOS_UNSPECIFIED;
125 }
126 }
127
128 DISPATCH_ALWAYS_INLINE
129 static inline qos_class_t
130 _dispatch_qos_to_qos_class(dispatch_qos_t qos)
131 {
132 switch (qos) {
133 case DISPATCH_QOS_USER_INTERACTIVE: return QOS_CLASS_USER_INTERACTIVE;
134 case DISPATCH_QOS_USER_INITIATED: return QOS_CLASS_USER_INITIATED;
135 case DISPATCH_QOS_DEFAULT: return QOS_CLASS_DEFAULT;
136 case DISPATCH_QOS_UTILITY: return QOS_CLASS_UTILITY;
137 case DISPATCH_QOS_BACKGROUND: return QOS_CLASS_BACKGROUND;
138 case DISPATCH_QOS_MAINTENANCE: return (qos_class_t)QOS_CLASS_MAINTENANCE;
139 default: return QOS_CLASS_UNSPECIFIED;
140 }
141 }
142
143 DISPATCH_ALWAYS_INLINE
144 static inline dispatch_qos_t
145 _dispatch_qos_from_queue_priority(long priority)
146 {
147 switch (priority) {
148 case DISPATCH_QUEUE_PRIORITY_BACKGROUND: return DISPATCH_QOS_BACKGROUND;
149 case DISPATCH_QUEUE_PRIORITY_NON_INTERACTIVE: return DISPATCH_QOS_UTILITY;
150 case DISPATCH_QUEUE_PRIORITY_LOW: return DISPATCH_QOS_UTILITY;
151 case DISPATCH_QUEUE_PRIORITY_DEFAULT: return DISPATCH_QOS_DEFAULT;
152 case DISPATCH_QUEUE_PRIORITY_HIGH: return DISPATCH_QOS_USER_INITIATED;
153 default: return _dispatch_qos_from_qos_class((qos_class_t)priority);
154 }
155 }
156
157 DISPATCH_ALWAYS_INLINE
158 static inline dispatch_qos_t
159 _dispatch_qos_from_pp(pthread_priority_t pp)
160 {
161 pp &= _PTHREAD_PRIORITY_QOS_CLASS_MASK;
162 pp >>= _PTHREAD_PRIORITY_QOS_CLASS_SHIFT;
163 return (dispatch_qos_t)__builtin_ffs((int)pp);
164 }
165
166 DISPATCH_ALWAYS_INLINE
167 static inline pthread_priority_t
168 _dispatch_qos_to_pp(dispatch_qos_t qos)
169 {
170 pthread_priority_t pp;
171 pp = 1ul << ((qos - 1) + _PTHREAD_PRIORITY_QOS_CLASS_SHIFT);
172 return pp | _PTHREAD_PRIORITY_PRIORITY_MASK;
173 }
174
175 // including maintenance
176 DISPATCH_ALWAYS_INLINE
177 static inline bool
178 _dispatch_qos_is_background(dispatch_qos_t qos)
179 {
180 return qos && qos <= DISPATCH_QOS_BACKGROUND;
181 }
182
183 #pragma mark dispatch_priority
184
185 #define _dispatch_priority_make(qos, relpri) \
186 (qos ? ((((qos) << DISPATCH_PRIORITY_QOS_SHIFT) & DISPATCH_PRIORITY_QOS_MASK) | \
187 ((dispatch_priority_t)(relpri - 1) & DISPATCH_PRIORITY_RELPRI_MASK)) : 0)
188
189 DISPATCH_ALWAYS_INLINE
190 static inline dispatch_priority_t
191 _dispatch_priority_with_override_qos(dispatch_priority_t pri,
192 dispatch_qos_t oqos)
193 {
194 pri &= ~DISPATCH_PRIORITY_OVERRIDE_MASK;
195 pri |= oqos << DISPATCH_PRIORITY_OVERRIDE_SHIFT;
196 return pri;
197 }
198
199 DISPATCH_ALWAYS_INLINE
200 static inline int
201 _dispatch_priority_relpri(dispatch_priority_t dbp)
202 {
203 if (dbp & DISPATCH_PRIORITY_QOS_MASK) {
204 return (int8_t)(dbp & DISPATCH_PRIORITY_RELPRI_MASK) + 1;
205 }
206 return 0;
207 }
208
209 DISPATCH_ALWAYS_INLINE
210 static inline dispatch_qos_t
211 _dispatch_priority_qos(dispatch_priority_t dbp)
212 {
213 dbp &= DISPATCH_PRIORITY_QOS_MASK;
214 return dbp >> DISPATCH_PRIORITY_QOS_SHIFT;
215 }
216
217 DISPATCH_ALWAYS_INLINE
218 static inline dispatch_qos_t
219 _dispatch_priority_override_qos(dispatch_priority_t dbp)
220 {
221 dbp &= DISPATCH_PRIORITY_OVERRIDE_MASK;
222 return dbp >> DISPATCH_PRIORITY_OVERRIDE_SHIFT;
223 }
224
225 DISPATCH_ALWAYS_INLINE
226 static inline dispatch_priority_t
227 _dispatch_priority_from_pp_impl(pthread_priority_t pp, bool keep_flags)
228 {
229 dispatch_assert(!(pp & _PTHREAD_PRIORITY_SCHED_PRI_FLAG));
230
231 dispatch_priority_t dbp;
232 if (keep_flags) {
233 dbp = pp & (DISPATCH_PRIORITY_PTHREAD_PRIORITY_FLAGS_MASK |
234 DISPATCH_PRIORITY_RELPRI_MASK);
235 } else {
236 dbp = pp & DISPATCH_PRIORITY_RELPRI_MASK;
237 }
238
239 dbp |= _dispatch_qos_from_pp(pp) << DISPATCH_PRIORITY_QOS_SHIFT;
240 return dbp;
241 }
242 #define _dispatch_priority_from_pp(pp) \
243 _dispatch_priority_from_pp_impl(pp, true)
244 #define _dispatch_priority_from_pp_strip_flags(pp) \
245 _dispatch_priority_from_pp_impl(pp, false)
246
247 DISPATCH_ALWAYS_INLINE
248 static inline pthread_priority_t
249 _dispatch_priority_to_pp_impl(dispatch_priority_t dbp, bool keep_flags)
250 {
251 pthread_priority_t pp;
252 if (keep_flags) {
253 pp = dbp & (DISPATCH_PRIORITY_PTHREAD_PRIORITY_FLAGS_MASK |
254 DISPATCH_PRIORITY_RELPRI_MASK);
255 } else {
256 pp = dbp & DISPATCH_PRIORITY_RELPRI_MASK;
257 }
258 dispatch_qos_t qos = _dispatch_priority_qos(dbp);
259 if (qos) {
260 pp |= (1ul << ((qos - 1) + _PTHREAD_PRIORITY_QOS_CLASS_SHIFT));
261 }
262 return pp;
263 }
264 #define _dispatch_priority_to_pp(pp) \
265 _dispatch_priority_to_pp_impl(pp, true)
266 #define _dispatch_priority_to_pp_strip_flags(pp) \
267 _dispatch_priority_to_pp_impl(pp, false)
268
269 #endif // __DISPATCH_SHIMS_PRIORITY__