diff --git a/cmake/modules/SwiftSupport.cmake b/cmake/modules/SwiftSupport.cmake index 4310b54c9..b67de9ced 100644 --- a/cmake/modules/SwiftSupport.cmake +++ b/cmake/modules/SwiftSupport.cmake @@ -23,6 +23,8 @@ function(get_swift_host_arch result_var_name) set("${result_var_name}" "armv7" PARENT_SCOPE) elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "armv7l") set("${result_var_name}" "armv7" PARENT_SCOPE) + elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "amd64") + set("${result_var_name}" "x86_64" PARENT_SCOPE) elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "AMD64") set("${result_var_name}" "x86_64" PARENT_SCOPE) elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "IA64") diff --git a/src/event/event_kevent.c b/src/event/event_kevent.c index 16b69b37d..16cc6cbf4 100644 --- a/src/event/event_kevent.c +++ b/src/event/event_kevent.c @@ -389,8 +389,13 @@ _dispatch_kevent_print_error(dispatch_kevent_t ke) case 0: return; case ERANGE: /* A broken QoS was passed to kevent_id() */ +#if defined(__APPLE__) DISPATCH_INTERNAL_CRASH(ke->qos, "Invalid kevent priority"); +#else + DISPATCH_INTERNAL_CRASH(0, "Invalid kevent priority"); +#endif default: +#if HAVE_MACH // log the unexpected error _dispatch_bug_kevent_client("kevent", _evfiltstr(ke->filter), !ke->udata ? NULL : @@ -398,6 +403,9 @@ _dispatch_kevent_print_error(dispatch_kevent_t ke) ke->flags & EV_ADD ? "add" : ke->flags & EV_ENABLE ? "enable" : "monitor", (int)ke->data, ke->ident, ke->udata, du); +#else + break; +#endif } } @@ -591,7 +599,6 @@ _dispatch_kq_create(intptr_t *fd_ptr) guardid_t guard = (uintptr_t)fd_ptr; kqfd = guarded_kqueue_np(&guard, GUARD_CLOSE | GUARD_DUP); #else - (void)guard_ptr; kqfd = kqueue(); #endif if (kqfd == -1) { @@ -743,7 +750,7 @@ _dispatch_kq_poll(dispatch_wlh_t wlh, dispatch_kevent_t ke, int n, switch (err) { case ENOMEM: _dispatch_temporary_resource_shortage(); - /* FALLTHROUGH */ + DISPATCH_FALLTHROUGH; case EINTR: goto retry; case EBADF: @@ -754,7 +761,7 @@ _dispatch_kq_poll(dispatch_wlh_t wlh, dispatch_kevent_t ke, int n, (flags & KEVENT_FLAG_DYNAMIC_KQ_MUST_EXIST)) { return 0; } - /* FALLTHROUGH */ + DISPATCH_FALLTHROUGH; #endif // DISPATCH_USE_KEVENT_WORKLOOP default: DISPATCH_CLIENT_CRASH(err, "Unexpected error from kevent"); @@ -860,7 +867,6 @@ _dispatch_kq_unote_set_kevent(dispatch_unote_t _du, dispatch_kevent_t dk, du->du_priority), #endif }; - (void)pp; // if DISPATCH_USE_KEVENT_QOS == 0 } DISPATCH_ALWAYS_INLINE @@ -985,6 +991,7 @@ _dispatch_sync_ipc_handoff_end(dispatch_wlh_t wlh, mach_port_t port) } #endif +#if DISPATCH_HAVE_DIRECT_KNOTES DISPATCH_NOINLINE static bool _dispatch_kq_unote_update(dispatch_wlh_t wlh, dispatch_unote_t _du, @@ -1055,6 +1062,7 @@ _dispatch_kq_unote_update(dispatch_wlh_t wlh, dispatch_unote_t _du, dispatch_assume_zero(r); return true; } +#endif // DISPATCH_HAVE_DIRECT_KNOTES #pragma mark dispatch_muxnote_t @@ -1300,6 +1308,7 @@ enum { DISPATCH_WORKLOOP_SYNC_END, }; +#if DISPATCH_USE_KEVENT_WORKLOOP static char const * const _dispatch_workloop_actions[] = { [DISPATCH_WORKLOOP_ASYNC] = "async", [DISPATCH_WORKLOOP_ASYNC_FROM_SYNC] = "async (from sync)", @@ -1316,6 +1325,7 @@ static char const * const _dispatch_workloop_actions[] = { [DISPATCH_WORKLOOP_SYNC_WAKE] = "sync-wake", [DISPATCH_WORKLOOP_SYNC_END] = "sync-end", }; +#endif // DISPATCH_USE_KEVENT_WORKLOOP void _dispatch_event_loop_atfork_child(void) diff --git a/src/init.c b/src/init.c index f4c3bae4c..e14e6eb38 100644 --- a/src/init.c +++ b/src/init.c @@ -1048,7 +1048,7 @@ _dispatch_bug_kevent_vanished(dispatch_unote_t du) "{ %p[%s], ident: %" PRIdPTR " / 0x%" PRIxPTR ", handler: %p }", dux_type(du._du)->dst_kind, dou._dq, dou._dq->dq_label ? dou._dq->dq_label : "", - du._du->du_ident, du._du->du_ident, func); + (intptr_t)du._du->du_ident, (intptr_t)du._du->du_ident, func); } #endif // RDAR_49023449 diff --git a/src/internal.h b/src/internal.h index cf4ccfe84..6f1ba1a96 100644 --- a/src/internal.h +++ b/src/internal.h @@ -36,7 +36,7 @@ #define __DISPATCH_BUILDING_DISPATCH__ #define __DISPATCH_INDIRECT__ -#ifdef __APPLE__ +#ifdef __APPLE__DISPATCH_USE_KEVENT_WORKLOOP #include #include #include @@ -277,6 +277,9 @@ upcast(dispatch_object_t dou) #include #include #endif +#if defined(__FreeBSD__) +#include +#endif // __FreeBSD__ #include #include #include diff --git a/src/io.c b/src/io.c index cbea654cb..ab247037c 100644 --- a/src/io.c +++ b/src/io.c @@ -22,7 +22,6 @@ #if defined(__FreeBSD__) #include -#define F_RDADVISE F_RDAHEAD #endif #ifndef DISPATCH_IO_DEBUG diff --git a/src/queue.c b/src/queue.c index 493de3f21..a5bdbb6ad 100644 --- a/src/queue.c +++ b/src/queue.c @@ -6467,7 +6467,7 @@ _dispatch_runloop_handle_is_valid(dispatch_runloop_handle_t handle) { #if TARGET_OS_MAC return MACH_PORT_VALID(handle); -#elif defined(__linux__) +#elif defined(__linux__) || defined(__FreeBSD__) return handle >= 0; #elif defined(_WIN32) return handle != NULL; @@ -6482,7 +6482,7 @@ _dispatch_runloop_queue_get_handle(dispatch_lane_t dq) { #if TARGET_OS_MAC return ((dispatch_runloop_handle_t)(uintptr_t)dq->do_ctxt); -#elif defined(__linux__) +#elif defined(__linux__) || defined(__FreeBSD__) // decode: 0 is a valid fd, so offset by 1 to distinguish from NULL return ((dispatch_runloop_handle_t)(uintptr_t)dq->do_ctxt) - 1; #elif defined(_WIN32) @@ -6499,7 +6499,7 @@ _dispatch_runloop_queue_set_handle(dispatch_lane_t dq, { #if TARGET_OS_MAC dq->do_ctxt = (void *)(uintptr_t)handle; -#elif defined(__linux__) +#elif defined(__linux__) || defined(__FreeBSD__) // encode: 0 is a valid fd, so offset by 1 to distinguish from NULL dq->do_ctxt = (void *)(uintptr_t)(handle + 1); #elif defined(_WIN32) @@ -6535,7 +6535,7 @@ _dispatch_runloop_queue_handle_init(void *ctxt) (void)dispatch_assume_zero(kr); handle = mp; -#elif defined(__linux__) +#elif defined(__linux__) || defined(__FreeBSD__) int fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); if (fd == -1) { int err = errno; @@ -6589,7 +6589,7 @@ _dispatch_runloop_queue_handle_dispose(dispatch_lane_t dq) kr = mach_port_destruct(mach_task_self(), mp, -1, guard); DISPATCH_VERIFY_MIG(kr); (void)dispatch_assume_zero(kr); -#elif defined(__linux__) +#elif defined(__linux__) || defined(__FreeBSD__) int rc = close(handle); (void)dispatch_assume_zero(rc); #elif defined(_WIN32) @@ -6622,7 +6622,7 @@ _dispatch_runloop_queue_class_poke(dispatch_lane_t dq) (void)dispatch_assume_zero(kr); break; } -#elif defined(__linux__) +#elif defined(__linux__) || defined(__FreeBSD__) int result; do { result = eventfd_write(handle, 1); diff --git a/src/shims/lock.c b/src/shims/lock.c index d4d63134a..07ea96cdd 100644 --- a/src/shims/lock.c +++ b/src/shims/lock.c @@ -56,6 +56,21 @@ _dispatch_thread_switch(dispatch_lock value, dispatch_lock_options_t flags, #endif #endif +#if defined(__FreeBSD__) +#if !HAVE_UL_UNFAIR_LOCK +DISPATCH_ALWAYS_INLINE +static inline void +_dispatch_thread_switch(dispatch_lock value, dispatch_lock_options_t flags, + uint32_t timeout) +{ + (void)value; + (void)flags; + (void)timeout; + sched_yield(); +} +#endif +#endif + #pragma mark - semaphores #if USE_MACH_SEM @@ -509,6 +524,16 @@ _dispatch_wait_on_address(uint32_t volatile *_address, uint32_t value, return _dispatch_futex_wait(address, value, NULL, FUTEX_PRIVATE_FLAG); #elif defined(_WIN32) return WaitOnAddress(address, &value, sizeof(value), INFINITE) == TRUE; +#elif defined(__FreeBSD__) + (void)flags; + if (nsecs != DISPATCH_TIME_FOREVER) { + struct timespec ts = { + .tv_sec = (__typeof__(ts.tv_sec))(nsecs / NSEC_PER_SEC), + .tv_nsec = (__typeof__(ts.tv_nsec))(nsecs % NSEC_PER_SEC), + }; + return _umtx_op((void*)address, UMTX_OP_WAIT_UINT, value, (void*)(uintptr_t)sizeof(struct timespec), (void*)&ts); + } + return _umtx_op((void*)address, UMTX_OP_WAIT_UINT, value, 0, 0); #else #error _dispatch_wait_on_address unimplemented for this platform #endif @@ -523,6 +548,8 @@ _dispatch_wake_by_address(uint32_t volatile *address) _dispatch_futex_wake((uint32_t *)address, INT_MAX, FUTEX_PRIVATE_FLAG); #elif defined(_WIN32) WakeByAddressAll((uint32_t *)address); +#elif defined(__FreeBSD__) + _umtx_op((void*)address, UMTX_OP_WAKE, INT_MAX, 0, 0); #else (void)address; #endif @@ -682,7 +709,7 @@ _dispatch_once_wait(dispatch_once_gate_t dgo) _dispatch_futex_wait(lock, (dispatch_lock)new_v, NULL, FUTEX_PRIVATE_FLAG); #else - _dispatch_thread_switch(new_v, 0, timeout++); + _dispatch_thread_switch((dispatch_lock)new_v, 0, timeout++); #endif (void)timeout; } diff --git a/src/shims/lock.h b/src/shims/lock.h index 6bf825aa7..3ea77250e 100644 --- a/src/shims/lock.h +++ b/src/shims/lock.h @@ -67,7 +67,7 @@ typedef uint32_t dispatch_lock; #define DLOCK_OWNER_MASK ((dispatch_lock)FUTEX_TID_MASK) #define DLOCK_WAITERS_BIT ((dispatch_lock)FUTEX_WAITERS) -#define DLOCK_FAILED_TRYLOCK_BIT ((dispatch_lock)FUTEX_OWNER_DIED) +#define DLOCK_FAILED_TRYLOCK_BIT ((dispatch_lock)FUTEX_OWNER_DIED)HAVE_UL_COMPARE_AND_WAIT #define DLOCK_OWNER_NULL ((dispatch_tid)0) #define _dispatch_tid_self() ((dispatch_tid)(_dispatch_get_tsd_base()->tid)) @@ -79,6 +79,29 @@ _dispatch_lock_owner(dispatch_lock lock_value) return lock_value & DLOCK_OWNER_MASK; } +#elif defined(__FreeBSD__) + +#include +#include +#include + +typedef uint32_t dispatch_tid; +typedef uint32_t dispatch_lock; + +#define DLOCK_OWNER_MASK ((dispatch_lock)0x3fffffff) +#define DLOCK_WAITERS_BIT ((dispatch_lock)UMUTEX_CONTESTED) +#define DLOCK_FAILED_TRYLOCK_BIT ((dispatch_lock)UMUTEX_RB_OWNERDEAD) + +#define DLOCK_OWNER_NULL ((dispatch_tid)UMUTEX_UNOWNED) +#define _dispatch_tid_self() ((dispatch_tid)(_dispatch_get_tsd_base()->tid)) + +DISPATCH_ALWAYS_INLINE +static inline dispatch_tid +_dispatch_lock_owner(dispatch_lock lock_value) +{ + return lock_value & DLOCK_OWNER_MASK; +} + #elif defined(_WIN32) #include diff --git a/src/swift/CMakeLists.txt b/src/swift/CMakeLists.txt index 53924723e..57dd5e2cc 100644 --- a/src/swift/CMakeLists.txt +++ b/src/swift/CMakeLists.txt @@ -32,6 +32,7 @@ target_compile_options(swiftDispatch PRIVATE "SHELL:-Xcc -fblocks" "SHELL:-Xcc -fmodule-map-file=${PROJECT_SOURCE_DIR}/dispatch/module.modulemap" "SHELL:-Xcc -I${PROJECT_SOURCE_DIR}") + set_target_properties(swiftDispatch PROPERTIES Swift_MODULE_NAME Dispatch Swift_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/swift diff --git a/src/swift/Source.swift b/src/swift/Source.swift index b4315c6cf..3a9fb779b 100644 --- a/src/swift/Source.swift +++ b/src/swift/Source.swift @@ -174,7 +174,7 @@ extension DispatchSource { } #endif -#if !os(Linux) && !os(Android) && !os(Windows) +#if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) public class func makeProcessSource(identifier: pid_t, eventMask: ProcessEvent, queue: DispatchQueue? = nil) -> DispatchSourceProcess { let source = dispatch_source_create(_swift_dispatch_source_type_PROC(), UInt(identifier), eventMask.rawValue, queue?.__wrapped) return DispatchSource(source: source) as DispatchSourceProcess @@ -224,7 +224,7 @@ extension DispatchSource { return DispatchSource(source: source) as DispatchSourceUserDataReplace } -#if !os(Linux) && !os(Android) && !os(Windows) +#if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) public class func makeFileSystemObjectSource(fileDescriptor: Int32, eventMask: FileSystemEvent, queue: DispatchQueue? = nil) -> DispatchSourceFileSystemObject { let source = dispatch_source_create(_swift_dispatch_source_type_VNODE(), UInt(fileDescriptor), eventMask.rawValue, queue?.__wrapped) return DispatchSource(source: source) as DispatchSourceFileSystemObject @@ -290,7 +290,7 @@ extension DispatchSourceMemoryPressure { } #endif -#if !os(Linux) && !os(Android) && !os(Windows) +#if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) extension DispatchSourceProcess { public var handle: pid_t { return pid_t(dispatch_source_get_handle(self as! DispatchSource)) diff --git a/src/swift/Wrapper.swift b/src/swift/Wrapper.swift index 1bf26b184..d9af9d703 100644 --- a/src/swift/Wrapper.swift +++ b/src/swift/Wrapper.swift @@ -181,7 +181,7 @@ extension DispatchSource : DispatchSourceMachSend, } #endif -#if !os(Linux) && !os(Android) && !os(Windows) +#if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) extension DispatchSource : DispatchSourceProcess, DispatchSourceFileSystemObject { } diff --git a/tests/bsdtestharness.c b/tests/bsdtestharness.c index ca52d6e97..30a2cddc4 100644 --- a/tests/bsdtestharness.c +++ b/tests/bsdtestharness.c @@ -151,7 +151,7 @@ main(int argc, char *argv[]) //fprintf(stderr, "pid = %d\n", pid); assert(pid > 0); -#if defined(__linux__) +#if defined(__linux__) || defined(__FreeBSD__) int status; struct rusage usage; struct timeval tv_stop, tv_wall; @@ -218,7 +218,7 @@ main(int argc, char *argv[]) #else dispatch_queue_t main_q = dispatch_get_main_queue(); - dispatch_source_t tmp_ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid, DISPATCH_PROC_EXIT, main_q); + dispatch_source_t tmp_ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, (uintptr_t)pid, DISPATCH_PROC_EXIT, main_q); assert(tmp_ds); dispatch_source_set_event_handler(tmp_ds, ^{ int status; diff --git a/tests/dispatch_apply.c b/tests/dispatch_apply.c index fa7fab53f..2b0ad4d03 100644 --- a/tests/dispatch_apply.c +++ b/tests/dispatch_apply.c @@ -80,7 +80,7 @@ static void busythread(void *ignored) static void test_apply_contended(dispatch_queue_t dq) { uint32_t activecpu; -#if defined(__linux__) || defined(__OpenBSD__) +#if defined(__linux__) || defined(__OpenBSD__) || defined(__FreeBSD__) activecpu = (uint32_t)sysconf(_SC_NPROCESSORS_ONLN); #elif defined(_WIN32) SYSTEM_INFO si; diff --git a/tests/dispatch_io_pipe.c b/tests/dispatch_io_pipe.c index f94438483..90c212236 100644 --- a/tests/dispatch_io_pipe.c +++ b/tests/dispatch_io_pipe.c @@ -90,6 +90,10 @@ test_get_pipe_buffer_size(int kind) CloseHandle(write_handle); }); return size; +#elif defined(__FreeBSD__) + // buffer size of blocking and non-blocking pipes is different on FreeBSD + (void)kind; + return PIPE_BUF; #else (void)kind; static dispatch_once_t once; diff --git a/tests/dispatch_select.c b/tests/dispatch_select.c index 6202711cb..b0758707d 100644 --- a/tests/dispatch_select.c +++ b/tests/dispatch_select.c @@ -39,7 +39,7 @@ void finish(void* cxt); void stage1(int stage) { -#if defined(_WIN32) +#if defined(_WIN32) || defined(__FreeBSD__) char *path = dispatch_test_get_large_file(); dispatch_fd_t fd = dispatch_test_fd_open(path, O_RDONLY); if (fd == -1)