2 * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
21 // Contains exported global data and initialization & other routines that must
22 // only exist once in the shared library even when resolvers are used.
27 #include "protocolServer.h"
31 #pragma mark dispatch_init
33 #if USE_LIBDISPATCH_INIT_CONSTRUCTOR
34 DISPATCH_NOTHROW
__attribute__((constructor
))
36 _libdispatch_init(void);
38 DISPATCH_EXPORT DISPATCH_NOTHROW
40 _libdispatch_init(void)
46 DISPATCH_EXPORT DISPATCH_NOTHROW
48 dispatch_atfork_prepare(void)
50 _os_object_atfork_prepare();
53 DISPATCH_EXPORT DISPATCH_NOTHROW
55 dispatch_atfork_parent(void)
57 _os_object_atfork_parent();
60 DISPATCH_EXPORT DISPATCH_NOTHROW
62 dispatch_atfork_child(void)
64 _os_object_atfork_child();
65 _voucher_atfork_child();
66 if (_dispatch_is_multithreaded_inline()) {
67 _dispatch_child_of_unsafe_fork
= true;
69 _dispatch_queue_atfork_child();
70 // clear the _PROHIBIT and _MULTITHREADED bits if set
71 _dispatch_unsafe_fork
= 0;
75 #pragma mark dispatch_globals
77 DISPATCH_HIDE_SYMBOL(dispatch_assert_queue
, 10.12, 10.0, 10.0, 3.0);
78 DISPATCH_HIDE_SYMBOL(dispatch_assert_queue_not
, 10.12, 10.0, 10.0, 3.0);
79 DISPATCH_HIDE_SYMBOL(dispatch_queue_create_with_target
, 10.12, 10.0, 10.0, 3.0);
81 #if DISPATCH_COCOA_COMPAT
82 void *(*_dispatch_begin_NSAutoReleasePool
)(void);
83 void (*_dispatch_end_NSAutoReleasePool
)(void *);
86 #if DISPATCH_USE_THREAD_LOCAL_STORAGE
87 __thread
struct dispatch_tsd __dispatch_tsd
;
88 pthread_key_t __dispatch_tsd_key
;
89 #elif !DISPATCH_USE_DIRECT_TSD
90 pthread_key_t dispatch_queue_key
;
91 pthread_key_t dispatch_frame_key
;
92 pthread_key_t dispatch_cache_key
;
93 pthread_key_t dispatch_context_key
;
94 pthread_key_t dispatch_pthread_root_queue_observer_hooks_key
;
95 pthread_key_t dispatch_defaultpriority_key
;
96 #if DISPATCH_INTROSPECTION
97 pthread_key_t dispatch_introspection_key
;
98 #elif DISPATCH_PERF_MON
99 pthread_key_t dispatch_bcounter_key
;
101 pthread_key_t dispatch_sema4_key
;
102 pthread_key_t dispatch_voucher_key
;
103 pthread_key_t dispatch_deferred_items_key
;
104 #endif // !DISPATCH_USE_DIRECT_TSD && !DISPATCH_USE_THREAD_LOCAL_STORAGE
106 #if VOUCHER_USE_MACH_VOUCHER
107 dispatch_once_t _voucher_task_mach_voucher_pred
;
108 mach_voucher_t _voucher_task_mach_voucher
;
109 #if !VOUCHER_USE_EMPTY_MACH_BASE_VOUCHER
110 mach_voucher_t _voucher_default_task_mach_voucher
;
112 dispatch_once_t _firehose_task_buffer_pred
;
113 firehose_buffer_t _firehose_task_buffer
;
114 const uint32_t _firehose_spi_version
= OS_FIREHOSE_SPI_VERSION
;
115 uint64_t _voucher_unique_pid
;
116 voucher_activity_hooks_t _voucher_libtrace_hooks
;
117 dispatch_mach_t _voucher_activity_debug_channel
;
119 #if HAVE_PTHREAD_WORKQUEUE_QOS && DISPATCH_DEBUG
120 int _dispatch_set_qos_class_enabled
;
122 #if DISPATCH_USE_KEVENT_WORKQUEUE && DISPATCH_USE_MGR_THREAD
123 int _dispatch_kevent_workqueue_enabled
;
125 #if DISPATCH_USE_EVFILT_MACHPORT_DIRECT && \
126 DISPATCH_EVFILT_MACHPORT_PORTSET_FALLBACK
127 int _dispatch_evfilt_machport_direct_enabled
;
130 DISPATCH_HW_CONFIG();
131 uint8_t _dispatch_unsafe_fork
;
132 bool _dispatch_child_of_unsafe_fork
;
133 #if DISPATCH_USE_MEMORYPRESSURE_SOURCE
134 bool _dispatch_memory_warn
;
135 int _dispatch_continuation_cache_limit
= DISPATCH_CONTINUATION_CACHE_LIMIT
;
140 _dispatch_is_multithreaded(void)
142 return _dispatch_is_multithreaded_inline();
147 _dispatch_is_fork_of_multithreaded_parent(void)
149 return _dispatch_child_of_unsafe_fork
;
154 _dispatch_fork_becomes_unsafe_slow(void)
156 uint8_t value
= os_atomic_or(&_dispatch_unsafe_fork
,
157 _DISPATCH_UNSAFE_FORK_MULTITHREADED
, relaxed
);
158 if (value
& _DISPATCH_UNSAFE_FORK_PROHIBIT
) {
159 DISPATCH_CLIENT_CRASH(0, "Transition to multithreaded is prohibited");
165 _dispatch_prohibit_transition_to_multithreaded(bool prohibit
)
168 uint8_t value
= os_atomic_or(&_dispatch_unsafe_fork
,
169 _DISPATCH_UNSAFE_FORK_PROHIBIT
, relaxed
);
170 if (value
& _DISPATCH_UNSAFE_FORK_MULTITHREADED
) {
171 DISPATCH_CLIENT_CRASH(0, "The executable is already multithreaded");
174 os_atomic_and(&_dispatch_unsafe_fork
,
175 (uint8_t)~_DISPATCH_UNSAFE_FORK_PROHIBIT
, relaxed
);
179 const struct dispatch_queue_offsets_s dispatch_queue_offsets
= {
181 .dqo_label
= offsetof(struct dispatch_queue_s
, dq_label
),
182 .dqo_label_size
= sizeof(((dispatch_queue_t
)NULL
)->dq_label
),
185 .dqo_serialnum
= offsetof(struct dispatch_queue_s
, dq_serialnum
),
186 .dqo_serialnum_size
= sizeof(((dispatch_queue_t
)NULL
)->dq_serialnum
),
187 .dqo_width
= offsetof(struct dispatch_queue_s
, dq_width
),
188 .dqo_width_size
= sizeof(((dispatch_queue_t
)NULL
)->dq_width
),
190 .dqo_running_size
= 0,
191 .dqo_suspend_cnt
= 0,
192 .dqo_suspend_cnt_size
= 0,
193 .dqo_target_queue
= offsetof(struct dispatch_queue_s
, do_targetq
),
194 .dqo_target_queue_size
= sizeof(((dispatch_queue_t
)NULL
)->do_targetq
),
195 .dqo_priority
= offsetof(struct dispatch_queue_s
, dq_priority
),
196 .dqo_priority_size
= sizeof(((dispatch_queue_t
)NULL
)->dq_priority
),
199 #if DISPATCH_USE_DIRECT_TSD
200 const struct dispatch_tsd_indexes_s dispatch_tsd_indexes
= {
202 .dti_queue_index
= dispatch_queue_key
,
203 .dti_voucher_index
= dispatch_voucher_key
,
204 .dti_qos_class_index
= dispatch_priority_key
,
206 #endif // DISPATCH_USE_DIRECT_TSD
208 // 6618342 Contact the team that owns the Instrument DTrace probe before
209 // renaming this symbol
210 DISPATCH_CACHELINE_ALIGN
211 struct dispatch_queue_s _dispatch_main_q
= {
212 DISPATCH_GLOBAL_OBJECT_HEADER(queue_main
),
213 #if !DISPATCH_USE_RESOLVERS
214 .do_targetq
= &_dispatch_root_queues
[
215 DISPATCH_ROOT_QUEUE_IDX_DEFAULT_QOS_OVERCOMMIT
],
217 .dq_state
= DISPATCH_QUEUE_STATE_INIT_VALUE(1),
218 .dq_label
= "com.apple.main-thread",
220 .dq_atomic_bits
= DQF_THREAD_BOUND
| DQF_CANNOT_TRYSYNC
,
221 .dq_override_voucher
= DISPATCH_NO_VOUCHER
,
226 #pragma mark dispatch_queue_attr_t
228 #define DISPATCH_QUEUE_ATTR_INIT(qos, prio, overcommit, freq, concurrent, inactive) \
230 DISPATCH_GLOBAL_OBJECT_HEADER(queue_attr), \
231 .dqa_qos_class = (qos), \
232 .dqa_relative_priority = (qos) ? (prio) : 0, \
233 .dqa_overcommit = _dispatch_queue_attr_overcommit_##overcommit, \
234 .dqa_autorelease_frequency = DISPATCH_AUTORELEASE_FREQUENCY_##freq, \
235 .dqa_concurrent = (concurrent), \
236 .dqa_inactive = (inactive), \
239 #define DISPATCH_QUEUE_ATTR_ACTIVE_INIT(qos, prio, overcommit, freq, concurrent) \
241 [DQA_INDEX_ACTIVE] = DISPATCH_QUEUE_ATTR_INIT(\
242 qos, prio, overcommit, freq, concurrent, false), \
243 [DQA_INDEX_INACTIVE] = DISPATCH_QUEUE_ATTR_INIT(\
244 qos, prio, overcommit, freq, concurrent, true), \
247 #define DISPATCH_QUEUE_ATTR_OVERCOMMIT_INIT(qos, prio, overcommit) \
249 [DQA_INDEX_AUTORELEASE_FREQUENCY_INHERIT][DQA_INDEX_CONCURRENT] = \
250 DISPATCH_QUEUE_ATTR_ACTIVE_INIT(qos, prio, overcommit, INHERIT, 1), \
251 [DQA_INDEX_AUTORELEASE_FREQUENCY_INHERIT][DQA_INDEX_SERIAL] = \
252 DISPATCH_QUEUE_ATTR_ACTIVE_INIT(qos, prio, overcommit, INHERIT, 0), \
253 [DQA_INDEX_AUTORELEASE_FREQUENCY_WORK_ITEM][DQA_INDEX_CONCURRENT] = \
254 DISPATCH_QUEUE_ATTR_ACTIVE_INIT(qos, prio, overcommit, WORK_ITEM, 1), \
255 [DQA_INDEX_AUTORELEASE_FREQUENCY_WORK_ITEM][DQA_INDEX_SERIAL] = \
256 DISPATCH_QUEUE_ATTR_ACTIVE_INIT(qos, prio, overcommit, WORK_ITEM, 0), \
257 [DQA_INDEX_AUTORELEASE_FREQUENCY_NEVER][DQA_INDEX_CONCURRENT] = \
258 DISPATCH_QUEUE_ATTR_ACTIVE_INIT(qos, prio, overcommit, NEVER, 1), \
259 [DQA_INDEX_AUTORELEASE_FREQUENCY_NEVER][DQA_INDEX_SERIAL] = \
260 DISPATCH_QUEUE_ATTR_ACTIVE_INIT(qos, prio, overcommit, NEVER, 0), \
263 #define DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, prio) \
265 [DQA_INDEX_UNSPECIFIED_OVERCOMMIT] = \
266 DISPATCH_QUEUE_ATTR_OVERCOMMIT_INIT(qos, -(prio), unspecified), \
267 [DQA_INDEX_NON_OVERCOMMIT] = \
268 DISPATCH_QUEUE_ATTR_OVERCOMMIT_INIT(qos, -(prio), disabled), \
269 [DQA_INDEX_OVERCOMMIT] = \
270 DISPATCH_QUEUE_ATTR_OVERCOMMIT_INIT(qos, -(prio), enabled), \
273 #define DISPATCH_QUEUE_ATTR_PRIO_INIT(qos) \
275 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 0), \
276 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 1), \
277 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 2), \
278 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 3), \
279 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 4), \
280 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 5), \
281 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 6), \
282 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 7), \
283 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 8), \
284 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 9), \
285 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 10), \
286 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 11), \
287 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 12), \
288 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 13), \
289 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 14), \
290 DISPATCH_QUEUE_ATTR_PRIO_INITIALIZER(qos, 15), \
293 #define DISPATCH_QUEUE_ATTR_QOS_INITIALIZER(qos) \
294 [DQA_INDEX_QOS_CLASS_##qos] = \
295 DISPATCH_QUEUE_ATTR_PRIO_INIT(_DISPATCH_QOS_CLASS_##qos)
297 // DISPATCH_QUEUE_CONCURRENT resp. _dispatch_queue_attr_concurrent is aliased
298 // to array member [0][0][0][0][0][0] and their properties must match!
299 const struct dispatch_queue_attr_s _dispatch_queue_attrs
[]
300 [DISPATCH_QUEUE_ATTR_PRIO_COUNT
]
301 [DISPATCH_QUEUE_ATTR_OVERCOMMIT_COUNT
]
302 [DISPATCH_QUEUE_ATTR_AUTORELEASE_FREQUENCY_COUNT
]
303 [DISPATCH_QUEUE_ATTR_CONCURRENCY_COUNT
]
304 [DISPATCH_QUEUE_ATTR_INACTIVE_COUNT
] = {
305 DISPATCH_QUEUE_ATTR_QOS_INITIALIZER(UNSPECIFIED
),
306 DISPATCH_QUEUE_ATTR_QOS_INITIALIZER(MAINTENANCE
),
307 DISPATCH_QUEUE_ATTR_QOS_INITIALIZER(BACKGROUND
),
308 DISPATCH_QUEUE_ATTR_QOS_INITIALIZER(UTILITY
),
309 DISPATCH_QUEUE_ATTR_QOS_INITIALIZER(DEFAULT
),
310 DISPATCH_QUEUE_ATTR_QOS_INITIALIZER(USER_INITIATED
),
311 DISPATCH_QUEUE_ATTR_QOS_INITIALIZER(USER_INTERACTIVE
),
314 #if DISPATCH_VARIANT_STATIC
315 // <rdar://problem/16778703>
316 struct dispatch_queue_attr_s _dispatch_queue_attr_concurrent
=
317 DISPATCH_QUEUE_ATTR_INIT(_DISPATCH_QOS_CLASS_UNSPECIFIED
, 0,
318 unspecified
, INHERIT
, 1, false);
319 #endif // DISPATCH_VARIANT_STATIC
321 // _dispatch_queue_attr_concurrent is aliased using libdispatch.aliases
322 // and the -alias_list linker option on Darwin but needs to be done manually
323 // for other platforms.
325 extern struct dispatch_queue_attr_s _dispatch_queue_attr_concurrent
326 __attribute__((__alias__("_dispatch_queue_attrs")));
330 #pragma mark dispatch_vtables
332 DISPATCH_VTABLE_INSTANCE(semaphore
,
333 .do_type
= DISPATCH_SEMAPHORE_TYPE
,
334 .do_kind
= "semaphore",
335 .do_dispose
= _dispatch_semaphore_dispose
,
336 .do_debug
= _dispatch_semaphore_debug
,
339 DISPATCH_VTABLE_INSTANCE(group
,
340 .do_type
= DISPATCH_GROUP_TYPE
,
342 .do_dispose
= _dispatch_group_dispose
,
343 .do_debug
= _dispatch_group_debug
,
346 DISPATCH_VTABLE_INSTANCE(queue
,
347 .do_type
= DISPATCH_QUEUE_LEGACY_TYPE
,
349 .do_dispose
= _dispatch_queue_dispose
,
350 .do_suspend
= _dispatch_queue_suspend
,
351 .do_resume
= _dispatch_queue_resume
,
352 .do_invoke
= _dispatch_queue_invoke
,
353 .do_wakeup
= _dispatch_queue_wakeup
,
354 .do_debug
= dispatch_queue_debug
,
355 .do_set_targetq
= _dispatch_queue_set_target_queue
,
358 DISPATCH_VTABLE_SUBCLASS_INSTANCE(queue_serial
, queue
,
359 .do_type
= DISPATCH_QUEUE_SERIAL_TYPE
,
360 .do_kind
= "serial-queue",
361 .do_dispose
= _dispatch_queue_dispose
,
362 .do_suspend
= _dispatch_queue_suspend
,
363 .do_resume
= _dispatch_queue_resume
,
364 .do_finalize_activation
= _dispatch_queue_finalize_activation
,
365 .do_invoke
= _dispatch_queue_invoke
,
366 .do_wakeup
= _dispatch_queue_wakeup
,
367 .do_debug
= dispatch_queue_debug
,
368 .do_set_targetq
= _dispatch_queue_set_target_queue
,
371 DISPATCH_VTABLE_SUBCLASS_INSTANCE(queue_concurrent
, queue
,
372 .do_type
= DISPATCH_QUEUE_CONCURRENT_TYPE
,
373 .do_kind
= "concurrent-queue",
374 .do_dispose
= _dispatch_queue_dispose
,
375 .do_suspend
= _dispatch_queue_suspend
,
376 .do_resume
= _dispatch_queue_resume
,
377 .do_finalize_activation
= _dispatch_queue_finalize_activation
,
378 .do_invoke
= _dispatch_queue_invoke
,
379 .do_wakeup
= _dispatch_queue_wakeup
,
380 .do_debug
= dispatch_queue_debug
,
381 .do_set_targetq
= _dispatch_queue_set_target_queue
,
385 DISPATCH_VTABLE_SUBCLASS_INSTANCE(queue_root
, queue
,
386 .do_type
= DISPATCH_QUEUE_GLOBAL_ROOT_TYPE
,
387 .do_kind
= "global-queue",
388 .do_dispose
= _dispatch_pthread_root_queue_dispose
,
389 .do_wakeup
= _dispatch_root_queue_wakeup
,
390 .do_debug
= dispatch_queue_debug
,
393 DISPATCH_VTABLE_SUBCLASS_INSTANCE(queue_main
, queue
,
394 .do_type
= DISPATCH_QUEUE_SERIAL_TYPE
,
395 .do_kind
= "main-queue",
396 .do_dispose
= _dispatch_queue_dispose
,
397 .do_invoke
= _dispatch_queue_invoke
,
398 .do_wakeup
= _dispatch_main_queue_wakeup
,
399 .do_debug
= dispatch_queue_debug
,
402 DISPATCH_VTABLE_SUBCLASS_INSTANCE(queue_runloop
, queue
,
403 .do_type
= DISPATCH_QUEUE_RUNLOOP_TYPE
,
404 .do_kind
= "runloop-queue",
405 .do_dispose
= _dispatch_runloop_queue_dispose
,
406 .do_invoke
= _dispatch_queue_invoke
,
407 .do_wakeup
= _dispatch_runloop_queue_wakeup
,
408 .do_debug
= dispatch_queue_debug
,
411 DISPATCH_VTABLE_SUBCLASS_INSTANCE(queue_mgr
, queue
,
412 .do_type
= DISPATCH_QUEUE_MGR_TYPE
,
413 .do_kind
= "mgr-queue",
414 .do_invoke
= _dispatch_mgr_thread
,
415 .do_wakeup
= _dispatch_mgr_queue_wakeup
,
416 .do_debug
= dispatch_queue_debug
,
419 DISPATCH_VTABLE_INSTANCE(queue_specific_queue
,
420 .do_type
= DISPATCH_QUEUE_SPECIFIC_TYPE
,
421 .do_kind
= "queue-context",
422 .do_dispose
= _dispatch_queue_specific_queue_dispose
,
423 .do_invoke
= (void *)_dispatch_queue_invoke
,
424 .do_wakeup
= (void *)_dispatch_queue_wakeup
,
425 .do_debug
= (void *)dispatch_queue_debug
,
428 DISPATCH_VTABLE_INSTANCE(queue_attr
,
429 .do_type
= DISPATCH_QUEUE_ATTR_TYPE
,
430 .do_kind
= "queue-attr",
433 DISPATCH_VTABLE_INSTANCE(source
,
434 .do_type
= DISPATCH_SOURCE_KEVENT_TYPE
,
435 .do_kind
= "kevent-source",
436 .do_dispose
= _dispatch_source_dispose
,
437 .do_suspend
= (void *)_dispatch_queue_suspend
,
438 .do_resume
= (void *)_dispatch_queue_resume
,
439 .do_finalize_activation
= _dispatch_source_finalize_activation
,
440 .do_invoke
= _dispatch_source_invoke
,
441 .do_wakeup
= _dispatch_source_wakeup
,
442 .do_debug
= _dispatch_source_debug
,
443 .do_set_targetq
= (void *)_dispatch_queue_set_target_queue
,
447 DISPATCH_VTABLE_INSTANCE(mach
,
448 .do_type
= DISPATCH_MACH_CHANNEL_TYPE
,
449 .do_kind
= "mach-channel",
450 .do_dispose
= _dispatch_mach_dispose
,
451 .do_suspend
= (void *)_dispatch_queue_suspend
,
452 .do_resume
= (void *)_dispatch_queue_resume
,
453 .do_finalize_activation
= _dispatch_mach_finalize_activation
,
454 .do_invoke
= _dispatch_mach_invoke
,
455 .do_wakeup
= _dispatch_mach_wakeup
,
456 .do_debug
= _dispatch_mach_debug
,
457 .do_set_targetq
= (void *)_dispatch_queue_set_target_queue
,
460 DISPATCH_VTABLE_INSTANCE(mach_msg
,
461 .do_type
= DISPATCH_MACH_MSG_TYPE
,
462 .do_kind
= "mach-msg",
463 .do_dispose
= _dispatch_mach_msg_dispose
,
464 .do_invoke
= _dispatch_mach_msg_invoke
,
465 .do_debug
= _dispatch_mach_msg_debug
,
469 #if !DISPATCH_DATA_IS_BRIDGED_TO_NSDATA
470 DISPATCH_VTABLE_INSTANCE(data
,
471 .do_type
= DISPATCH_DATA_TYPE
,
473 .do_dispose
= _dispatch_data_dispose
,
474 .do_debug
= _dispatch_data_debug
,
478 DISPATCH_VTABLE_INSTANCE(io
,
479 .do_type
= DISPATCH_IO_TYPE
,
480 .do_kind
= "channel",
481 .do_dispose
= _dispatch_io_dispose
,
482 .do_debug
= _dispatch_io_debug
,
483 .do_set_targetq
= _dispatch_io_set_target_queue
,
486 DISPATCH_VTABLE_INSTANCE(operation
,
487 .do_type
= DISPATCH_OPERATION_TYPE
,
488 .do_kind
= "operation",
489 .do_dispose
= _dispatch_operation_dispose
,
490 .do_debug
= _dispatch_operation_debug
,
493 DISPATCH_VTABLE_INSTANCE(disk
,
494 .do_type
= DISPATCH_DISK_TYPE
,
496 .do_dispose
= _dispatch_disk_dispose
,
500 const struct dispatch_continuation_vtable_s _dispatch_continuation_vtables
[] = {
501 DC_VTABLE_ENTRY(ASYNC_REDIRECT
,
502 .do_kind
= "dc-redirect",
503 .do_invoke
= _dispatch_async_redirect_invoke
),
505 DC_VTABLE_ENTRY(MACH_SEND_BARRRIER_DRAIN
,
506 .do_kind
= "dc-mach-send-drain",
507 .do_invoke
= _dispatch_mach_send_barrier_drain_invoke
),
508 DC_VTABLE_ENTRY(MACH_SEND_BARRIER
,
509 .do_kind
= "dc-mach-send-barrier",
510 .do_invoke
= _dispatch_mach_barrier_invoke
),
511 DC_VTABLE_ENTRY(MACH_RECV_BARRIER
,
512 .do_kind
= "dc-mach-recv-barrier",
513 .do_invoke
= _dispatch_mach_barrier_invoke
),
515 #if HAVE_PTHREAD_WORKQUEUE_QOS
516 DC_VTABLE_ENTRY(OVERRIDE_STEALING
,
517 .do_kind
= "dc-override-stealing",
518 .do_invoke
= _dispatch_queue_override_invoke
),
519 DC_VTABLE_ENTRY(OVERRIDE_OWNING
,
520 .do_kind
= "dc-override-owning",
521 .do_invoke
= _dispatch_queue_override_invoke
),
526 _dispatch_vtable_init(void)
528 #if OS_OBJECT_HAVE_OBJC2
529 // ObjC classes and dispatch vtables are co-located via linker order and
530 // alias files, verify correct layout during initialization rdar://10640168
531 dispatch_assert((char*)&DISPATCH_CONCAT(_
,DISPATCH_CLASS(semaphore_vtable
))
532 - (char*)DISPATCH_VTABLE(semaphore
) ==
533 offsetof(struct dispatch_semaphore_vtable_s
, _os_obj_vtable
));
538 #pragma mark dispatch_bug
540 static char _dispatch_build
[16];
543 _dispatch_build_init(void *context DISPATCH_UNUSED
)
546 int mib
[] = { CTL_KERN
, KERN_OSVERSION
};
547 size_t bufsz
= sizeof(_dispatch_build
);
549 sysctl(mib
, 2, _dispatch_build
, &bufsz
, NULL
, 0);
550 #if TARGET_IPHONE_SIMULATOR
551 char *sim_version
= getenv("SIMULATOR_RUNTIME_BUILD_VERSION");
553 (void)strlcat(_dispatch_build
, " ", sizeof(_dispatch_build
));
554 (void)strlcat(_dispatch_build
, sim_version
, sizeof(_dispatch_build
));
556 #endif // TARGET_IPHONE_SIMULATOR
560 * XXXRW: What to do here for !Mac OS X?
562 memset(_dispatch_build
, 0, sizeof(_dispatch_build
));
566 static dispatch_once_t _dispatch_build_pred
;
569 _dispatch_get_build(void)
571 dispatch_once_f(&_dispatch_build_pred
, NULL
, _dispatch_build_init
);
572 return _dispatch_build
;
575 #define _dispatch_bug_log(msg, ...) do { \
576 static void *last_seen; \
577 void *ra = __builtin_return_address(0); \
578 if (last_seen != ra) { \
580 _dispatch_log(msg, ##__VA_ARGS__); \
585 _dispatch_bug(size_t line
, long val
)
587 dispatch_once_f(&_dispatch_build_pred
, NULL
, _dispatch_build_init
);
588 _dispatch_bug_log("BUG in libdispatch: %s - %lu - 0x%lx",
589 _dispatch_build
, (unsigned long)line
, val
);
593 _dispatch_bug_client(const char* msg
)
595 _dispatch_bug_log("BUG in libdispatch client: %s", msg
);
600 _dispatch_bug_mach_client(const char* msg
, mach_msg_return_t kr
)
602 _dispatch_bug_log("BUG in libdispatch client: %s %s - 0x%x", msg
,
603 mach_error_string(kr
), kr
);
608 _dispatch_bug_kevent_client(const char* msg
, const char* filter
,
609 const char *operation
, int err
)
611 if (operation
&& err
) {
612 _dispatch_bug_log("BUG in libdispatch client: %s[%s] %s: \"%s\" - 0x%x",
613 msg
, filter
, operation
, strerror(err
), err
);
614 } else if (operation
) {
615 _dispatch_bug_log("BUG in libdispatch client: %s[%s] %s",
616 msg
, filter
, operation
);
618 _dispatch_bug_log("BUG in libdispatch: %s[%s]: \"%s\" - 0x%x",
619 msg
, filter
, strerror(err
), err
);
624 _dispatch_bug_deprecated(const char *msg
)
626 _dispatch_bug_log("DEPRECATED USE in libdispatch client: %s", msg
);
630 _dispatch_abort(size_t line
, long val
)
632 _dispatch_bug(line
, val
);
636 #if !DISPATCH_USE_OS_DEBUG_LOG
639 #pragma mark dispatch_log
641 static int dispatch_logfile
= -1;
642 static bool dispatch_log_disabled
;
644 static uint64_t dispatch_log_basetime
;
646 static dispatch_once_t _dispatch_logv_pred
;
649 _dispatch_logv_init(void *context DISPATCH_UNUSED
)
652 bool log_to_file
= true;
654 bool log_to_file
= false;
656 char *e
= getenv("LIBDISPATCH_LOG");
658 if (strcmp(e
, "YES") == 0) {
660 } else if (strcmp(e
, "NO") == 0) {
661 dispatch_log_disabled
= true;
662 } else if (strcmp(e
, "syslog") == 0) {
664 } else if (strcmp(e
, "file") == 0) {
666 } else if (strcmp(e
, "stderr") == 0) {
668 dispatch_logfile
= STDERR_FILENO
;
671 if (!dispatch_log_disabled
) {
672 if (log_to_file
&& dispatch_logfile
== -1) {
674 snprintf(path
, sizeof(path
), "/var/tmp/libdispatch.%d.log",
676 dispatch_logfile
= open(path
, O_WRONLY
| O_APPEND
| O_CREAT
|
677 O_NOFOLLOW
| O_CLOEXEC
, 0666);
679 if (dispatch_logfile
!= -1) {
681 gettimeofday(&tv
, NULL
);
683 dispatch_log_basetime
= _dispatch_absolute_time();
685 dprintf(dispatch_logfile
, "=== log file opened for %s[%u] at "
686 "%ld.%06u ===\n", getprogname() ?: "", getpid(),
687 tv
.tv_sec
, (int)tv
.tv_usec
);
693 _dispatch_log_file(char *buf
, size_t len
)
699 r
= write(dispatch_logfile
, buf
, len
);
700 if (slowpath(r
== -1) && errno
== EINTR
) {
707 _dispatch_logv_file(const char *msg
, va_list ap
)
710 size_t bufsiz
= sizeof(buf
), offset
= 0;
714 offset
+= dsnprintf(&buf
[offset
], bufsiz
- offset
, "%llu\t",
715 _dispatch_absolute_time() - dispatch_log_basetime
);
717 r
= vsnprintf(&buf
[offset
], bufsiz
- offset
, msg
, ap
);
720 if (offset
> bufsiz
- 1) {
723 _dispatch_log_file(buf
, offset
);
726 #if DISPATCH_USE_SIMPLE_ASL
728 _dispatch_syslog(const char *msg
)
730 _simple_asl_log(ASL_LEVEL_NOTICE
, "com.apple.libsystem.libdispatch", msg
);
734 _dispatch_vsyslog(const char *msg
, va_list ap
)
737 vasprintf(&str
, msg
, ap
);
739 _dispatch_syslog(str
);
743 #else // DISPATCH_USE_SIMPLE_ASL
745 _dispatch_syslog(const char *msg
)
747 syslog(LOG_NOTICE
, "%s", msg
);
751 _dispatch_vsyslog(const char *msg
, va_list ap
)
753 vsyslog(LOG_NOTICE
, msg
, ap
);
755 #endif // DISPATCH_USE_SIMPLE_ASL
757 DISPATCH_ALWAYS_INLINE
759 _dispatch_logv(const char *msg
, size_t len
, va_list *ap_ptr
)
761 dispatch_once_f(&_dispatch_logv_pred
, NULL
, _dispatch_logv_init
);
762 if (slowpath(dispatch_log_disabled
)) {
765 if (slowpath(dispatch_logfile
!= -1)) {
767 return _dispatch_log_file((char*)msg
, len
);
769 return _dispatch_logv_file(msg
, *ap_ptr
);
772 return _dispatch_syslog(msg
);
774 return _dispatch_vsyslog(msg
, *ap_ptr
);
779 _dispatch_log(const char *msg
, ...)
784 _dispatch_logv(msg
, 0, &ap
);
788 #endif // DISPATCH_USE_OS_DEBUG_LOG
791 #pragma mark dispatch_debug
794 _dispatch_object_debug2(dispatch_object_t dou
, char* buf
, size_t bufsiz
)
796 DISPATCH_OBJECT_TFB(_dispatch_objc_debug
, dou
, buf
, bufsiz
);
797 if (dx_vtable(dou
._do
)->do_debug
) {
798 return dx_debug(dou
._do
, buf
, bufsiz
);
800 return strlcpy(buf
, "NULL vtable slot: ", bufsiz
);
805 _dispatch_debugv(dispatch_object_t dou
, const char *msg
, va_list ap
)
808 size_t bufsiz
= sizeof(buf
), offset
= 0;
810 #if DISPATCH_DEBUG && !DISPATCH_USE_OS_DEBUG_LOG
811 offset
+= dsnprintf(&buf
[offset
], bufsiz
- offset
, "%llu\t\t%p\t",
812 _dispatch_absolute_time() - dispatch_log_basetime
,
813 (void *)_dispatch_thread_self());
816 offset
+= _dispatch_object_debug2(dou
, &buf
[offset
], bufsiz
- offset
);
817 dispatch_assert(offset
+ 2 < bufsiz
);
822 offset
+= strlcpy(&buf
[offset
], "NULL: ", bufsiz
- offset
);
824 r
= vsnprintf(&buf
[offset
], bufsiz
- offset
, msg
, ap
);
825 #if !DISPATCH_USE_OS_DEBUG_LOG
826 size_t len
= offset
+ (r
< 0 ? 0 : (size_t)r
);
827 if (len
> bufsiz
- 1) {
830 _dispatch_logv(buf
, len
, NULL
);
832 _dispatch_log("%s", buf
);
838 dispatch_debugv(dispatch_object_t dou
, const char *msg
, va_list ap
)
840 _dispatch_debugv(dou
, msg
, ap
);
845 dispatch_debug(dispatch_object_t dou
, const char *msg
, ...)
850 _dispatch_debugv(dou
, msg
, ap
);
857 _dispatch_object_debug(dispatch_object_t dou
, const char *msg
, ...)
862 _dispatch_debugv(dou
._do
, msg
, ap
);
868 #pragma mark dispatch_calloc
872 _dispatch_temporary_resource_shortage(void)
878 _dispatch_calloc(size_t num_items
, size_t size
)
881 while (!fastpath(buf
= calloc(num_items
, size
))) {
882 _dispatch_temporary_resource_shortage();
888 * If the source string is mutable, allocates memory and copies the contents.
889 * Otherwise returns the source string.
892 _dispatch_strdup_if_mutable(const char *str
)
894 #if HAVE_DYLD_IS_MEMORY_IMMUTABLE
895 size_t size
= strlen(str
) + 1;
896 if (slowpath(!_dyld_is_memory_immutable(str
, size
))) {
897 char *clone
= (char *) malloc(size
);
898 if (dispatch_assume(clone
)) {
899 memcpy(clone
, str
, size
);
910 #pragma mark dispatch_block_t
915 (_dispatch_Block_copy
)(void *db
)
917 dispatch_block_t rval
;
920 while (!fastpath(rval
= Block_copy(db
))) {
921 _dispatch_temporary_resource_shortage();
925 DISPATCH_CLIENT_CRASH(0, "NULL was passed where a block should have been");
929 _dispatch_call_block_and_release(void *block
)
931 void (^b
)(void) = block
;
939 #pragma mark dispatch_client_callout
941 // Abort on uncaught exceptions thrown from client callouts rdar://8577499
942 #if DISPATCH_USE_CLIENT_CALLOUT && (__USING_SJLJ_EXCEPTIONS__ || !USE_OBJC || \
943 OS_OBJECT_HAVE_OBJC1)
944 // On platforms with SjLj exceptions, avoid the SjLj overhead on every callout
945 // by clearing the unwinder's TSD pointer to the handler stack around callouts
947 #define _dispatch_get_tsd_base()
948 #define _dispatch_get_unwind_tsd() (NULL)
949 #define _dispatch_set_unwind_tsd(u) do {(void)(u);} while (0)
950 #define _dispatch_free_unwind_tsd()
952 #undef _dispatch_client_callout
955 _dispatch_client_callout(void *ctxt
, dispatch_function_t f
)
957 _dispatch_get_tsd_base();
958 void *u
= _dispatch_get_unwind_tsd();
959 if (fastpath(!u
)) return f(ctxt
);
960 _dispatch_set_unwind_tsd(NULL
);
962 _dispatch_free_unwind_tsd();
963 _dispatch_set_unwind_tsd(u
);
966 #undef _dispatch_client_callout2
969 _dispatch_client_callout2(void *ctxt
, size_t i
, void (*f
)(void *, size_t))
971 _dispatch_get_tsd_base();
972 void *u
= _dispatch_get_unwind_tsd();
973 if (fastpath(!u
)) return f(ctxt
, i
);
974 _dispatch_set_unwind_tsd(NULL
);
976 _dispatch_free_unwind_tsd();
977 _dispatch_set_unwind_tsd(u
);
981 #undef _dispatch_client_callout4
983 _dispatch_client_callout4(void *ctxt
, dispatch_mach_reason_t reason
,
984 dispatch_mach_msg_t dmsg
, mach_error_t error
,
985 dispatch_mach_handler_function_t f
)
987 _dispatch_get_tsd_base();
988 void *u
= _dispatch_get_unwind_tsd();
989 if (fastpath(!u
)) return f(ctxt
, reason
, dmsg
, error
);
990 _dispatch_set_unwind_tsd(NULL
);
991 f(ctxt
, reason
, dmsg
, error
);
992 _dispatch_free_unwind_tsd();
993 _dispatch_set_unwind_tsd(u
);
997 #endif // DISPATCH_USE_CLIENT_CALLOUT
1000 #pragma mark _os_object_t no_objc
1004 static const _os_object_vtable_s _os_object_vtable
;
1007 _os_object_init(void)
1013 _os_object_alloc_realized(const void *cls
, size_t size
)
1016 dispatch_assert(size
>= sizeof(struct _os_object_s
));
1017 while (!fastpath(obj
= calloc(1u, size
))) {
1018 _dispatch_temporary_resource_shortage();
1020 obj
->os_obj_isa
= cls
;
1025 _os_object_alloc(const void *cls
, size_t size
)
1027 if (!cls
) cls
= &_os_object_vtable
;
1028 return _os_object_alloc_realized(cls
, size
);
1032 _os_object_dealloc(_os_object_t obj
)
1034 *((void *volatile*)&obj
->os_obj_isa
) = (void *)0x200;
1039 _os_object_xref_dispose(_os_object_t obj
)
1041 _os_object_xrefcnt_dispose_barrier(obj
);
1042 if (fastpath(obj
->os_obj_isa
->_os_obj_xref_dispose
)) {
1043 return obj
->os_obj_isa
->_os_obj_xref_dispose(obj
);
1045 return _os_object_release_internal(obj
);
1049 _os_object_dispose(_os_object_t obj
)
1051 _os_object_refcnt_dispose_barrier(obj
);
1052 if (fastpath(obj
->os_obj_isa
->_os_obj_dispose
)) {
1053 return obj
->os_obj_isa
->_os_obj_dispose(obj
);
1055 return _os_object_dealloc(obj
);
1059 os_retain(void *obj
)
1061 if (fastpath(obj
)) {
1062 return _os_object_retain(obj
);
1069 os_release(void *obj
)
1071 if (fastpath(obj
)) {
1072 return _os_object_release(obj
);
1077 _os_object_atfork_prepare(void)
1083 _os_object_atfork_parent(void)
1089 _os_object_atfork_child(void)
1095 #pragma mark dispatch_autorelease_pool no_objc
1097 #if DISPATCH_COCOA_COMPAT
1100 _dispatch_autorelease_pool_push(void)
1103 if (_dispatch_begin_NSAutoReleasePool
) {
1104 pool
= _dispatch_begin_NSAutoReleasePool();
1110 _dispatch_autorelease_pool_pop(void *pool
)
1112 if (_dispatch_end_NSAutoReleasePool
) {
1113 _dispatch_end_NSAutoReleasePool(pool
);
1118 _dispatch_last_resort_autorelease_pool_push(void)
1120 return _dispatch_autorelease_pool_push();
1124 _dispatch_last_resort_autorelease_pool_pop(void *pool
)
1126 _dispatch_autorelease_pool_pop(pool
);
1129 #endif // DISPATCH_COCOA_COMPAT
1133 #pragma mark dispatch_source_types
1136 dispatch_source_type_timer_init(dispatch_source_t ds
,
1137 dispatch_source_type_t type DISPATCH_UNUSED
,
1138 uintptr_t handle DISPATCH_UNUSED
,
1141 if (fastpath(!ds
->ds_refs
)) {
1142 ds
->ds_refs
= _dispatch_calloc(1ul,
1143 sizeof(struct dispatch_timer_source_refs_s
));
1145 ds
->ds_needs_rearm
= true;
1146 ds
->ds_is_timer
= true;
1147 ds_timer(ds
->ds_refs
).flags
= mask
;
1150 const struct dispatch_source_type_s _dispatch_source_type_timer
= {
1152 .filter
= DISPATCH_EVFILT_TIMER
,
1154 .mask
= DISPATCH_TIMER_STRICT
|DISPATCH_TIMER_BACKGROUND
|
1155 DISPATCH_TIMER_WALL_CLOCK
,
1156 .init
= dispatch_source_type_timer_init
,
1160 dispatch_source_type_after_init(dispatch_source_t ds
,
1161 dispatch_source_type_t type
, uintptr_t handle
, unsigned long mask
)
1163 dispatch_source_type_timer_init(ds
, type
, handle
, mask
);
1164 ds
->ds_needs_rearm
= false;
1165 ds_timer(ds
->ds_refs
).flags
|= DISPATCH_TIMER_AFTER
;
1168 const struct dispatch_source_type_s _dispatch_source_type_after
= {
1170 .filter
= DISPATCH_EVFILT_TIMER
,
1172 .init
= dispatch_source_type_after_init
,
1176 dispatch_source_type_timer_with_aggregate_init(dispatch_source_t ds
,
1177 dispatch_source_type_t type
, uintptr_t handle
, unsigned long mask
)
1179 ds
->ds_refs
= _dispatch_calloc(1ul,
1180 sizeof(struct dispatch_timer_source_aggregate_refs_s
));
1181 dispatch_source_type_timer_init(ds
, type
, handle
, mask
);
1182 ds_timer(ds
->ds_refs
).flags
|= DISPATCH_TIMER_WITH_AGGREGATE
;
1183 ds
->dq_specific_q
= (void*)handle
;
1184 _dispatch_retain(ds
->dq_specific_q
);
1187 const struct dispatch_source_type_s _dispatch_source_type_timer_with_aggregate
={
1189 .filter
= DISPATCH_EVFILT_TIMER
,
1192 .mask
= DISPATCH_TIMER_STRICT
|DISPATCH_TIMER_BACKGROUND
,
1193 .init
= dispatch_source_type_timer_with_aggregate_init
,
1197 dispatch_source_type_interval_init(dispatch_source_t ds
,
1198 dispatch_source_type_t type
, uintptr_t handle
, unsigned long mask
)
1200 dispatch_source_type_timer_init(ds
, type
, handle
, mask
);
1201 ds_timer(ds
->ds_refs
).flags
|= DISPATCH_TIMER_INTERVAL
;
1202 unsigned long ident
= _dispatch_source_timer_idx(ds
->ds_refs
);
1203 ds
->ds_dkev
->dk_kevent
.ident
= ds
->ds_ident_hack
= ident
;
1204 _dispatch_source_set_interval(ds
, handle
);
1207 const struct dispatch_source_type_s _dispatch_source_type_interval
= {
1209 .filter
= DISPATCH_EVFILT_TIMER
,
1212 .mask
= DISPATCH_TIMER_STRICT
|DISPATCH_TIMER_BACKGROUND
|
1213 DISPATCH_INTERVAL_UI_ANIMATION
,
1214 .init
= dispatch_source_type_interval_init
,
1218 dispatch_source_type_readwrite_init(dispatch_source_t ds
,
1219 dispatch_source_type_t type DISPATCH_UNUSED
,
1220 uintptr_t handle DISPATCH_UNUSED
,
1221 unsigned long mask DISPATCH_UNUSED
)
1223 ds
->ds_is_level
= true;
1224 #if HAVE_DECL_NOTE_LOWAT
1225 // bypass kernel check for device kqueue support rdar://19004921
1226 ds
->ds_dkev
->dk_kevent
.fflags
= NOTE_LOWAT
;
1228 ds
->ds_dkev
->dk_kevent
.data
= 1;
1231 const struct dispatch_source_type_s _dispatch_source_type_read
= {
1233 .filter
= EVFILT_READ
,
1234 .flags
= EV_VANISHED
|EV_DISPATCH
|EV_UDATA_SPECIFIC
,
1236 .init
= dispatch_source_type_readwrite_init
,
1239 const struct dispatch_source_type_s _dispatch_source_type_write
= {
1241 .filter
= EVFILT_WRITE
,
1242 .flags
= EV_VANISHED
|EV_DISPATCH
|EV_UDATA_SPECIFIC
,
1244 .init
= dispatch_source_type_readwrite_init
,
1247 #if DISPATCH_USE_MEMORYSTATUS
1249 #if TARGET_IPHONE_SIMULATOR // rdar://problem/9219483
1250 static int _dispatch_ios_simulator_memory_warnings_fd
= -1;
1252 _dispatch_ios_simulator_memorypressure_init(void *context DISPATCH_UNUSED
)
1254 char *e
= getenv("SIMULATOR_MEMORY_WARNINGS");
1256 _dispatch_ios_simulator_memory_warnings_fd
= open(e
, O_EVTONLY
);
1257 if (_dispatch_ios_simulator_memory_warnings_fd
== -1) {
1258 (void)dispatch_assume_zero(errno
);
1263 #if TARGET_IPHONE_SIMULATOR
1265 dispatch_source_type_memorypressure_init(dispatch_source_t ds
,
1266 dispatch_source_type_t type DISPATCH_UNUSED
,
1267 uintptr_t handle DISPATCH_UNUSED
,
1268 unsigned long mask DISPATCH_UNUSED
)
1270 static dispatch_once_t pred
;
1271 dispatch_once_f(&pred
, NULL
, _dispatch_ios_simulator_memorypressure_init
);
1272 handle
= (uintptr_t)_dispatch_ios_simulator_memory_warnings_fd
;
1274 ds
->ds_dkev
->dk_kevent
.filter
= EVFILT_VNODE
;
1275 ds
->ds_dkev
->dk_kevent
.ident
= handle
;
1276 ds
->ds_dkev
->dk_kevent
.flags
|= EV_CLEAR
;
1277 ds
->ds_dkev
->dk_kevent
.fflags
= (uint32_t)mask
;
1278 ds
->ds_ident_hack
= handle
;
1279 ds
->ds_pending_data_mask
= mask
;
1280 ds
->ds_memorypressure_override
= 1;
1283 #define dispatch_source_type_memorypressure_init NULL
1286 #ifndef NOTE_MEMORYSTATUS_LOW_SWAP
1287 #define NOTE_MEMORYSTATUS_LOW_SWAP 0x8
1290 const struct dispatch_source_type_s _dispatch_source_type_memorypressure
= {
1292 .filter
= EVFILT_MEMORYSTATUS
,
1293 .flags
= EV_DISPATCH
|EV_UDATA_SPECIFIC
,
1295 .mask
= NOTE_MEMORYSTATUS_PRESSURE_NORMAL
|NOTE_MEMORYSTATUS_PRESSURE_WARN
1296 |NOTE_MEMORYSTATUS_PRESSURE_CRITICAL
|NOTE_MEMORYSTATUS_LOW_SWAP
1297 |NOTE_MEMORYSTATUS_PROC_LIMIT_WARN
|NOTE_MEMORYSTATUS_PROC_LIMIT_CRITICAL
,
1298 .init
= dispatch_source_type_memorypressure_init
,
1302 dispatch_source_type_vm_init(dispatch_source_t ds
,
1303 dispatch_source_type_t type DISPATCH_UNUSED
,
1304 uintptr_t handle DISPATCH_UNUSED
,
1305 unsigned long mask DISPATCH_UNUSED
)
1307 // Map legacy vm pressure to memorypressure warning rdar://problem/15907505
1308 mask
= NOTE_MEMORYSTATUS_PRESSURE_WARN
;
1309 ds
->ds_dkev
->dk_kevent
.fflags
= (uint32_t)mask
;
1310 ds
->ds_pending_data_mask
= mask
;
1311 ds
->ds_vmpressure_override
= 1;
1312 #if TARGET_IPHONE_SIMULATOR
1313 dispatch_source_type_memorypressure_init(ds
, type
, handle
, mask
);
1317 const struct dispatch_source_type_s _dispatch_source_type_vm
= {
1319 .filter
= EVFILT_MEMORYSTATUS
,
1320 .flags
= EV_DISPATCH
|EV_UDATA_SPECIFIC
,
1322 .mask
= NOTE_VM_PRESSURE
,
1323 .init
= dispatch_source_type_vm_init
,
1326 #endif // DISPATCH_USE_MEMORYSTATUS
1328 const struct dispatch_source_type_s _dispatch_source_type_signal
= {
1330 .filter
= EVFILT_SIGNAL
,
1331 .flags
= EV_UDATA_SPECIFIC
,
1335 #if !defined(__linux__)
1337 dispatch_source_type_proc_init(dispatch_source_t ds
,
1338 dispatch_source_type_t type DISPATCH_UNUSED
,
1339 uintptr_t handle DISPATCH_UNUSED
,
1340 unsigned long mask DISPATCH_UNUSED
)
1342 ds
->ds_dkev
->dk_kevent
.fflags
|= NOTE_EXIT
; // rdar://16655831
1345 const struct dispatch_source_type_s _dispatch_source_type_proc
= {
1347 .filter
= EVFILT_PROC
,
1348 .flags
= EV_CLEAR
|EV_UDATA_SPECIFIC
,
1350 .mask
= NOTE_EXIT
|NOTE_FORK
|NOTE_EXEC
1351 #if HAVE_DECL_NOTE_SIGNAL
1354 #if HAVE_DECL_NOTE_REAP
1358 .init
= dispatch_source_type_proc_init
,
1361 const struct dispatch_source_type_s _dispatch_source_type_vnode
= {
1363 .filter
= EVFILT_VNODE
,
1364 .flags
= EV_CLEAR
|EV_VANISHED
|EV_UDATA_SPECIFIC
,
1366 .mask
= NOTE_DELETE
|NOTE_WRITE
|NOTE_EXTEND
|NOTE_ATTRIB
|NOTE_LINK
|
1367 NOTE_RENAME
|NOTE_FUNLOCK
1368 #if HAVE_DECL_NOTE_REVOKE
1371 #if HAVE_DECL_NOTE_NONE
1377 const struct dispatch_source_type_s _dispatch_source_type_vfs
= {
1379 .filter
= EVFILT_FS
,
1380 .flags
= EV_CLEAR
|EV_UDATA_SPECIFIC
,
1382 .mask
= VQ_NOTRESP
|VQ_NEEDAUTH
|VQ_LOWDISK
|VQ_MOUNT
|VQ_UNMOUNT
|VQ_DEAD
|
1383 VQ_ASSIST
|VQ_NOTRESPLOCK
1384 #if HAVE_DECL_VQ_UPDATE
1387 #if HAVE_DECL_VQ_VERYLOWDISK
1390 #if HAVE_DECL_VQ_QUOTA
1393 #if HAVE_DECL_VQ_NEARLOWDISK
1396 #if HAVE_DECL_VQ_DESIRED_DISK
1402 const struct dispatch_source_type_s _dispatch_source_type_sock
= {
1405 .filter
= EVFILT_SOCK
,
1406 .flags
= EV_CLEAR
|EV_VANISHED
|EV_UDATA_SPECIFIC
,
1408 .mask
= NOTE_CONNRESET
| NOTE_READCLOSED
| NOTE_WRITECLOSED
|
1409 NOTE_TIMEOUT
| NOTE_NOSRCADDR
| NOTE_IFDENIED
| NOTE_SUSPEND
|
1410 NOTE_RESUME
| NOTE_KEEPALIVE
1411 #ifdef NOTE_ADAPTIVE_WTIMO
1412 | NOTE_ADAPTIVE_WTIMO
| NOTE_ADAPTIVE_RTIMO
1414 #ifdef NOTE_CONNECTED
1415 | NOTE_CONNECTED
| NOTE_DISCONNECTED
| NOTE_CONNINFO_UPDATED
1417 #ifdef NOTE_NOTIFY_ACK
1421 #endif // EVFILT_SOCK
1423 #endif // !defined(__linux__)
1426 dispatch_source_type_data_init(dispatch_source_t ds
,
1427 dispatch_source_type_t type DISPATCH_UNUSED
,
1428 uintptr_t handle DISPATCH_UNUSED
,
1429 unsigned long mask DISPATCH_UNUSED
)
1431 ds
->ds_is_installed
= true;
1432 ds
->ds_is_custom_source
= true;
1433 ds
->ds_is_direct_kevent
= true;
1434 ds
->ds_pending_data_mask
= ~0ul;
1435 ds
->ds_needs_rearm
= false; // not registered with kevent
1438 const struct dispatch_source_type_s _dispatch_source_type_data_add
= {
1440 .filter
= DISPATCH_EVFILT_CUSTOM_ADD
,
1441 .flags
= EV_UDATA_SPECIFIC
,
1443 .init
= dispatch_source_type_data_init
,
1446 const struct dispatch_source_type_s _dispatch_source_type_data_or
= {
1448 .filter
= DISPATCH_EVFILT_CUSTOM_OR
,
1449 .flags
= EV_CLEAR
|EV_UDATA_SPECIFIC
,
1452 .init
= dispatch_source_type_data_init
,
1458 dispatch_source_type_mach_send_init(dispatch_source_t ds
,
1459 dispatch_source_type_t type DISPATCH_UNUSED
,
1460 uintptr_t handle DISPATCH_UNUSED
, unsigned long mask
)
1463 // Preserve legacy behavior that (mask == 0) => DISPATCH_MACH_SEND_DEAD
1464 ds
->ds_dkev
->dk_kevent
.fflags
= DISPATCH_MACH_SEND_DEAD
;
1465 ds
->ds_pending_data_mask
= DISPATCH_MACH_SEND_DEAD
;
1469 const struct dispatch_source_type_s _dispatch_source_type_mach_send
= {
1471 .filter
= DISPATCH_EVFILT_MACH_NOTIFICATION
,
1474 .mask
= DISPATCH_MACH_SEND_DEAD
|DISPATCH_MACH_SEND_POSSIBLE
,
1475 .init
= dispatch_source_type_mach_send_init
,
1479 dispatch_source_type_mach_recv_init(dispatch_source_t ds
,
1480 dispatch_source_type_t type DISPATCH_UNUSED
,
1481 uintptr_t handle DISPATCH_UNUSED
,
1482 unsigned long mask DISPATCH_UNUSED
)
1484 ds
->ds_pending_data_mask
= DISPATCH_MACH_RECV_MESSAGE
;
1485 #if DISPATCH_EVFILT_MACHPORT_PORTSET_FALLBACK
1486 if (_dispatch_evfilt_machport_direct_enabled
) return;
1487 ds
->ds_dkev
->dk_kevent
.fflags
= DISPATCH_MACH_RECV_MESSAGE
;
1488 ds
->ds_dkev
->dk_kevent
.flags
&= ~(EV_UDATA_SPECIFIC
|EV_VANISHED
);
1489 ds
->ds_is_direct_kevent
= false;
1493 const struct dispatch_source_type_s _dispatch_source_type_mach_recv
= {
1495 .filter
= EVFILT_MACHPORT
,
1496 .flags
= EV_VANISHED
|EV_DISPATCH
|EV_UDATA_SPECIFIC
,
1498 .init
= dispatch_source_type_mach_recv_init
,
1502 #pragma mark dispatch_mig
1505 dispatch_mach_msg_get_context(mach_msg_header_t
*msg
)
1507 mach_msg_context_trailer_t
*tp
;
1508 void *context
= NULL
;
1510 tp
= (mach_msg_context_trailer_t
*)((uint8_t *)msg
+
1511 round_msg(msg
->msgh_size
));
1512 if (tp
->msgh_trailer_size
>=
1513 (mach_msg_size_t
)sizeof(mach_msg_context_trailer_t
)) {
1514 context
= (void *)(uintptr_t)tp
->msgh_context
;
1520 _dispatch_wakeup_runloop_thread(mach_port_t mp DISPATCH_UNUSED
)
1522 // dummy function just to pop a runloop thread out of mach_msg()
1527 _dispatch_consume_send_once_right(mach_port_t mp DISPATCH_UNUSED
)
1529 // dummy function to consume a send-once right
1534 _dispatch_mach_notify_port_destroyed(mach_port_t notify DISPATCH_UNUSED
,
1538 // this function should never be called
1539 (void)dispatch_assume_zero(name
);
1540 kr
= mach_port_mod_refs(mach_task_self(), name
, MACH_PORT_RIGHT_RECEIVE
,-1);
1541 DISPATCH_VERIFY_MIG(kr
);
1542 (void)dispatch_assume_zero(kr
);
1543 return KERN_SUCCESS
;
1547 _dispatch_mach_notify_no_senders(mach_port_t notify
,
1548 mach_port_mscount_t mscnt DISPATCH_UNUSED
)
1550 // this function should never be called
1551 (void)dispatch_assume_zero(notify
);
1552 return KERN_SUCCESS
;
1556 _dispatch_mach_notify_send_once(mach_port_t notify DISPATCH_UNUSED
)
1558 // we only register for dead-name notifications
1559 // some code deallocated our send-once right without consuming it
1561 _dispatch_log("Corruption: An app/library deleted a libdispatch "
1562 "dead-name notification");
1564 return KERN_SUCCESS
;