From 8e892953f6918654eca76ce0ca66dda9dbd3e8db Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 11 Nov 2021 21:49:54 -0800 Subject: [PATCH 01/30] dispatch: adjust the print specifies to avoid some warnings (NFCI) This adjusts the dispatch debug logging to use to `%llx` for the conversion of some values. This avoids a format conversion warning on Windows. --- src/event/event.c | 4 ++-- src/source.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/event/event.c b/src/event/event.c index b908419d2..6f00f2f47 100644 --- a/src/event/event.c +++ b/src/event/event.c @@ -760,9 +760,9 @@ _dispatch_timer_heap_update(dispatch_timer_heap_t dth, #pragma mark timer unote #define _dispatch_timer_du_debug(what, du) \ - _dispatch_debug("kevent-source[%p]: %s kevent[%p] { ident = 0x%x }", \ + _dispatch_debug("kevent-source[%p]: %s kevent[%p] { ident = 0x%llx }", \ _dispatch_wref2ptr((du)->du_owner_wref), what, \ - (du), (du)->du_ident) + (du), (unsigned long long)(du)->du_ident) DISPATCH_ALWAYS_INLINE static inline unsigned int diff --git a/src/source.c b/src/source.c index 9af2a4a8b..4ee634933 100644 --- a/src/source.c +++ b/src/source.c @@ -1449,11 +1449,11 @@ _dispatch_source_debug_attr(dispatch_source_t ds, char* buf, size_t bufsiz) dispatch_source_refs_t dr = ds->ds_refs; dispatch_queue_flags_t dqf = _dispatch_queue_atomic_flags(ds); dispatch_unote_state_t du_state = _dispatch_unote_state(dr); - return dsnprintf(buf, bufsiz, "target = %s[%p], ident = 0x%x, " + return dsnprintf(buf, bufsiz, "target = %s[%p], ident = 0x%llx, " "mask = 0x%x, pending_data = 0x%llx, registered = %d, " "armed = %d, %s%s%s", target && target->dq_label ? target->dq_label : "", target, - dr->du_ident, dr->du_fflags, (unsigned long long)dr->ds_pending_data, + (unsigned long long)dr->du_ident, dr->du_fflags, (unsigned long long)dr->ds_pending_data, _du_state_registered(du_state), _du_state_armed(du_state), (dqf & DSF_CANCELED) ? "cancelled, " : "", (dqf & DSF_NEEDS_EVENT) ? "needs-event, " : "", From b78af3012244763b919dcd59e3d3db3e72cd0168 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 11 Nov 2021 21:55:01 -0800 Subject: [PATCH 02/30] dispatch: silence a warning on Windows (NFC) clang objects to the return from function marked as noreturn. Add in a marker to indicate that the return path is dead. This should be equivalent to the existing code but silences the compiler warning. --- src/queue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/queue.c b/src/queue.c index 44cdb4aa5..96bed5ed7 100644 --- a/src/queue.c +++ b/src/queue.c @@ -7813,6 +7813,7 @@ _dispatch_sig_thread(void *ctxt DISPATCH_UNUSED) _dispatch_clear_stack(0); #if defined(_WIN32) Sleep(INFINITE); + __assume(0); #else _dispatch_sigsuspend(); #endif From bd216a165ae3c917ae66c07af719e22c1dc1b0f6 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 11 Nov 2021 21:57:39 -0800 Subject: [PATCH 03/30] dispatch: make assertions LLP64 friendly (NFCI) Use `long long` rather than `long` for the value being asserted. This is important as there are many places where we use the assertions on pointer values, which would be truncated on a LLP64 environment. This helps clean up the warning spew on Windows. --- src/internal.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/internal.h b/src/internal.h index d22a3ac09..1beaa2269 100644 --- a/src/internal.h +++ b/src/internal.h @@ -587,11 +587,11 @@ void _dispatch_log(const char *msg, ...); */ DISPATCH_ALWAYS_INLINE static inline void -_dispatch_assert(long e, size_t line) DISPATCH_STATIC_ASSERT_IF(!e) +_dispatch_assert(long long e, size_t line) DISPATCH_STATIC_ASSERT_IF(!e) { if (unlikely(DISPATCH_DEBUG && !e)) _dispatch_abort(line, e); } -#define dispatch_assert(e) _dispatch_assert((long)(e), __LINE__) +#define dispatch_assert(e) _dispatch_assert((long long)(e), __LINE__) /* * A lot of API return zero upon success and not-zero on fail. Let's capture @@ -599,11 +599,11 @@ _dispatch_assert(long e, size_t line) DISPATCH_STATIC_ASSERT_IF(!e) */ DISPATCH_ALWAYS_INLINE static inline void -_dispatch_assert_zero(long e, size_t line) DISPATCH_STATIC_ASSERT_IF(e) +_dispatch_assert_zero(long long e, size_t line) DISPATCH_STATIC_ASSERT_IF(e) { if (unlikely(DISPATCH_DEBUG && e)) _dispatch_abort(line, e); } -#define dispatch_assert_zero(e) _dispatch_assert_zero((long)(e), __LINE__) +#define dispatch_assert_zero(e) _dispatch_assert_zero((long long)(e), __LINE__) /* * For reporting bugs or impedance mismatches between libdispatch and external @@ -613,12 +613,12 @@ _dispatch_assert_zero(long e, size_t line) DISPATCH_STATIC_ASSERT_IF(e) */ DISPATCH_ALWAYS_INLINE static inline void -_dispatch_assume(long e, size_t line) DISPATCH_STATIC_ASSERT_IF(!e) +_dispatch_assume(long long e, size_t line) DISPATCH_STATIC_ASSERT_IF(!e) { if (unlikely(!e)) _dispatch_bug(line, e); } #define dispatch_assume(e) \ - ({ __typeof__(e) _e = (e); _dispatch_assume((long)_e, __LINE__); _e; }) + ({ __typeof__(e) _e = (e); _dispatch_assume((long long)_e, __LINE__); _e; }) /* * A lot of API return zero upon success and not-zero on fail. Let's capture From a72dfbdbdfed5a8e6b60de67b8bdbee36a2e3eaa Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 11 Nov 2021 21:51:15 -0800 Subject: [PATCH 04/30] dispatch: host declaration of `dispatch_pthread_root_queue_observer_hooks_s` This type is referenced before the declaration. This hoists the declaration earlier to have the type available when used. --- src/queue_internal.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/queue_internal.h b/src/queue_internal.h index 68a5fec23..e9947aee6 100644 --- a/src/queue_internal.h +++ b/src/queue_internal.h @@ -445,6 +445,13 @@ DISPATCH_OPTIONS(dispatch_queue_flags, uint32_t, #pragma mark - #pragma mark dispatch_queue_t +typedef struct dispatch_pthread_root_queue_observer_hooks_s { + void (*queue_will_execute)(dispatch_queue_t queue); + void (*queue_did_execute)(dispatch_queue_t queue); +} dispatch_pthread_root_queue_observer_hooks_s; +typedef dispatch_pthread_root_queue_observer_hooks_s + *dispatch_pthread_root_queue_observer_hooks_t; + typedef struct dispatch_queue_specific_s { const void *dqs_key; void *dqs_ctxt; @@ -651,13 +658,6 @@ struct dispatch_queue_global_s { } DISPATCH_CACHELINE_ALIGN; -typedef struct dispatch_pthread_root_queue_observer_hooks_s { - void (*queue_will_execute)(dispatch_queue_t queue); - void (*queue_did_execute)(dispatch_queue_t queue); -} dispatch_pthread_root_queue_observer_hooks_s; -typedef dispatch_pthread_root_queue_observer_hooks_s - *dispatch_pthread_root_queue_observer_hooks_t; - #ifdef __APPLE__ #define DISPATCH_IOHID_SPI 1 From 220b32294d4e404eaf225fc8eca705484c9d2f53 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 11 Nov 2021 21:52:20 -0800 Subject: [PATCH 05/30] dispatch: adjust for LLP64 environments Use the internal `DISPATCH_SIZEOF_POINTER` rather than `__LP64__` which does not account for LLP64 environments. --- src/queue_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/queue_internal.h b/src/queue_internal.h index e9947aee6..0c4674ada 100644 --- a/src/queue_internal.h +++ b/src/queue_internal.h @@ -1240,7 +1240,7 @@ struct dispatch_apply_attr_s { uint32_t flags; size_t per_cluster_parallelism; uintptr_t guard; /* To prevent copying */ -#if defined(__LP64__) +#if DISPATCH_SIZEOF_PTR == 8 uint8_t unused[40]; #else uint8_t unused[48]; From 26a55112c5355ab68a27b8b0111ffb9b9a456791 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 11:34:13 -0800 Subject: [PATCH 06/30] dispatch: follow `os/base.h` inclusion pattern There are three different `base.h` headers, one meant for Apple platforms (`base.h`), one for Windows (`generic_win_base.h`), and one for Unix systems (`generic_unix_base.h`). Conditionally include the correct one for the build target as we do throughout the rest of dispatch for portability. --- os/clock.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/os/clock.h b/os/clock.h index 665e1d871..81832f3f8 100644 --- a/os/clock.h +++ b/os/clock.h @@ -1,7 +1,14 @@ #ifndef __OS_CLOCK__ #define __OS_CLOCK__ +#if defined(__APPLE__) #include +#elif defined(_WIN32) +#include +#elif defined(__unix__) +#include +#endif + #include /* From 7b5aa71b7916374981330992c1e6b99546c08a88 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 11:36:24 -0800 Subject: [PATCH 07/30] dispatch: exclude workgroup support on non-Apple targets Follow the advice from @MadCoder and limit workgroup headers to Apple targets only. This is required to restore the ability to build dispatch on other platforms. --- dispatch/dispatch.h | 2 ++ dispatch/workloop.h | 2 ++ os/eventlink_private.h | 5 ++++- src/internal.h | 6 ++++++ src/queue.c | 4 ++++ src/queue_internal.h | 2 ++ 6 files changed, 20 insertions(+), 1 deletion(-) diff --git a/dispatch/dispatch.h b/dispatch/dispatch.h index 9b517f36c..9c5bf101b 100644 --- a/dispatch/dispatch.h +++ b/dispatch/dispatch.h @@ -62,7 +62,9 @@ #endif #include +#if HAVE_MACH #include +#endif #include #include #include diff --git a/dispatch/workloop.h b/dispatch/workloop.h index 98c4f8a41..7ca103c35 100644 --- a/dispatch/workloop.h +++ b/dispatch/workloop.h @@ -133,6 +133,7 @@ void dispatch_workloop_set_autorelease_frequency(dispatch_workloop_t workloop, dispatch_autorelease_frequency_t frequency); +#if HAVE_MACH /*! * @function dispatch_workloop_set_os_workgroup * @@ -159,6 +160,7 @@ DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW void dispatch_workloop_set_os_workgroup(dispatch_workloop_t workloop, os_workgroup_t workgroup); +#endif __END_DECLS diff --git a/os/eventlink_private.h b/os/eventlink_private.h index eb55a745b..dded60765 100644 --- a/os/eventlink_private.h +++ b/os/eventlink_private.h @@ -1,8 +1,11 @@ #ifndef __OS_EVENTLINK__ #define __OS_EVENTLINK__ -#include +#if HAVE_MACH #include +#endif + +#include #include __BEGIN_DECLS diff --git a/src/internal.h b/src/internal.h index 1beaa2269..3f293ec8e 100644 --- a/src/internal.h +++ b/src/internal.h @@ -219,10 +219,12 @@ upcast(dispatch_object_t dou) #endif // __OBJC__ #include +#if HAVE_MACH #include #include #include #include +#endif #include #include #include @@ -241,8 +243,10 @@ upcast(dispatch_object_t dou) #endif #include "os/object_private.h" #include "os/eventlink_private.h" +#if HAVE_MACH #include "os/workgroup_object_private.h" #include "os/workgroup_interval_private.h" +#endif #include "apply_private.h" #include "queue_private.h" #include "channel_private.h" @@ -1180,7 +1184,9 @@ extern bool _dispatch_kevent_workqueue_enabled; /* #includes dependent on internal.h */ #include "object_internal.h" +#if HAVE_MACH #include "workgroup_internal.h" +#endif #include "eventlink_internal.h" #include "semaphore_internal.h" #include "introspection_internal.h" diff --git a/src/queue.c b/src/queue.c index 96bed5ed7..0e0f8d228 100644 --- a/src/queue.c +++ b/src/queue.c @@ -4056,9 +4056,11 @@ static void _dispatch_workloop_attributes_dispose(dispatch_workloop_t dwl) { if (dwl->dwl_attr) { +#if HAVE_MACH if (dwl->dwl_attr->workgroup) { _os_object_release(dwl->dwl_attr->workgroup->_as_os_obj); } +#endif free(dwl->dwl_attr); } } @@ -4127,6 +4129,7 @@ dispatch_workloop_set_qos_class_floor(dispatch_workloop_t dwl, #endif // TARGET_OS_MAC } +#if HAVE_MACH void dispatch_workloop_set_os_workgroup(dispatch_workloop_t dwl, os_workgroup_t wg) { @@ -4142,6 +4145,7 @@ dispatch_workloop_set_os_workgroup(dispatch_workloop_t dwl, os_workgroup_t wg) _os_object_retain(wg->_as_os_obj); dwl->dwl_attr->workgroup = wg; } +#endif void dispatch_workloop_set_qos_class(dispatch_workloop_t dwl, diff --git a/src/queue_internal.h b/src/queue_internal.h index 0c4674ada..120d8332c 100644 --- a/src/queue_internal.h +++ b/src/queue_internal.h @@ -482,7 +482,9 @@ typedef struct dispatch_workloop_attr_s { uint8_t percent; uint32_t refillms; } dwla_cpupercent; +#if HAVE_MACH os_workgroup_t workgroup; +#endif dispatch_pthread_root_queue_observer_hooks_s dwla_observers; } dispatch_workloop_attr_s; From 28c3270f8e1a9286b7f940c9d8709e7fcc785a3b Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 11:43:30 -0800 Subject: [PATCH 08/30] os: update unix and windows base.h This adds additional macros from base.h to the windows and unix variants to allow building dispatch on non-Apple targets. This ensures that we have: - `SPI_AVAILABLE` - `SPI_DEPRECATED` - `OS_REFINED_FOR_SWIFT` - `OS_SWIFT_NAME` consistently across all the targets. --- os/generic_unix_base.h | 8 ++++++++ os/generic_win_base.h | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/os/generic_unix_base.h b/os/generic_unix_base.h index aaf6f8504..9b0802c8d 100644 --- a/os/generic_unix_base.h +++ b/os/generic_unix_base.h @@ -40,6 +40,14 @@ #define API_DEPRECATED_WITH_REPLACEMENT(...) #endif +#ifndef SPI_AVAILABLE +#define SPI_AVAILABLE(...) +#endif + +#ifndef SPI_DEPRECATED +#define SPI_DEPRECATED(...) +#endif + #if __GNUC__ #define OS_EXPECT(x, v) __builtin_expect((x), (v)) #define OS_UNUSED __attribute__((__unused__)) diff --git a/os/generic_win_base.h b/os/generic_win_base.h index afc5f4265..0ba5bd028 100644 --- a/os/generic_win_base.h +++ b/os/generic_win_base.h @@ -46,6 +46,14 @@ typedef void pthread_attr_t; #define API_DEPRECATED_WITH_REPLACEMENT(...) #endif +#ifndef SPI_AVAILABLE +#define SPI_AVAILABLE(...) +#endif + +#ifndef SPI_DEPRECATED +#define SPI_DEPRECATED(...) +#endif + #if !defined(__has_attribute) #define __has_attribute(attibute) 0 #endif @@ -99,6 +107,18 @@ typedef void pthread_attr_t; #define OS_SWIFT_UNAVAILABLE(msg) #endif +#if __has_attribute(swift_private) +# define OS_REFINED_FOR_SWIFT __attribute__((__swift_private__)) +#else +# define OS_REFINED_FOR_SWIFT +#endif + +#if __has_attribute(swift_name) +# define OS_SWIFT_NAME(_name) __attribute__((__swift_name__(#_name))) +#else +# define OS_SWIFT_NAME(_name) +#endif + #define __OS_STRINGIFY(s) #s #define OS_STRINGIFY(s) __OS_STRINGIFY(s) From 025bbb446ad66bf49968b0edc9ff6c288c7a15f6 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 11:44:43 -0800 Subject: [PATCH 09/30] windows: add a shim for Windows This function was not previously used in all codepaths and was unavailable on Windows. This replicates the shim from the Unix path to Windows. --- src/event/event_windows.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/event/event_windows.c b/src/event/event_windows.c index 94674a3bf..a65dd8a3c 100644 --- a/src/event/event_windows.c +++ b/src/event/event_windows.c @@ -974,6 +974,12 @@ _dispatch_event_loop_end_ownership(dispatch_wlh_t wlh, uint64_t old_state, (void)wlh; (void)old_state; (void)new_state; (void)flags; } +void +_dispatch_event_loop_ensure_ownership(dispatch_wlh_t wlh) +{ + (void)wlh; +} + #if DISPATCH_WLH_DEBUG void _dispatch_event_loop_assert_not_owned(dispatch_wlh_t wlh) From 25758bd77d4fe97836a59aa5eea2f620081b25de Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 11:47:53 -0800 Subject: [PATCH 10/30] dispatch: exclude some mach_port_t usage This removes some `mach_port_t` usage in the eventlink support. Additionally guard the inclusion of a mach header with `HAVE_MACH` to allow building on non-Apple platforms. --- os/eventlink_private.h | 2 ++ src/internal.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/os/eventlink_private.h b/os/eventlink_private.h index dded60765..35dd315d0 100644 --- a/os/eventlink_private.h +++ b/os/eventlink_private.h @@ -111,6 +111,7 @@ OS_EXPORT OS_OBJECT_WARN_UNUSED_RESULT int os_eventlink_activate(os_eventlink_t eventlink); +#if HAVE_MACH /*! * @function os_eventlink_extract_remote_port * @@ -141,6 +142,7 @@ os_eventlink_extract_remote_port(os_eventlink_t eventlink, mach_port_t *port_out OS_EXPORT OS_OBJECT_RETURNS_RETAINED os_eventlink_t _Nullable os_eventlink_create_with_port(const char *name, mach_port_t mach_port); +#endif /*! * @function os_eventlink_create_remote_with_eventlink diff --git a/src/internal.h b/src/internal.h index 3f293ec8e..269ba866a 100644 --- a/src/internal.h +++ b/src/internal.h @@ -252,7 +252,9 @@ upcast(dispatch_object_t dou) #include "channel_private.h" #include "workloop_private.h" #include "source_private.h" +#if HAVE_MACH #include "mach_private.h" +#endif #include "data_private.h" #include "time_private.h" #include "os/voucher_private.h" From 811b4a1cabb038a3f2512d23cc83c3ecde937033 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 11:49:54 -0800 Subject: [PATCH 11/30] time: explicitly size the time macros The default backing for `enum` types on Windows are signed values, and the enumerators are handled via integer promotion to the type. Explicitly type the enums to ensure that the type is correct. --- dispatch/time.h | 2 +- private/time_private.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dispatch/time.h b/dispatch/time.h index 02dd27f6e..56a40a499 100644 --- a/dispatch/time.h +++ b/dispatch/time.h @@ -66,7 +66,7 @@ struct timespec; */ typedef uint64_t dispatch_time_t; -enum { +enum : unsigned long long { DISPATCH_WALLTIME_NOW DISPATCH_ENUM_API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = ~1ull, }; diff --git a/private/time_private.h b/private/time_private.h index e8dd1accf..6495af2c6 100644 --- a/private/time_private.h +++ b/private/time_private.h @@ -49,7 +49,7 @@ __BEGIN_DECLS * dispatch_source_set_timer(ds, t, 10 * NSEC_PER_SEC, 0); * dispatch_activate(ds); */ -enum { +enum : unsigned long long { DISPATCH_MONOTONICTIME_NOW DISPATCH_ENUM_API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = (1ull << 63) }; From e597c94fd3ec0e836141b5ef0436980a5ac4d9ea Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 13:16:58 -0800 Subject: [PATCH 12/30] dispatch: use reserved spelling for `typeof` `typeof` is a GNU extension, use the reserved spelling for the keyword. This allows clang to properly deal with this symbol on Windows builds. --- src/benchmark.c | 4 ++-- src/queue.c | 4 ++-- src/shims/atomic.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/benchmark.c b/src/benchmark.c index 259a67ca5..309c2106a 100644 --- a/src/benchmark.c +++ b/src/benchmark.c @@ -60,7 +60,7 @@ _dispatch_benchmark_init(void *context) } while (i < cnt); delta = _dispatch_uptime() - start; - lcost = (typeof(lcost)) delta; + lcost = (__typeof__(lcost)) delta; #if HAVE_MACH_ABSOLUTE_TIME lcost *= bdata->tbi.numer; lcost /= bdata->tbi.denom; @@ -113,7 +113,7 @@ dispatch_benchmark_f(size_t count, register void *ctxt, } while (i < count); delta = _dispatch_uptime() - start; - conversion = (typeof(conversion)) delta; + conversion = (__typeof__(conversion)) delta; #if HAVE_MACH_ABSOLUTE_TIME conversion *= bdata.tbi.numer; big_denom = bdata.tbi.denom; diff --git a/src/queue.c b/src/queue.c index 0e0f8d228..fd54e1a8d 100644 --- a/src/queue.c +++ b/src/queue.c @@ -5762,11 +5762,11 @@ dispatch_channel_enqueue(dispatch_channel_t dch, void *ctxt) #ifndef __APPLE__ #if __BLOCKS__ -void typeof(dispatch_channel_async) dispatch_channel_async +void __typeof__(dispatch_channel_async) dispatch_channel_async __attribute__((__alias__("dispatch_async"))); #endif -void typeof(dispatch_channel_async_f) dispatch_channel_async_f +void __typeof__(dispatch_channel_async_f) dispatch_channel_async_f __attribute__((__alias__("dispatch_async_f"))); #endif diff --git a/src/shims/atomic.h b/src/shims/atomic.h index 44af102eb..ce72755f3 100644 --- a/src/shims/atomic.h +++ b/src/shims/atomic.h @@ -137,7 +137,7 @@ typedef struct { unsigned long __opaque_zero; } os_atomic_dependency_t; #define OS_ATOMIC_DEPENDENCY_NONE ((os_atomic_dependency_t){ 0UL }) #define os_atomic_make_dependency(v) ((void)(v), OS_ATOMIC_DEPENDENCY_NONE) #define os_atomic_inject_dependency(p, e) \ - ((typeof(*(p)) *)((p) + _os_atomic_auto_dependency(e).__opaque_zero)) + ((__typeof__(*(p)) *)((p) + _os_atomic_auto_dependency(e).__opaque_zero)) #define os_atomic_load_with_dependency_on(p, e) \ os_atomic_load(os_atomic_inject_dependency(p, e), dependency) From 093d3a8f0c46afbc919977d721f35c4d91f58204 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 13:40:27 -0800 Subject: [PATCH 13/30] private: use `dispatch_qos_class_t` rather than `qos_class_t` The `qos_class_t` is typealiased as `disaptch_qos_class_t` in `dispatch/object.h` to allow portability for platforms which do not vend the type. Use this to allow building the new interfaces on Windows. --- private/channel_private.h | 2 +- private/queue_private.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/private/channel_private.h b/private/channel_private.h index 9c2ecf626..ca5ff7efc 100644 --- a/private/channel_private.h +++ b/private/channel_private.h @@ -259,7 +259,7 @@ dispatch_channel_create(const char *_Nullable label, API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0), bridgeos(4.0)) DISPATCH_EXPORT DISPATCH_NOTHROW DISPATCH_NONNULL_ALL void -dispatch_channel_wakeup(dispatch_channel_t channel, qos_class_t qos_class); +dispatch_channel_wakeup(dispatch_channel_t channel, dispatch_qos_class_t qos_class); /*! @typedef dispatch_channel_enumerator_handler_t * diff --git a/private/queue_private.h b/private/queue_private.h index 199fcaeed..011c1e3b7 100644 --- a/private/queue_private.h +++ b/private/queue_private.h @@ -537,7 +537,7 @@ SPI_AVAILABLE(macos(12.0), ios(15.0)) DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL2 void dispatch_async_swift_job(dispatch_queue_t queue, void *swift_job, - qos_class_t qos); + dispatch_qos_class_t qos); __END_DECLS From 48932f3279f0c3e22de19d1d6aadf70a8658043b Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 13:56:30 -0800 Subject: [PATCH 14/30] shims: convert `_dispatch_preemption_yeild` to an expression Because `_dispatch_preemption_yield` is used an expression as: ~~~ ((void) (q), _dispatch_preemption_yield(n)) ~~~ we need to convert the expansion to an expression. We _could_ also just wrap the invocation into a parenthesis as an alternative approach, but this should be safe enough to let us get away with it. --- src/shims/yield.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/shims/yield.h b/src/shims/yield.h index aeb429d44..fd8bf0088 100644 --- a/src/shims/yield.h +++ b/src/shims/yield.h @@ -161,14 +161,14 @@ void *_dispatch_wait_for_enqueuer(void **ptr, void **tailp); #define _dispatch_preemption_yield_to(th, n) thread_switch(th, \ DISPATCH_YIELD_THREAD_SWITCH_OPTION, (mach_msg_timeout_t)(n)) #elif HAVE_PTHREAD_YIELD_NP -#define _dispatch_preemption_yield(n) { (void)n; pthread_yield_np(); } -#define _dispatch_preemption_yield_to(th, n) { (void)n; pthread_yield_np(); } +#define _dispatch_preemption_yield(n) ({ (void)n; pthread_yield_np(); }) +#define _dispatch_preemption_yield_to(th, n) ({ (void)n; pthread_yield_np(); }) #elif defined(_WIN32) -#define _dispatch_preemption_yield(n) { (void)n; Sleep(0); } -#define _dispatch_preemption_yield_to(th, n) { (void)n; Sleep(0); } +#define _dispatch_preemption_yield(n) ({ (void)n; Sleep(0); }) +#define _dispatch_preemption_yield_to(th, n) ({ (void)n; Sleep(0); }) #else -#define _dispatch_preemption_yield(n) { (void)n; sched_yield(); } -#define _dispatch_preemption_yield_to(th, n) { (void)n; sched_yield(); } +#define _dispatch_preemption_yield(n) ({ (void)n; sched_yield(); }) +#define _dispatch_preemption_yield_to(th, n) ({ (void)n; sched_yield(); }) #endif // HAVE_MACH #if DISPATCH_HAVE_YIELD_TO_ENQUEUER From c1f36605e8ec5f3cd6dde75b0325d47da6abc72c Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 14:16:02 -0800 Subject: [PATCH 15/30] os: replace `__header_always_inline` with `DISPATCH_ALWAYS_INLINE` Since we build on non-XNU environments, we cannot rely on osfmk to provide the definition for `__header_always_inline`. Instead adopt `DISPATCH_ALWAYS_INLINE` to achieve the desired effect. --- os/voucher_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/voucher_private.h b/os/voucher_private.h index 3e72c919a..bb5cae3d6 100644 --- a/os/voucher_private.h +++ b/os/voucher_private.h @@ -128,7 +128,7 @@ voucher_adopt(voucher_t _Nullable voucher OS_OBJECT_CONSUMED); */ SPI_AVAILABLE(macos(12.0), ios(15.0)) -__header_always_inline bool +DISPATCH_ALWAYS_INLINE bool voucher_needs_adopt(voucher_t _Nullable voucher) { #if __APPLE__ From 956c270fa2ec5ebc131f0bd6eeb42a5d295f4b74 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 14:18:49 -0800 Subject: [PATCH 16/30] shims: add a definition for `os_atomic_init` This is adopted from osfmk to provide the `os_atomic_init` macro which still relies on the C11 atomics. --- src/shims/atomic.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shims/atomic.h b/src/shims/atomic.h index ce72755f3..df0af9c89 100644 --- a/src/shims/atomic.h +++ b/src/shims/atomic.h @@ -143,6 +143,8 @@ typedef struct { unsigned long __opaque_zero; } os_atomic_dependency_t; #define os_atomic_thread_fence(m) atomic_thread_fence(memory_order_##m) +#define os_atomic_init(p, v) atomic_init(_os_atomic_c11_atomic(p), v) + #define os_atomic_inc(p, m) \ os_atomic_add((p), 1, m) #define os_atomic_inc_orig(p, m) \ From 0bc1ee2969ae3a937f161a3f232db00a13fe77ef Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 14:26:06 -0800 Subject: [PATCH 17/30] dispatch: use platform specific paths for setting thread names This adds the Windows specific path for setting the thread name. This may only work partially as the thread name is meant to be UCS-2, but for now, matches the behaviour in Foundation. Similarly, on Linux, `pthread_setname_np` takes a thread identifier to set the name. Add a platform specific path here as well. --- src/queue.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/queue.c b/src/queue.c index fd54e1a8d..49a2281be 100644 --- a/src/queue.c +++ b/src/queue.c @@ -6988,7 +6988,19 @@ _dispatch_worker_thread(void *context) /* Set it up before the configure block so that it can get overridden by * client if they want to name their threads differently */ if (dq->_as_dq->dq_label) { +#if defined(__APPLE__) pthread_setname_np(dq->_as_dq->dq_label); +#elif defined(_WIN32) + int length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, dq->_as_dq->dq_label, -1, NULL, 0); + if (length) { + WCHAR *description = calloc(length + 1, sizeof(WCHAR)); + MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, dq->_as_dq->dq_label, -1, description, length); + SetThreadDescription(GetCurrentThread(), description); + free(description); + } +#else + pthread_setname_np(pthread_self(), dq->_as_dq->dq_label); +#endif } if (pqc->dpq_thread_configure) { From d5455e177ef67cfbabdafd1cadcf983583b658d8 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 14:29:30 -0800 Subject: [PATCH 18/30] shims: adopt `_os_atomic_auto_dependency` from osfmk This adds the missing shim for atomics from osfmk to allow usage of `_os_atomic_auto_dependency. --- src/shims/atomic.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/shims/atomic.h b/src/shims/atomic.h index df0af9c89..7832d544a 100644 --- a/src/shims/atomic.h +++ b/src/shims/atomic.h @@ -134,6 +134,11 @@ typedef struct { unsigned long __opaque_zero; } os_atomic_dependency_t; +#define _os_atomic_auto_dependency(e) \ + _Generic(e, \ + os_atomic_dependency_t: (e), \ + default: os_atomic_make_dependency(e)) + #define OS_ATOMIC_DEPENDENCY_NONE ((os_atomic_dependency_t){ 0UL }) #define os_atomic_make_dependency(v) ((void)(v), OS_ATOMIC_DEPENDENCY_NONE) #define os_atomic_inject_dependency(p, e) \ From 9502860ad1efb5f169ca4028e4f2d2c7fa5692ed Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 19 Nov 2021 13:01:12 -0800 Subject: [PATCH 19/30] dispatch: repair the signal thread construction on Windows Handle the signal thread construction on Windows by using `_beginthreadex` as POSIX threads are not used on Windows. This reapirs the build for Windows. --- src/queue.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/queue.c b/src/queue.c index 49a2281be..a75dde337 100644 --- a/src/queue.c +++ b/src/queue.c @@ -7835,6 +7835,15 @@ _dispatch_sig_thread(void *ctxt DISPATCH_UNUSED) #endif } +#if defined(_WIN32) +static unsigned WINAPI +_dispatch_sig_thread_thunk(LPVOID lpParameter) +{ + _dispatch_sig_thread(lpParameter); + return 0; +} +#endif + void dispatch_main(void) { @@ -7900,6 +7909,7 @@ _dispatch_queue_cleanup2(void) // See dispatch_main for call to _dispatch_sig_thread on linux. #ifndef __linux__ if (_dispatch_program_is_probably_callback_driven) { +#if defined(_POSIX_THREADS) pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); @@ -7909,6 +7919,13 @@ _dispatch_queue_cleanup2(void) DISPATCH_CLIENT_CRASH(r, "Unable to create signal thread"); } pthread_attr_destroy(&attr); +#else + uintptr_t hThread = 0; + if (unlikely(!(hThread = _beginthreadex(NULL, /* stack_size */ 0, _dispatch_sig_thread_thunk, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL)))) { + DISPATCH_CLIENT_CRASH(errno, "unable to create signal thread"); + } + CloseHandle((HANDLE)hThread); +#endif // this used to be here as a workaround for 6778970 // but removing it had bincompat fallouts :'( sleep(1); From 1ba15ff934920d2b8713010c220398d9a4c16a18 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 14:57:17 -0800 Subject: [PATCH 20/30] dispatch: remove an unused function This preprocesses away a function definition to avoid a warning on Windows. This cleans all but one warning on Windows. --- src/queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/queue.c b/src/queue.c index a75dde337..a96d23b2f 100644 --- a/src/queue.c +++ b/src/queue.c @@ -7989,7 +7989,7 @@ _dispatch_context_cleanup(void *ctxt) #pragma mark - #pragma mark dispatch_init -#if !DISPATCH_USE_COOPERATIVE_WORKQUEUE +#if !DISPATCH_USE_INTERNAL_WORKQUEUE && !DISPATCH_USE_COOPERATIVE_WORKQUEUE static void _dispatch_cooperative_root_queue_init_fallback(dispatch_queue_global_t dq) { From 100c055dae2d2cde740dbe5565d14ffc6cef7ebe Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 15:33:52 -0800 Subject: [PATCH 21/30] private: remove reference to mach.h This removes the reference to mach.h which is pulled in when building tests. This allows building tests on Windows. --- private/private.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/private/private.h b/private/private.h index e49d15c95..a98ecd835 100644 --- a/private/private.h +++ b/private/private.h @@ -67,7 +67,9 @@ #endif #include #include +#if HAVE_MACH #include +#endif #include #include #include From 8979120733195f8e8acd7f032e485f8b461219ae Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 16:10:47 -0800 Subject: [PATCH 22/30] dispatch: repair the context for the cooperative root queue The dispatch object context for the cooperative root queue was not initialized which resulted in the pthread root queue being invalid when initializing the root queues. This corrects the default value for the root queue. --- src/init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/init.c b/src/init.c index 08f790828..23b4ea722 100644 --- a/src/init.c +++ b/src/init.c @@ -342,6 +342,7 @@ struct dispatch_queue_global_s _dispatch_root_queues[] = { #define _DISPATCH_COOPERATIVE_ROOT_QUEUE_ENTRY(n, flags, ...) \ [_DISPATCH_ROOT_QUEUE_IDX(n, flags)] = { \ .do_vtable = DISPATCH_VTABLE(queue_concurrent), \ + .do_ctxt = _dispatch_root_queue_ctxt(_DISPATCH_ROOT_QUEUE_IDX(n, flags)), \ .dq_priority = flags | ((flags & DISPATCH_PRIORITY_FLAG_FALLBACK) ? \ _dispatch_priority_make_fallback(DISPATCH_QOS_##n) : \ _dispatch_priority_make(DISPATCH_QOS_##n, 0)), \ From fc4eb8814dc194bc9b52c02597dba79fb2d37ae6 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 16:12:05 -0800 Subject: [PATCH 23/30] Block: adjust the type constructor for Windows We need to add in the `rawValue:` label when constructing the types as identified by the compiler. --- src/swift/Block.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/swift/Block.swift b/src/swift/Block.swift index 71d998ba6..0387be845 100644 --- a/src/swift/Block.swift +++ b/src/swift/Block.swift @@ -41,7 +41,7 @@ public class DispatchWorkItem { public init(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], block: @escaping @convention(block) () -> ()) { #if os(Windows) && (arch(arm64) || arch(x86_64)) - let flags = dispatch_block_flags_t(UInt32(flags.rawValue)) + let flags = dispatch_block_flags_t(rawValue: UInt32(flags.rawValue)) #else let flags: dispatch_block_flags_t = numericCast(flags.rawValue) #endif @@ -53,7 +53,7 @@ public class DispatchWorkItem { // dispatch_block_t, as we know the lifetime of the block in question. internal init(flags: DispatchWorkItemFlags = [], noescapeBlock: () -> ()) { #if os(Windows) && (arch(arm64) || arch(x86_64)) - let flags = dispatch_block_flags_t(UInt32(flags.rawValue)) + let flags = dispatch_block_flags_t(rawValue: UInt32(flags.rawValue)) #else let flags: dispatch_block_flags_t = numericCast(flags.rawValue) #endif From f251ab890bde8469b7a4e6cd4401c9d75a39f72f Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 Nov 2021 16:12:38 -0800 Subject: [PATCH 24/30] Queue: make the Swift overlay build again This adjusts the construction of the `dispatch_autorelease_frequency_t` to explicitly add the `rawValue:` label and force unwrap the optional as identified by the compiler. --- src/swift/Queue.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/swift/Queue.swift b/src/swift/Queue.swift index fe7406c42..7b6e12a2e 100644 --- a/src/swift/Queue.swift +++ b/src/swift/Queue.swift @@ -98,13 +98,13 @@ extension DispatchQueue { switch self { case .inherit: // DISPATCH_AUTORELEASE_FREQUENCY_INHERIT - return CDispatch.dispatch_queue_attr_make_with_autorelease_frequency(attr, dispatch_autorelease_frequency_t(0)) + return CDispatch.dispatch_queue_attr_make_with_autorelease_frequency(attr, dispatch_autorelease_frequency_t(rawValue: 0)!) case .workItem: // DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM - return CDispatch.dispatch_queue_attr_make_with_autorelease_frequency(attr, dispatch_autorelease_frequency_t(1)) + return CDispatch.dispatch_queue_attr_make_with_autorelease_frequency(attr, dispatch_autorelease_frequency_t(rawValue: 1)!) case .never: // DISPATCH_AUTORELEASE_FREQUENCY_NEVER - return CDispatch.dispatch_queue_attr_make_with_autorelease_frequency(attr, dispatch_autorelease_frequency_t(2)) + return CDispatch.dispatch_queue_attr_make_with_autorelease_frequency(attr, dispatch_autorelease_frequency_t(rawValue: 2)!) } } else { return attr From 9d366f90b168094bcd11c3224645148807c22fff Mon Sep 17 00:00:00 2001 From: 3405691582 Date: Fri, 12 Nov 2021 19:20:40 -0500 Subject: [PATCH 25/30] Voucher portability fixes. * The `VOUCHER_USE_MACH_VOUCHER` branch defines `_voucher_atfork_parent` but the `#else` branch does not. Assume it should look like the implementation for `_voucher_atfork_child` nearby. * Compiler complains about `voucher_process_can_use_arbitrary_personas` not having a previous prototype. This actually isn't used anywhere outside the `VOUCHER_USE_MACH_VOUCHER` branch, so remove it. * Ensure `voucher_needs_adopt` is `static` inline, otherwise the linker gives "multiple definition" errors despite it being marked as inline. --- dispatch/base.h | 2 +- os/voucher_private.h | 3 ++- src/voucher.c | 7 +++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dispatch/base.h b/dispatch/base.h index 0a2370bd8..8e0a7bbf4 100644 --- a/dispatch/base.h +++ b/dispatch/base.h @@ -62,7 +62,7 @@ #define DISPATCH_CONST __attribute__((__const__)) #define DISPATCH_WARN_RESULT __attribute__((__warn_unused_result__)) #define DISPATCH_MALLOC __attribute__((__malloc__)) -#define DISPATCH_ALWAYS_INLINE __attribute__((__always_inline__)) +#define DISPATCH_ALWAYS_INLINE __attribute__((unused, __always_inline__)) #define DISPATCH_UNAVAILABLE __attribute__((__unavailable__)) #define DISPATCH_UNAVAILABLE_MSG(msg) __attribute__((__unavailable__(msg))) #elif defined(_MSC_VER) diff --git a/os/voucher_private.h b/os/voucher_private.h index bb5cae3d6..dec03b3c3 100644 --- a/os/voucher_private.h +++ b/os/voucher_private.h @@ -128,7 +128,7 @@ voucher_adopt(voucher_t _Nullable voucher OS_OBJECT_CONSUMED); */ SPI_AVAILABLE(macos(12.0), ios(15.0)) -DISPATCH_ALWAYS_INLINE bool +DISPATCH_ALWAYS_INLINE static bool voucher_needs_adopt(voucher_t _Nullable voucher) { #if __APPLE__ @@ -136,6 +136,7 @@ voucher_needs_adopt(voucher_t _Nullable voucher) return (((void *) voucher) != _pthread_getspecific_direct(OS_VOUCHER_TSD_KEY)); } #endif + (void)voucher; return true; } diff --git a/src/voucher.c b/src/voucher.c index 61f1643df..e4d5e72da 100644 --- a/src/voucher.c +++ b/src/voucher.c @@ -1987,14 +1987,13 @@ voucher_get_current_persona_proximate_info(struct proc_persona_info *persona_inf } #endif // __has_include() -bool -voucher_process_can_use_arbitrary_personas(void) +void +_voucher_activity_debug_channel_init(void) { - return false; } void -_voucher_activity_debug_channel_init(void) +_voucher_atfork_parent(void) { } From 7e9922043c33a043f6d7a75483f87707c4697cd2 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Sat, 13 Nov 2021 11:49:33 -0800 Subject: [PATCH 26/30] build: add an additional installed header The new revision adds a dispatch/workloop.h which is required to be installed. This adds that header to the install set. Without this header Swift is unable to build the Dispatch C module. --- dispatch/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/dispatch/CMakeLists.txt b/dispatch/CMakeLists.txt index 7f68ed381..8e033dfd3 100644 --- a/dispatch/CMakeLists.txt +++ b/dispatch/CMakeLists.txt @@ -13,6 +13,7 @@ install(FILES semaphore.h source.h time.h + workloop.h DESTINATION "${INSTALL_DISPATCH_HEADERS_DIR}") if(ENABLE_SWIFT) From 8ca15bcd7f60e9330835327b2ce994b76ee174a2 Mon Sep 17 00:00:00 2001 From: 3405691582 Date: Sun, 14 Nov 2021 13:33:59 -0500 Subject: [PATCH 27/30] Fix initializing of dispatch_block_flags_t. Without this change, `Block.swift` fails to compile complaining that "'numericCast' requires that 'dispatch_block_flags_t' conform to 'BinaryInteger'". A number of changes may have tickled this, possibly: improved recent type handling in the Swift compiler, more stringent handling of C enum types, or changes to the `DISPATCH_OPTIONS` macro. Regardless, this change solves the problem. --- src/swift/Block.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/swift/Block.swift b/src/swift/Block.swift index 0387be845..c9fd90a33 100644 --- a/src/swift/Block.swift +++ b/src/swift/Block.swift @@ -43,7 +43,7 @@ public class DispatchWorkItem { #if os(Windows) && (arch(arm64) || arch(x86_64)) let flags = dispatch_block_flags_t(rawValue: UInt32(flags.rawValue)) #else - let flags: dispatch_block_flags_t = numericCast(flags.rawValue) + let flags = dispatch_block_flags_t(rawValue: flags.rawValue) #endif _block = dispatch_block_create_with_qos_class(flags, qos.qosClass.rawValue.rawValue, Int32(qos.relativePriority), block) @@ -55,7 +55,7 @@ public class DispatchWorkItem { #if os(Windows) && (arch(arm64) || arch(x86_64)) let flags = dispatch_block_flags_t(rawValue: UInt32(flags.rawValue)) #else - let flags: dispatch_block_flags_t = numericCast(flags.rawValue) + let flags = dispatch_block_flags_t(rawValue: flags.rawValue) #endif _block = _swift_dispatch_block_create_noescape(flags, noescapeBlock) } From be92ae700afeadb8552290918611f61570e44d20 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 19 Nov 2021 13:08:38 -0800 Subject: [PATCH 28/30] dispatch: explicitly cast to avoid truncation warning Add an explicit cast from `void *` to `uintptr_t` before truncating the context to the `dispatch_flags_t`. Add an assertion to ensure that we are not dropping something. --- src/queue.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/queue.c b/src/queue.c index a96d23b2f..c746b4eba 100644 --- a/src/queue.c +++ b/src/queue.c @@ -794,7 +794,10 @@ _dispatch_async_redirect_invoke(dispatch_continuation_t dc, { dispatch_thread_frame_s dtf; struct dispatch_continuation_s *other_dc = dc->dc_other; - dispatch_invoke_flags_t ctxt_flags = (dispatch_invoke_flags_t)dc->dc_ctxt; +#if DISPATCH_SIZEOF_PTR == 8 + dispatch_assert(((uintptr_t)dc->dc_ctxt >> 32) == 0); +#endif + dispatch_invoke_flags_t ctxt_flags = (dispatch_invoke_flags_t)(uintptr_t)dc->dc_ctxt; // if we went through _dispatch_root_queue_push_override, // the "right" root queue was stuffed into dc_func dispatch_queue_global_t assumed_rq = (dispatch_queue_global_t)dc->dc_func; From c4c351608431ab108b3d57081cd23720b2ac37f2 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 19 Nov 2021 13:14:20 -0800 Subject: [PATCH 29/30] dispatch: remove stray `void` The functions are meant to be aliases that are exported. They should be defined to be the typeof the target function. This corrects the aliasing. --- src/queue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/queue.c b/src/queue.c index c746b4eba..0bbc11b43 100644 --- a/src/queue.c +++ b/src/queue.c @@ -5765,11 +5765,11 @@ dispatch_channel_enqueue(dispatch_channel_t dch, void *ctxt) #ifndef __APPLE__ #if __BLOCKS__ -void __typeof__(dispatch_channel_async) dispatch_channel_async +__typeof__(dispatch_channel_async) dispatch_channel_async __attribute__((__alias__("dispatch_async"))); #endif -void __typeof__(dispatch_channel_async_f) dispatch_channel_async_f +__typeof__(dispatch_channel_async_f) dispatch_channel_async_f __attribute__((__alias__("dispatch_async_f"))); #endif From ef765a323d446ddfdb1aa69dcf55b9bbda58cb4f Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 19 Nov 2021 13:42:32 -0800 Subject: [PATCH 30/30] shims: add a new HAVE_WAIT_ON_ADDRESS and adopt in locks This introduces a new `HAVE_WAIT_ON_ADDRESS` which is the equivalent to `HAVE_FUTEX` on Linux. Extend the other sites to use this rather than `defined(_WIN32)`. This identified a couple of additional sites that required updating which is included in this change now. --- src/shims/lock.c | 10 +++++++--- src/shims/lock.h | 18 +++++++++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/shims/lock.c b/src/shims/lock.c index 4a750b3bd..17f8f0fae 100644 --- a/src/shims/lock.c +++ b/src/shims/lock.c @@ -507,7 +507,7 @@ _dispatch_wait_on_address(uint32_t volatile *_address, uint32_t value, return _dispatch_futex_wait(address, value, &ts, FUTEX_PRIVATE_FLAG); } return _dispatch_futex_wait(address, value, NULL, FUTEX_PRIVATE_FLAG); -#elif defined(_WIN32) +#elif HAVE_WAIT_ON_ADDRESS return WaitOnAddress(address, &value, sizeof(value), INFINITE) == TRUE; #else #error _dispatch_wait_on_address unimplemented for this platform @@ -521,7 +521,7 @@ _dispatch_wake_by_address(uint32_t volatile *address) _dispatch_ulock_wake((uint32_t *)address, ULF_WAKE_ALL); #elif HAVE_FUTEX _dispatch_futex_wake((uint32_t *)address, INT_MAX, FUTEX_PRIVATE_FLAG); -#elif defined(_WIN32) +#elif HAVE_WAIT_ON_ADDRESS WakeByAddressAll((uint32_t *)address); #else (void)address; @@ -537,6 +537,8 @@ _dispatch_thread_event_signal_slow(dispatch_thread_event_t dte) _dispatch_ulock_wake(&dte->dte_value, 0); #elif HAVE_FUTEX _dispatch_futex_wake(&dte->dte_value, 1, FUTEX_PRIVATE_FLAG); +#elif HAVE_WAIT_ON_ADDRESS + WakeByAddressSingle(&dte->dte_value); #else _dispatch_sema4_signal(&dte->dte_sema, 1); #endif @@ -545,7 +547,7 @@ _dispatch_thread_event_signal_slow(dispatch_thread_event_t dte) void _dispatch_thread_event_wait_slow(dispatch_thread_event_t dte) { -#if HAVE_UL_COMPARE_AND_WAIT || HAVE_FUTEX +#if HAVE_UL_COMPARE_AND_WAIT || HAVE_FUTEX || HAVE_WAIT_ON_ADDRESS for (;;) { uint32_t value = os_atomic_load(&dte->dte_value, acquire); if (likely(value == 0)) return; @@ -558,6 +560,8 @@ _dispatch_thread_event_wait_slow(dispatch_thread_event_t dte) #elif HAVE_FUTEX _dispatch_futex_wait(&dte->dte_value, UINT32_MAX, NULL, FUTEX_PRIVATE_FLAG); +#elif HAVE_WAIT_ON_ADDRESS + WaitOnAddress(&dte->dte_value, &value, sizeof(value), INFINITE); #endif } #else diff --git a/src/shims/lock.h b/src/shims/lock.h index 9c602724c..de03d25fe 100644 --- a/src/shims/lock.h +++ b/src/shims/lock.h @@ -174,6 +174,14 @@ _dispatch_lock_has_failed_trylock(dispatch_lock lock_value) #endif #endif // HAVE_FUTEX +#ifndef HAVE_WAIT_ON_ADDRESS +#if defined(_WIN32) +#define HAVE_WAIT_ON_ADDRESS 1 +#else +#define HAVE_WIAT_ON_ADDRESS 0 +#endif +#endif + #if defined(__x86_64__) || defined(__i386__) || defined(__s390x__) #define DISPATCH_ONCE_USE_QUIESCENT_COUNTER 0 #elif __APPLE__ @@ -271,7 +279,7 @@ void _dispatch_wake_by_address(uint32_t volatile *address); * This locking primitive has no notion of ownership */ typedef struct dispatch_thread_event_s { -#if HAVE_UL_COMPARE_AND_WAIT || HAVE_FUTEX +#if HAVE_UL_COMPARE_AND_WAIT || HAVE_FUTEX || HAVE_WAIT_ON_ADDRESS // 1 means signalled but not waited on yet // UINT32_MAX means waited on, but not signalled yet // 0 is the initial and final state @@ -289,7 +297,7 @@ DISPATCH_ALWAYS_INLINE static inline void _dispatch_thread_event_init(dispatch_thread_event_t dte) { -#if HAVE_UL_COMPARE_AND_WAIT || HAVE_FUTEX +#if HAVE_UL_COMPARE_AND_WAIT || HAVE_FUTEX || HAVE_WAIT_ON_ADDRESS dte->dte_value = 0; #else _dispatch_sema4_init(&dte->dte_sema, _DSEMA4_POLICY_FIFO); @@ -300,7 +308,7 @@ DISPATCH_ALWAYS_INLINE static inline void _dispatch_thread_event_signal(dispatch_thread_event_t dte) { -#if HAVE_UL_COMPARE_AND_WAIT || HAVE_FUTEX +#if HAVE_UL_COMPARE_AND_WAIT || HAVE_FUTEX || HAVE_WAIT_ON_ADDRESS if (os_atomic_add_orig(&dte->dte_value, 1u, release) == 0) { // 0 -> 1 transition doesn't need a signal // force a wake even when the value is corrupt, @@ -318,7 +326,7 @@ DISPATCH_ALWAYS_INLINE static inline void _dispatch_thread_event_wait(dispatch_thread_event_t dte) { -#if HAVE_UL_COMPARE_AND_WAIT || HAVE_FUTEX +#if HAVE_UL_COMPARE_AND_WAIT || HAVE_FUTEX || HAVE_WAIT_ON_ADDRESS if (os_atomic_sub(&dte->dte_value, 1u, acquire) == 0) { // 1 -> 0 is always a valid transition, so we can return // for any other value, take the slow path which checks it's not corrupt @@ -334,7 +342,7 @@ DISPATCH_ALWAYS_INLINE static inline void _dispatch_thread_event_destroy(dispatch_thread_event_t dte) { -#if HAVE_UL_COMPARE_AND_WAIT || HAVE_FUTEX +#if HAVE_UL_COMPARE_AND_WAIT || HAVE_FUTEX || HAVE_WAIT_ON_ADDRESS // nothing to do dispatch_assert(dte->dte_value == 0); #else