-#pragma mark -
-#pragma mark dispatch_source_types
-
-static void
-dispatch_source_type_timer_init(dispatch_source_t ds,
- dispatch_source_type_t type DISPATCH_UNUSED,
- uintptr_t handle DISPATCH_UNUSED,
- unsigned long mask,
- dispatch_queue_t q)
-{
- if (fastpath(!ds->ds_refs)) {
- ds->ds_refs = _dispatch_calloc(1ul,
- sizeof(struct dispatch_timer_source_refs_s));
- }
- ds->ds_needs_rearm = true;
- ds->ds_is_timer = true;
- if (q == dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)
- || q == dispatch_get_global_queue(
- DISPATCH_QUEUE_PRIORITY_BACKGROUND, DISPATCH_QUEUE_OVERCOMMIT)){
- mask |= DISPATCH_TIMER_BACKGROUND; // <rdar://problem/12200216>
- }
- ds_timer(ds->ds_refs).flags = mask;
-}
-
-const struct dispatch_source_type_s _dispatch_source_type_timer = {
- .ke = {
- .filter = DISPATCH_EVFILT_TIMER,
- },
- .mask = DISPATCH_TIMER_STRICT|DISPATCH_TIMER_BACKGROUND|
- DISPATCH_TIMER_WALL_CLOCK,
- .init = dispatch_source_type_timer_init,
-};
-
-static void
-dispatch_source_type_after_init(dispatch_source_t ds,
- dispatch_source_type_t type, uintptr_t handle, unsigned long mask,
- dispatch_queue_t q)
-{
- dispatch_source_type_timer_init(ds, type, handle, mask, q);
- ds->ds_needs_rearm = false;
- ds_timer(ds->ds_refs).flags |= DISPATCH_TIMER_AFTER;
-}
-
-const struct dispatch_source_type_s _dispatch_source_type_after = {
- .ke = {
- .filter = DISPATCH_EVFILT_TIMER,
- },
- .init = dispatch_source_type_after_init,
-};
-
-static void
-dispatch_source_type_timer_with_aggregate_init(dispatch_source_t ds,
- dispatch_source_type_t type, uintptr_t handle, unsigned long mask,
- dispatch_queue_t q)
-{
- ds->ds_refs = _dispatch_calloc(1ul,
- sizeof(struct dispatch_timer_source_aggregate_refs_s));
- dispatch_source_type_timer_init(ds, type, handle, mask, q);
- ds_timer(ds->ds_refs).flags |= DISPATCH_TIMER_WITH_AGGREGATE;
- ds->dq_specific_q = (void*)handle;
- _dispatch_retain(ds->dq_specific_q);
-}
-
-const struct dispatch_source_type_s _dispatch_source_type_timer_with_aggregate={
- .ke = {
- .filter = DISPATCH_EVFILT_TIMER,
- .ident = ~0ull,
- },
- .mask = DISPATCH_TIMER_STRICT|DISPATCH_TIMER_BACKGROUND,
- .init = dispatch_source_type_timer_with_aggregate_init,
-};
-
-static void
-dispatch_source_type_interval_init(dispatch_source_t ds,
- dispatch_source_type_t type, uintptr_t handle, unsigned long mask,
- dispatch_queue_t q)
-{
- dispatch_source_type_timer_init(ds, type, handle, mask, q);
- ds_timer(ds->ds_refs).flags |= DISPATCH_TIMER_INTERVAL;
- unsigned long ident = _dispatch_source_timer_idx(ds->ds_refs);
- ds->ds_dkev->dk_kevent.ident = ds->ds_ident_hack = ident;
- _dispatch_source_set_interval(ds, handle);
-}
-
-const struct dispatch_source_type_s _dispatch_source_type_interval = {
- .ke = {
- .filter = DISPATCH_EVFILT_TIMER,
- .ident = ~0ull,
- },
- .mask = DISPATCH_TIMER_STRICT|DISPATCH_TIMER_BACKGROUND|
- DISPATCH_INTERVAL_UI_ANIMATION,
- .init = dispatch_source_type_interval_init,
-};
-
-static void
-dispatch_source_type_readwrite_init(dispatch_source_t ds,
- dispatch_source_type_t type DISPATCH_UNUSED,
- uintptr_t handle DISPATCH_UNUSED,
- unsigned long mask DISPATCH_UNUSED,
- dispatch_queue_t q DISPATCH_UNUSED)
-{
- ds->ds_is_level = true;
-#ifdef HAVE_DECL_NOTE_LOWAT
- // bypass kernel check for device kqueue support rdar://19004921
- ds->ds_dkev->dk_kevent.fflags = NOTE_LOWAT;
-#endif
- ds->ds_dkev->dk_kevent.data = 1;
-}
-
-const struct dispatch_source_type_s _dispatch_source_type_read = {
- .ke = {
- .filter = EVFILT_READ,
- .flags = EV_VANISHED|EV_DISPATCH|EV_UDATA_SPECIFIC,
- },
- .init = dispatch_source_type_readwrite_init,
-};
-
-const struct dispatch_source_type_s _dispatch_source_type_write = {
- .ke = {
- .filter = EVFILT_WRITE,
- .flags = EV_VANISHED|EV_DISPATCH|EV_UDATA_SPECIFIC,
- },
- .init = dispatch_source_type_readwrite_init,
-};
-
-#if DISPATCH_USE_MEMORYSTATUS
-
-#if TARGET_IPHONE_SIMULATOR // rdar://problem/9219483
-static int _dispatch_ios_simulator_memory_warnings_fd = -1;
-static void
-_dispatch_ios_simulator_memorypressure_init(void *context DISPATCH_UNUSED)
-{
- char *e = getenv("SIMULATOR_MEMORY_WARNINGS");
- if (!e) return;
- _dispatch_ios_simulator_memory_warnings_fd = open(e, O_EVTONLY);
- if (_dispatch_ios_simulator_memory_warnings_fd == -1) {
- (void)dispatch_assume_zero(errno);
- }
-}
-#endif
-
-#if TARGET_IPHONE_SIMULATOR
-static void
-dispatch_source_type_memorypressure_init(dispatch_source_t ds,
- dispatch_source_type_t type DISPATCH_UNUSED,
- uintptr_t handle DISPATCH_UNUSED,
- unsigned long mask DISPATCH_UNUSED,
- dispatch_queue_t q DISPATCH_UNUSED)
-{
- static dispatch_once_t pred;
- dispatch_once_f(&pred, NULL, _dispatch_ios_simulator_memorypressure_init);
- handle = (uintptr_t)_dispatch_ios_simulator_memory_warnings_fd;
- mask = NOTE_ATTRIB;
- ds->ds_dkev->dk_kevent.filter = EVFILT_VNODE;
- ds->ds_dkev->dk_kevent.ident = handle;
- ds->ds_dkev->dk_kevent.flags |= EV_CLEAR;
- ds->ds_dkev->dk_kevent.fflags = (uint32_t)mask;
- ds->ds_ident_hack = handle;
- ds->ds_pending_data_mask = mask;
- ds->ds_memorypressure_override = 1;
-}
-#else
-#define dispatch_source_type_memorypressure_init NULL
-#endif
-
-#ifndef NOTE_MEMORYSTATUS_LOW_SWAP
-#define NOTE_MEMORYSTATUS_LOW_SWAP 0x8
-#endif
-
-const struct dispatch_source_type_s _dispatch_source_type_memorypressure = {
- .ke = {
- .filter = EVFILT_MEMORYSTATUS,
- .flags = EV_DISPATCH|EV_UDATA_SPECIFIC,
- },
- .mask = NOTE_MEMORYSTATUS_PRESSURE_NORMAL|NOTE_MEMORYSTATUS_PRESSURE_WARN
- |NOTE_MEMORYSTATUS_PRESSURE_CRITICAL|NOTE_MEMORYSTATUS_LOW_SWAP
- |NOTE_MEMORYSTATUS_PROC_LIMIT_WARN|NOTE_MEMORYSTATUS_PROC_LIMIT_CRITICAL,
- .init = dispatch_source_type_memorypressure_init,
-};
-
-static void
-dispatch_source_type_vm_init(dispatch_source_t ds,
- dispatch_source_type_t type DISPATCH_UNUSED,
- uintptr_t handle DISPATCH_UNUSED,
- unsigned long mask DISPATCH_UNUSED,
- dispatch_queue_t q DISPATCH_UNUSED)
-{
- // Map legacy vm pressure to memorypressure warning rdar://problem/15907505
- mask = NOTE_MEMORYSTATUS_PRESSURE_WARN;
- ds->ds_dkev->dk_kevent.fflags = (uint32_t)mask;
- ds->ds_pending_data_mask = mask;
- ds->ds_vmpressure_override = 1;
-#if TARGET_IPHONE_SIMULATOR
- dispatch_source_type_memorypressure_init(ds, type, handle, mask, q);
-#endif
-}
-
-const struct dispatch_source_type_s _dispatch_source_type_vm = {
- .ke = {
- .filter = EVFILT_MEMORYSTATUS,
- .flags = EV_DISPATCH|EV_UDATA_SPECIFIC,
- },
- .mask = NOTE_VM_PRESSURE,
- .init = dispatch_source_type_vm_init,
-};
-
-#elif DISPATCH_USE_VM_PRESSURE
-
-const struct dispatch_source_type_s _dispatch_source_type_vm = {
- .ke = {
- .filter = EVFILT_VM,
- .flags = EV_DISPATCH|EV_UDATA_SPECIFIC,
- },
- .mask = NOTE_VM_PRESSURE,
-};
-
-#endif // DISPATCH_USE_VM_PRESSURE
-
-const struct dispatch_source_type_s _dispatch_source_type_signal = {
- .ke = {
- .filter = EVFILT_SIGNAL,
- .flags = EV_UDATA_SPECIFIC,
- },
-};
-
-#if !defined(__linux__)
-static void
-dispatch_source_type_proc_init(dispatch_source_t ds,
- dispatch_source_type_t type DISPATCH_UNUSED,
- uintptr_t handle DISPATCH_UNUSED,
- unsigned long mask DISPATCH_UNUSED,
- dispatch_queue_t q DISPATCH_UNUSED)
-{
- ds->ds_dkev->dk_kevent.fflags |= NOTE_EXIT; // rdar://16655831
-}
-
-const struct dispatch_source_type_s _dispatch_source_type_proc = {
- .ke = {
- .filter = EVFILT_PROC,
- .flags = EV_CLEAR|EV_UDATA_SPECIFIC,
- },
- .mask = NOTE_EXIT|NOTE_FORK|NOTE_EXEC
-#if HAVE_DECL_NOTE_SIGNAL
- |NOTE_SIGNAL
-#endif
-#if HAVE_DECL_NOTE_REAP
- |NOTE_REAP
-#endif
- ,
- .init = dispatch_source_type_proc_init,
-};
-
-const struct dispatch_source_type_s _dispatch_source_type_vnode = {
- .ke = {
- .filter = EVFILT_VNODE,
- .flags = EV_CLEAR|EV_VANISHED|EV_UDATA_SPECIFIC,
- },
- .mask = NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_LINK|
- NOTE_RENAME|NOTE_FUNLOCK
-#if HAVE_DECL_NOTE_REVOKE
- |NOTE_REVOKE
-#endif
-#if HAVE_DECL_NOTE_NONE
- |NOTE_NONE
-#endif
- ,
-};
-
-const struct dispatch_source_type_s _dispatch_source_type_vfs = {
- .ke = {
- .filter = EVFILT_FS,
- .flags = EV_CLEAR|EV_UDATA_SPECIFIC,
- },
- .mask = VQ_NOTRESP|VQ_NEEDAUTH|VQ_LOWDISK|VQ_MOUNT|VQ_UNMOUNT|VQ_DEAD|
- VQ_ASSIST|VQ_NOTRESPLOCK
-#if HAVE_DECL_VQ_UPDATE
- |VQ_UPDATE
-#endif
-#if HAVE_DECL_VQ_VERYLOWDISK
- |VQ_VERYLOWDISK
-#endif
-#if HAVE_DECL_VQ_QUOTA
- |VQ_QUOTA
-#endif
- ,
-};
-
-const struct dispatch_source_type_s _dispatch_source_type_sock = {
-#ifdef EVFILT_SOCK
- .ke = {
- .filter = EVFILT_SOCK,
- .flags = EV_CLEAR|EV_VANISHED|EV_UDATA_SPECIFIC,
- },
- .mask = NOTE_CONNRESET | NOTE_READCLOSED | NOTE_WRITECLOSED |
- NOTE_TIMEOUT | NOTE_NOSRCADDR | NOTE_IFDENIED | NOTE_SUSPEND |
- NOTE_RESUME | NOTE_KEEPALIVE
-#ifdef NOTE_ADAPTIVE_WTIMO
- | NOTE_ADAPTIVE_WTIMO | NOTE_ADAPTIVE_RTIMO
-#endif
-#ifdef NOTE_CONNECTED
- | NOTE_CONNECTED | NOTE_DISCONNECTED | NOTE_CONNINFO_UPDATED
-#endif
-#ifdef NOTE_NOTIFY_ACK
- | NOTE_NOTIFY_ACK
-#endif
- ,
-#endif // EVFILT_SOCK
-};
-#endif // !defined(__linux__)
-
-static void
-dispatch_source_type_data_init(dispatch_source_t ds,
- dispatch_source_type_t type DISPATCH_UNUSED,
- uintptr_t handle DISPATCH_UNUSED,
- unsigned long mask DISPATCH_UNUSED,
- dispatch_queue_t q DISPATCH_UNUSED)
-{
- ds->ds_is_installed = true;
- ds->ds_is_custom_source = true;
- ds->ds_is_direct_kevent = true;
- ds->ds_pending_data_mask = ~0ul;
- ds->ds_needs_rearm = false; // not registered with kevent
-}
-
-const struct dispatch_source_type_s _dispatch_source_type_data_add = {
- .ke = {
- .filter = DISPATCH_EVFILT_CUSTOM_ADD,
- .flags = EV_UDATA_SPECIFIC,
- },
- .init = dispatch_source_type_data_init,
-};
-
-const struct dispatch_source_type_s _dispatch_source_type_data_or = {
- .ke = {
- .filter = DISPATCH_EVFILT_CUSTOM_OR,
- .flags = EV_CLEAR|EV_UDATA_SPECIFIC,
- .fflags = ~0u,
- },
- .init = dispatch_source_type_data_init,
-};
-
-#if HAVE_MACH
-
-static void
-dispatch_source_type_mach_send_init(dispatch_source_t ds,
- dispatch_source_type_t type DISPATCH_UNUSED,
- uintptr_t handle DISPATCH_UNUSED, unsigned long mask,
- dispatch_queue_t q DISPATCH_UNUSED)
-{
- if (!mask) {
- // Preserve legacy behavior that (mask == 0) => DISPATCH_MACH_SEND_DEAD
- ds->ds_dkev->dk_kevent.fflags = DISPATCH_MACH_SEND_DEAD;
- ds->ds_pending_data_mask = DISPATCH_MACH_SEND_DEAD;
- }
-}
-
-const struct dispatch_source_type_s _dispatch_source_type_mach_send = {
- .ke = {
- .filter = DISPATCH_EVFILT_MACH_NOTIFICATION,
- .flags = EV_CLEAR,
- },
- .mask = DISPATCH_MACH_SEND_DEAD|DISPATCH_MACH_SEND_POSSIBLE,
- .init = dispatch_source_type_mach_send_init,
-};
-
-static void
-dispatch_source_type_mach_recv_init(dispatch_source_t ds,
- dispatch_source_type_t type DISPATCH_UNUSED,
- uintptr_t handle DISPATCH_UNUSED,
- unsigned long mask DISPATCH_UNUSED,
- dispatch_queue_t q DISPATCH_UNUSED)
-{
- ds->ds_pending_data_mask = DISPATCH_MACH_RECV_MESSAGE;
-#if DISPATCH_EVFILT_MACHPORT_PORTSET_FALLBACK
- if (_dispatch_evfilt_machport_direct_enabled) return;
- ds->ds_dkev->dk_kevent.fflags = DISPATCH_MACH_RECV_MESSAGE;
- ds->ds_dkev->dk_kevent.flags &= ~(EV_UDATA_SPECIFIC|EV_VANISHED);
- ds->ds_is_direct_kevent = false;
-#endif
-}
-
-const struct dispatch_source_type_s _dispatch_source_type_mach_recv = {
- .ke = {
- .filter = EVFILT_MACHPORT,
- .flags = EV_VANISHED|EV_DISPATCH|EV_UDATA_SPECIFIC,
- },
- .init = dispatch_source_type_mach_recv_init,
-};
-