diff --git a/CMakeLists.txt b/CMakeLists.txt index 43bc70db2..19ea9e08c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,6 +83,7 @@ option(BUILD_SHARED_LIBS "build shared libraries" ON) option(ENABLE_TESTING "build libdispatch tests" ON) if(CMAKE_SYSTEM_NAME STREQUAL Linux OR + CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL Android) set(USE_GOLD_LINKER_DEFAULT ON) else() @@ -95,6 +96,7 @@ set(DISPATCH_USE_THREAD_LOCAL_STORAGE ${ENABLE_THREAD_LOCAL_STORAGE}) if(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL Android OR + CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL Windows) set(ENABLE_INTERNAL_PTHREAD_WORKQUEUES_DEFAULT ON) else() @@ -120,6 +122,7 @@ option(INSTALL_PRIVATE_HEADERS "installs private headers in the same location as if(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL Android OR + CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL Windows) add_library(BlocksRuntime STATIC @@ -264,6 +267,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL Android) set(ENABLE_DTRACE_DEFAULT OFF) endif() +if(CMAKE_SYSTEM_NAME STREQUAL FreeBSD) + add_definitions(-D_WITH_DPRINTF) +endif() + if(ENABLE_DTRACE STREQUAL "") find_program(dtrace_EXECUTABLE dtrace) if(dtrace_EXECUTABLE) diff --git a/cmake/config.h.in b/cmake/config.h.in index c858589c0..12a253056 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -139,10 +139,10 @@ #cmakedefine HAVE_PTHREAD_MACHDEP_H /* Define to 1 if you have the `pthread_main_np' function. */ -#cmakedefine HAVE_PTHREAD_MAIN_NP +#cmakedefine01 HAVE_PTHREAD_MAIN_NP /* Define to 1 if you have the header file. */ -#cmakedefine HAVE_PTHREAD_NP_H +#cmakedefine01 HAVE_PTHREAD_NP_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_PTHREAD_QOS_H diff --git a/dispatch/base.h b/dispatch/base.h index 4c82b010c..0c5f8c98e 100644 --- a/dispatch/base.h +++ b/dispatch/base.h @@ -112,6 +112,14 @@ #define DISPATCH_LINUX_UNAVAILABLE() #endif +#ifdef __FreeBSD__ +#define DISPATCH_FREEBSD_UNAVAILABLE() \ + DISPATCH_UNAVAILABLE_MSG( \ + "This interface is unavailable on FreeBSD systems") +#else +#define DISPATCH_FREEBSD_UNAVAILABLE() +#endif + #ifndef DISPATCH_ALIAS_V2 #if TARGET_OS_MAC #define DISPATCH_ALIAS_V2(sym) __asm__("_" #sym "$V2") diff --git a/dispatch/dispatch.h b/dispatch/dispatch.h index 2d45b8356..a4b54593c 100644 --- a/dispatch/dispatch.h +++ b/dispatch/dispatch.h @@ -26,8 +26,8 @@ #include #include #include -#elif defined(__linux__) -#include +#elif defined(__linux__) || defined(__FreeBSD__) +#include #endif #include @@ -40,7 +40,7 @@ #endif #include -#if defined(__linux__) && defined(__has_feature) +#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__has_feature) #if __has_feature(modules) #if !defined(__arm__) #include // for off_t (to match Glibc.modulemap) diff --git a/os/CMakeLists.txt b/os/CMakeLists.txt index e1e93a4ef..2c4d32e66 100644 --- a/os/CMakeLists.txt +++ b/os/CMakeLists.txt @@ -4,7 +4,7 @@ install(FILES object.h - linux_base.h + generic_unix_base.h DESTINATION "${INSTALL_OS_HEADERS_DIR}") diff --git a/os/Makefile.am b/os/Makefile.am index d009a3753..8be68d7ff 100644 --- a/os/Makefile.am +++ b/os/Makefile.am @@ -10,7 +10,7 @@ endif os_HEADERS= \ object.h \ - linux_base.h + generic_unix_base.h noinst_HEADERS= \ object_private.h \ diff --git a/os/linux_base.h b/os/generic_unix_base.h similarity index 94% rename from os/linux_base.h rename to os/generic_unix_base.h index 58b497148..26c664c12 100644 --- a/os/linux_base.h +++ b/os/generic_unix_base.h @@ -10,12 +10,17 @@ * */ -#ifndef __OS_LINUX_BASE__ -#define __OS_LINUX_BASE__ +#ifndef __OS_GENERIC_UNIX_BASE__ +#define __OS_GENERIC_UNIX_BASE__ #if __has_include() #include #endif + +#if defined(__FreeBSD__) +#include +#include +#endif #include #if __has_include() @@ -120,4 +125,4 @@ enum { __VA_ARGS__ }; typedef _type _name##_t #endif #define OS_NOTHROW -#endif /* __OS_LINUX_BASE__ */ +#endif /* __OS_GENERIC_UNIX_BASE__ */ diff --git a/os/object.h b/os/object.h index 100721fc0..3666c332a 100644 --- a/os/object.h +++ b/os/object.h @@ -26,8 +26,8 @@ #include #include #include -#elif defined(__linux__) -#include +#elif defined(__linux__) || defined(__FreeBSD__) +#include #endif /*! diff --git a/os/voucher_activity_private.h b/os/voucher_activity_private.h index 8ce0ef583..3df90234d 100644 --- a/os/voucher_activity_private.h +++ b/os/voucher_activity_private.h @@ -26,7 +26,7 @@ #include #include #endif -#ifndef __linux__ +#if __APPLE__ #include #include #endif diff --git a/os/voucher_private.h b/os/voucher_private.h index aecbbc9ff..3e28091ef 100644 --- a/os/voucher_private.h +++ b/os/voucher_private.h @@ -21,7 +21,7 @@ #ifndef __OS_VOUCHER_PRIVATE__ #define __OS_VOUCHER_PRIVATE__ -#ifndef __linux__ +#if __APPLE__ #include #include #endif diff --git a/private/private.h b/private/private.h index 228ce2c19..cb4f6769a 100644 --- a/private/private.h +++ b/private/private.h @@ -32,8 +32,8 @@ #include #include #include -#elif defined(__linux__) -#include +#elif defined(__linux__) || defined(__FreeBSD__) +#include #endif #if TARGET_OS_MAC @@ -172,7 +172,7 @@ void _dispatch_prohibit_transition_to_multithreaded(bool prohibit); #if TARGET_OS_MAC #define DISPATCH_COCOA_COMPAT 1 -#elif defined(__linux__) +#elif defined(__linux__) || defined(__FreeBSD__) #define DISPATCH_COCOA_COMPAT 1 #else #define DISPATCH_COCOA_COMPAT 0 @@ -184,7 +184,7 @@ void _dispatch_prohibit_transition_to_multithreaded(bool prohibit); #if TARGET_OS_MAC typedef mach_port_t dispatch_runloop_handle_t; -#elif defined(__linux__) +#elif defined(__linux__) || defined(__FreeBSD__) typedef int dispatch_runloop_handle_t; #else #error "runloop support not implemented on this platform" diff --git a/private/queue_private.h b/private/queue_private.h index 06fca91b5..f71e5e37f 100644 --- a/private/queue_private.h +++ b/private/queue_private.h @@ -49,6 +49,13 @@ enum { #define DISPATCH_QUEUE_FLAGS_MASK (DISPATCH_QUEUE_OVERCOMMIT) +// On FreeBSD pthread_attr_t is a typedef to a pointer type +#if defined(__FreeBSD__) +# define DISPATCH_QUEUE_NULLABLE_PTHREAD_ATTR_PTR _Nullable +#else +# define DISPATCH_QUEUE_NULLABLE_PTHREAD_ATTR_PTR +#endif + /*! * @function dispatch_queue_attr_make_with_overcommit * @@ -227,7 +234,7 @@ DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT DISPATCH_NOTHROW dispatch_queue_t dispatch_pthread_root_queue_create(const char *_Nullable label, - unsigned long flags, const pthread_attr_t *_Nullable attr, + unsigned long flags, const pthread_attr_t DISPATCH_QUEUE_NULLABLE_PTHREAD_ATTR_PTR *_Nullable attr, dispatch_block_t _Nullable configure); /*! diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0dd6a3cfb..c9c55b5f2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -47,8 +47,8 @@ add_library(dispatch shims/atomic_sfb.h shims/getprogname.h shims/hw_config.h - shims/linux_stubs.c - shims/linux_stubs.h + shims/generic_unix_stubs.c + shims/generic_unix_stubs.h shims/lock.c shims/lock.h shims/perfmon.h @@ -101,6 +101,7 @@ if(ENABLE_SWIFT) -fmodule-map-file=${CMAKE_SOURCE_DIR}/dispatch/module.modulemap SWIFT_FLAGS -I ${CMAKE_SOURCE_DIR} + -I/usr/include ${swift_optimization_flags} DEPENDS ${CMAKE_SOURCE_DIR}/dispatch/module.modulemap) diff --git a/src/Makefile.am b/src/Makefile.am index 58dcead4b..e6d31f545 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -59,8 +59,8 @@ libdispatch_la_SOURCES= \ shims/atomic_sfb.h \ shims/getprogname.h \ shims/hw_config.h \ - shims/linux_stubs.c \ - shims/linux_stubs.h \ + shims/generic_unix_stubs.c \ + shims/generic_unix_stubs.h \ shims/lock.c \ shims/lock.h \ shims/perfmon.h \ diff --git a/src/block.cpp b/src/block.cpp index 2a6f00799..6936ada90 100644 --- a/src/block.cpp +++ b/src/block.cpp @@ -109,7 +109,7 @@ extern "C" { // The compiler hides the name of the function it generates, and changes it if // we try to reference it directly, but the linker still sees it. extern void DISPATCH_BLOCK_SPECIAL_INVOKE(void *) -#ifdef __linux__ +#if defined(__linux__) || defined(__FreeBSD__) asm("___dispatch_block_create_block_invoke"); #else asm("____dispatch_block_create_block_invoke"); diff --git a/src/event/event_config.h b/src/event/event_config.h index 60f776f95..02508c081 100644 --- a/src/event/event_config.h +++ b/src/event/event_config.h @@ -76,16 +76,14 @@ #if DISPATCH_EVENT_BACKEND_KEVENT # if defined(EV_SET_QOS) # define DISPATCH_USE_KEVENT_QOS 1 -# ifndef KEVENT_FLAG_IMMEDIATE -# define KEVENT_FLAG_IMMEDIATE 0x001 -# endif -# ifndef KEVENT_FLAG_ERROR_EVENTS -# define KEVENT_FLAG_ERROR_EVENTS 0x002 -# endif # else # define DISPATCH_USE_KEVENT_QOS 0 # endif +# ifndef KEVENT_FLAG_ERROR_EVENTS +# define KEVENT_FLAG_ERROR_EVENTS 0x002 +# endif + # ifdef NOTE_LEEWAY # define DISPATCH_HAVE_TIMER_COALESCING 1 # else @@ -106,6 +104,14 @@ # define NOTE_FUNLOCK 0x00000100 # endif +// FreeBSD's kevent does not support those +# ifndef NOTE_ABSOLUTE +# define NOTE_ABSOLUTE 0 +# endif +# ifndef NOTE_EXITSTATUS +# define NOTE_EXITSTATUS 0 +# endif + # if HAVE_DECL_NOTE_REAP # if defined(NOTE_REAP) && defined(__APPLE__) # undef NOTE_REAP @@ -146,9 +152,15 @@ # define DISPATCH_HAVE_TIMER_QOS 0 # define DISPATCH_HAVE_TIMER_COALESCING 0 -# define KEVENT_FLAG_IMMEDIATE 0x001 #endif // !DISPATCH_EVENT_BACKEND_KEVENT +// These flags are used by dispatch generic code and +// translated back by the various backends to similar semantics +// hence must be defined even on non Darwin platforms +#ifndef KEVENT_FLAG_IMMEDIATE +# define KEVENT_FLAG_IMMEDIATE 0x001 +#endif + #ifdef EV_UDATA_SPECIFIC # define DISPATCH_EV_DIRECT (EV_UDATA_SPECIFIC|EV_DISPATCH) #else diff --git a/src/event/event_kevent.c b/src/event/event_kevent.c index 8fe76d55c..e7dafc7a7 100644 --- a/src/event/event_kevent.c +++ b/src/event/event_kevent.c @@ -32,6 +32,8 @@ #define DISPATCH_KEVENT_MUXED_MARKER 1ul #define DISPATCH_MACH_AUDIT_TOKEN_PID (5) +#define dispatch_kevent_udata_t typeof(((dispatch_kevent_t)NULL)->udata) + typedef struct dispatch_muxnote_s { TAILQ_ENTRY(dispatch_muxnote_s) dmn_list; TAILQ_HEAD(, dispatch_unote_linkage_s) dmn_unotes_head; @@ -59,8 +61,13 @@ DISPATCH_CACHELINE_ALIGN static TAILQ_HEAD(dispatch_muxnote_bucket_s, dispatch_muxnote_s) _dispatch_sources[DSL_HASH_SIZE]; +#if defined(__APPLE__) #define DISPATCH_NOTE_CLOCK_WALL NOTE_MACH_CONTINUOUS_TIME #define DISPATCH_NOTE_CLOCK_MACH 0 +#else +#define DISPATCH_NOTE_CLOCK_WALL 0 +#define DISPATCH_NOTE_CLOCK_MACH 0 +#endif static const uint32_t _dispatch_timer_index_to_fflags[] = { #define DISPATCH_TIMER_FFLAGS_INIT(kind, qos, note) \ @@ -191,17 +198,20 @@ dispatch_kevent_debug(const char *verb, const dispatch_kevent_s *kev, _dispatch_debug("%s kevent[%p] %s= { ident = 0x%llx, filter = %s, " "flags = %s (0x%x), fflags = 0x%x, data = 0x%llx, udata = 0x%llx, " "qos = 0x%x, ext[0] = 0x%llx, ext[1] = 0x%llx, ext[2] = 0x%llx, " - "ext[3] = 0x%llx }: %s #%u", verb, kev, i_n, kev->ident, - _evfiltstr(kev->filter), _evflagstr(kev->flags, flagstr, - sizeof(flagstr)), kev->flags, kev->fflags, kev->data, kev->udata, - kev->qos, kev->ext[0], kev->ext[1], kev->ext[2], kev->ext[3], + "ext[3] = 0x%llx }: %s #%u", verb, kev, i_n, + (unsigned long long)kev->ident, _evfiltstr(kev->filter), + _evflagstr(kev->flags, flagstr, sizeof(flagstr)), kev->flags, kev->fflags, + (unsigned long long)kev->data, (unsigned long long)kev->udata, kev->qos, + kev->ext[0], kev->ext[1], kev->ext[2], kev->ext[3], function, line); #else _dispatch_debug("%s kevent[%p] %s= { ident = 0x%llx, filter = %s, " "flags = %s (0x%x), fflags = 0x%x, data = 0x%llx, udata = 0x%llx}: " "%s #%u", verb, kev, i_n, - kev->ident, _evfiltstr(kev->filter), _evflagstr(kev->flags, flagstr, - sizeof(flagstr)), kev->flags, kev->fflags, kev->data, kev->udata, + (unsigned long long)kev->ident, _evfiltstr(kev->filter), + _evflagstr(kev->flags, flagstr, sizeof(flagstr)), kev->flags, + kev->fflags, (unsigned long long)kev->data, + (unsigned long long)kev->udata, function, line); #endif } @@ -333,11 +343,18 @@ _dispatch_kevent_get_muxnote(dispatch_kevent_t ke) return (dispatch_muxnote_t)dmn_addr; } +DISPATCH_ALWAYS_INLINE +static inline bool +_dispatch_kevent_unote_is_muxed(dispatch_kevent_t ke) +{ + return ((uintptr_t)ke->udata) & DISPATCH_KEVENT_MUXED_MARKER; +} + DISPATCH_ALWAYS_INLINE static dispatch_unote_t _dispatch_kevent_get_unote(dispatch_kevent_t ke) { - dispatch_assert((ke->udata & DISPATCH_KEVENT_MUXED_MARKER) == 0); + dispatch_assert(_dispatch_kevent_unote_is_muxed(ke) == false); return (dispatch_unote_t){ ._du = (dispatch_unote_class_t)ke->udata }; } @@ -356,7 +373,7 @@ _dispatch_kevent_print_error(dispatch_kevent_t ke) } // for EV_DELETE if the update was deferred we may have reclaimed // the udata already, and it is unsafe to dereference it now. - } else if (ke->udata & DISPATCH_KEVENT_MUXED_MARKER) { + } else if (_dispatch_kevent_unote_is_muxed(ke)) { ke->flags |= _dispatch_kevent_get_muxnote(ke)->dmn_kev.flags; } else if (ke->udata) { if (!_dispatch_unote_registered(_dispatch_kevent_get_unote(ke))) { @@ -463,7 +480,7 @@ _dispatch_kevent_drain(dispatch_kevent_t ke) } #endif - if (ke->udata & DISPATCH_KEVENT_MUXED_MARKER) { + if (_dispatch_kevent_unote_is_muxed(ke)) { return _dispatch_kevent_merge_muxed(ke); } return _dispatch_kevent_merge(_dispatch_kevent_get_unote(ke), ke); @@ -480,7 +497,7 @@ _dispatch_kq_create(const void *guard_ptr) .ident = 1, .filter = EVFILT_USER, .flags = EV_ADD|EV_CLEAR, - .udata = (uintptr_t)DISPATCH_WLH_MANAGER, + .udata = (dispatch_kevent_udata_t)DISPATCH_WLH_MANAGER, }; int kqfd; @@ -542,7 +559,7 @@ _dispatch_kq_init(void *context) .filter = EVFILT_USER, .flags = EV_ADD|EV_CLEAR, .qos = _PTHREAD_PRIORITY_EVENT_MANAGER_FLAG, - .udata = (uintptr_t)DISPATCH_WLH_MANAGER, + .udata = (dispatch_kevent_udata_t)DISPATCH_WLH_MANAGER, }; retry: r = kevent_qos(kqfd, &ke, 1, NULL, 0, NULL, NULL, @@ -601,7 +618,7 @@ _dispatch_kq_poll(dispatch_wlh_t wlh, dispatch_kevent_t ke, int n, for (r = 0; r < n; r++) { ke[r].flags |= EV_RECEIPT; } - out_n = n; + n_out = n; } #endif @@ -614,6 +631,8 @@ _dispatch_kq_poll(dispatch_wlh_t wlh, dispatch_kevent_t ke, int n, } r = kevent_qos(kqfd, ke, n, ke_out, n_out, buf, avail, flags); #else + (void)buf; + (void)avail; const struct timespec timeout_immediately = {}, *timeout = NULL; if (flags & KEVENT_FLAG_IMMEDIATE) timeout = &timeout_immediately; r = kevent(kqfd, ke, n, ke_out, n_out, timeout); @@ -717,19 +736,20 @@ _dispatch_kq_unote_set_kevent(dispatch_unote_t _du, dispatch_kevent_t dk, .ident = du->du_ident, .filter = dst->dst_filter, .flags = flags, - .udata = (uintptr_t)du, + .udata = (dispatch_kevent_udata_t)du, .fflags = du->du_fflags | dst->dst_fflags, .data = (typeof(dk->data))dst->dst_data, #if DISPATCH_USE_KEVENT_QOS .qos = (typeof(dk->qos))pp, #endif }; + (void)pp; // if DISPATCH_USE_KEVENT_QOS == 0 } DISPATCH_ALWAYS_INLINE static inline int _dispatch_kq_deferred_find_slot(dispatch_deferred_items_t ddi, - int16_t filter, uint64_t ident, uint64_t udata) + int16_t filter, uint64_t ident, dispatch_kevent_udata_t udata) { dispatch_kevent_t events = ddi->ddi_eventlist; int i; @@ -825,7 +845,7 @@ _dispatch_kq_unote_update(dispatch_wlh_t wlh, dispatch_unote_t _du, if (ddi && wlh == _dispatch_get_wlh()) { int slot = _dispatch_kq_deferred_find_slot(ddi, - du->du_filter, du->du_ident, (uintptr_t)du); + du->du_filter, du->du_ident, (dispatch_kevent_udata_t)du); if (slot < ddi->ddi_nevents) { // when deleting and an enable is pending, // we must merge EV_ENABLE to do an immediate deletion @@ -924,6 +944,7 @@ _dispatch_muxnote_find(struct dispatch_muxnote_bucket_s *dmb, #define _dispatch_unote_muxnote_find(dmb, du, wlh) \ _dispatch_muxnote_find(dmb, wlh, du._du->du_ident, du._du->du_filter) +#if HAVE_MACH DISPATCH_ALWAYS_INLINE static inline dispatch_muxnote_t _dispatch_mach_muxnote_find(mach_port_t name, int16_t filter) @@ -932,6 +953,7 @@ _dispatch_mach_muxnote_find(mach_port_t name, int16_t filter) dmb = _dispatch_muxnote_bucket(name, filter); return _dispatch_muxnote_find(dmb, DISPATCH_WLH_ANON, name, filter); } +#endif DISPATCH_NOINLINE static bool @@ -961,7 +983,8 @@ _dispatch_unote_register_muxed(dispatch_unote_t du, dispatch_wlh_t wlh) #if DISPATCH_USE_KEVENT_QOS dmn->dmn_kev.qos = _PTHREAD_PRIORITY_EVENT_MANAGER_FLAG; #endif - dmn->dmn_kev.udata = (uintptr_t)dmn | DISPATCH_KEVENT_MUXED_MARKER; + dmn->dmn_kev.udata = (dispatch_kevent_udata_t)((uintptr_t)dmn | + DISPATCH_KEVENT_MUXED_MARKER); dmn->dmn_wlh = wlh; if (unlikely(du._du->du_type->dst_update_mux)) { installed = du._du->du_type->dst_update_mux(dmn); @@ -984,11 +1007,13 @@ _dispatch_unote_register_muxed(dispatch_unote_t du, dispatch_wlh_t wlh) TAILQ_INSERT_TAIL(&dmn->dmn_unotes_head, dul, du_link); dul->du_muxnote = dmn; +#if HAVE_MACH if (du._du->du_filter == DISPATCH_EVFILT_MACH_NOTIFICATION) { bool armed = DISPATCH_MACH_NOTIFICATION_ARMED(&dmn->dmn_kev); os_atomic_store2o(du._dmsr, dmsr_notification_armed, armed,relaxed); } du._du->du_wlh = DISPATCH_WLH_ANON; +#endif } return installed; } @@ -1038,9 +1063,12 @@ _dispatch_unote_unregister_muxed(dispatch_unote_t du, uint32_t flags) dispatch_muxnote_t dmn = dul->du_muxnote; bool update = false, dispose = false; +#if HAVE_MACH if (dmn->dmn_kev.filter == DISPATCH_EVFILT_MACH_NOTIFICATION) { os_atomic_store2o(du._dmsr, dmsr_notification_armed, false, relaxed); } +#endif + dispatch_assert(du._du->du_wlh == DISPATCH_WLH_ANON); du._du->du_wlh = NULL; TAILQ_REMOVE(&dmn->dmn_unotes_head, dul, du_link); @@ -1129,7 +1157,7 @@ _dispatch_event_loop_poke(dispatch_wlh_t wlh, uint64_t dq_state, uint32_t flags) .ident = 1, .filter = EVFILT_USER, .fflags = NOTE_TRIGGER, - .udata = (uintptr_t)DISPATCH_WLH_MANAGER, + .udata = (dispatch_kevent_udata_t)DISPATCH_WLH_MANAGER, }; return _dispatch_kq_deferred_update(DISPATCH_WLH_ANON, &ke); } else if (wlh && wlh != DISPATCH_WLH_ANON) { @@ -1262,7 +1290,7 @@ _dispatch_event_loop_timer_program(uint32_t tidx, .flags = action | EV_ONESHOT, .fflags = _dispatch_timer_index_to_fflags[tidx], .data = (int64_t)target, - .udata = (uintptr_t)&_dispatch_timers_heap[tidx], + .udata = (dispatch_kevent_udata_t)&_dispatch_timers_heap[tidx], #if DISPATCH_HAVE_TIMER_COALESCING .ext[1] = leeway, #endif @@ -1270,6 +1298,7 @@ _dispatch_event_loop_timer_program(uint32_t tidx, .qos = _PTHREAD_PRIORITY_EVENT_MANAGER_FLAG, #endif }; + (void)leeway; // if DISPATCH_HAVE_TIMER_COALESCING == 0 _dispatch_kq_deferred_update(DISPATCH_WLH_ANON, &ke); } @@ -1927,11 +1956,13 @@ _dispatch_mach_notification_set_armed(dispatch_mach_send_refs_t dmsr) return; } +#if HAVE_MACH DISPATCH_MACH_NOTIFICATION_ARMED(&dmn->dmn_kev) = true; TAILQ_FOREACH(dul, &dmn->dmn_unotes_head, du_link) { du = _dispatch_unote_linkage_get_unote(dul); os_atomic_store2o(du._dmsr, dmsr_notification_armed, true, relaxed); } +#endif } static dispatch_unote_t diff --git a/src/event/workqueue.c b/src/event/workqueue.c index 73362a58a..19a247671 100644 --- a/src/event/workqueue.c +++ b/src/event/workqueue.c @@ -66,7 +66,9 @@ typedef struct dispatch_workq_monitor_s { int num_registered_tids; } dispatch_workq_monitor_s, *dispatch_workq_monitor_t; +#if HAVE_DISPATCH_WORKQ_MONITORING static dispatch_workq_monitor_s _dispatch_workq_monitors[DISPATCH_QOS_MAX]; +#endif #pragma mark Implementation of the monitoring subsystem. @@ -91,6 +93,9 @@ _dispatch_workq_worker_register(dispatch_queue_t root_q, qos_class_t cls) int worker_id = mon->num_registered_tids++; mon->registered_tids[worker_id] = tid; _dispatch_unfair_lock_unlock(&mon->registered_tid_lock); +#else + (void)root_q; + (void)cls; #endif // HAVE_DISPATCH_WORKQ_MONITORING } @@ -113,6 +118,9 @@ _dispatch_workq_worker_unregister(dispatch_queue_t root_q, qos_class_t cls) } } _dispatch_unfair_lock_unlock(&mon->registered_tid_lock); +#else + (void)root_q; + (void)cls; #endif // HAVE_DISPATCH_WORKQ_MONITORING } diff --git a/src/init.c b/src/init.c index 6672fac45..26612c0ad 100644 --- a/src/init.c +++ b/src/init.c @@ -737,7 +737,7 @@ _dispatch_logv_file(const char *msg, va_list ap) #if DISPATCH_DEBUG offset += dsnprintf(&buf[offset], bufsiz - offset, "%llu\t", - _dispatch_absolute_time() - dispatch_log_basetime); + (unsigned long long)_dispatch_absolute_time() - dispatch_log_basetime); #endif r = vsnprintf(&buf[offset], bufsiz - offset, msg, ap); if (r < 0) return; @@ -834,7 +834,7 @@ _dispatch_debugv(dispatch_object_t dou, const char *msg, va_list ap) int r; #if DISPATCH_DEBUG && !DISPATCH_USE_OS_DEBUG_LOG offset += dsnprintf(&buf[offset], bufsiz - offset, "%llu\t\t%p\t", - _dispatch_absolute_time() - dispatch_log_basetime, + (unsigned long long)_dispatch_absolute_time() - dispatch_log_basetime, (void *)_dispatch_thread_self()); #endif if (dou._do) { diff --git a/src/io.c b/src/io.c index 155b6cf02..80aa78051 100644 --- a/src/io.c +++ b/src/io.c @@ -20,6 +20,11 @@ #include "internal.h" +#if defined(__FreeBSD__) +#include +#define F_RDADVISE F_RDAHEAD +#endif + #ifndef DISPATCH_IO_DEBUG #define DISPATCH_IO_DEBUG DISPATCH_DEBUG #endif @@ -419,7 +424,7 @@ dispatch_io_create_with_path(dispatch_io_type_t type, const char *path, struct stat st; _dispatch_io_syscall_switch_noerr(err, (path_data->oflag & O_NOFOLLOW) == O_NOFOLLOW -#ifndef __linux__ +#if __APPLE__ || (path_data->oflag & O_SYMLINK) == O_SYMLINK #endif ? lstat(path_data->path, &st) : stat(path_data->path, &st), @@ -627,7 +632,8 @@ dispatch_io_set_interval(dispatch_io_t channel, uint64_t interval, { _dispatch_retain(channel); dispatch_async(channel->queue, ^{ - _dispatch_channel_debug("set interval: %llu", channel, interval); + _dispatch_channel_debug("set interval: %llu", channel, + (unsigned long long)interval); channel->params.interval = interval < INT64_MAX ? interval : INT64_MAX; channel->params.interval_flags = flags; _dispatch_release(channel); @@ -1372,7 +1378,7 @@ _dispatch_fd_entry_create_with_fd(dispatch_fd_t fd, uintptr_t hash) break; ); } - dev_t dev = major(st.st_dev); + dev_t dev = (dev_t)major(st.st_dev); // We have to get the disk on the global dev queue. The // barrier queue cannot continue until that is complete dispatch_suspend(fd_entry->barrier_queue); @@ -1459,7 +1465,7 @@ _dispatch_fd_entry_create_with_path(dispatch_io_path_data_t path_data, path_data->channel->queue); _dispatch_fd_entry_debug("create: path %s", fd_entry, path_data->path); if (S_ISREG(mode)) { - _dispatch_disk_init(fd_entry, major(dev)); + _dispatch_disk_init(fd_entry, (dev_t)major(dev)); } else { _dispatch_stream_init(fd_entry, _dispatch_get_root_queue(DISPATCH_QOS_DEFAULT, false)); @@ -2138,7 +2144,7 @@ _dispatch_operation_advise(dispatch_operation_t op, size_t chunk_size) { _dispatch_op_debug("advise", op); if (_dispatch_io_get_error(op, NULL, true)) return; -#ifdef __linux__ +#if defined(__linux__) || defined(__FreeBSD__) // linux does not support fcntl (F_RDAVISE) // define necessary datastructure and use readahead struct radvisory { @@ -2165,7 +2171,7 @@ _dispatch_operation_advise(dispatch_operation_t op, size_t chunk_size) } advise.ra_offset = op->advise_offset; op->advise_offset += advise.ra_count; -#ifdef __linux__ +#if defined(__linux__) _dispatch_io_syscall_switch(err, readahead(op->fd_entry->fd, advise.ra_offset, (size_t)advise.ra_count), case EINVAL: break; // fd does refer to a non-supported filetype diff --git a/src/queue.c b/src/queue.c index 33e500957..7725d0d05 100644 --- a/src/queue.c +++ b/src/queue.c @@ -912,7 +912,14 @@ DISPATCH_ALWAYS_INLINE static inline pid_t gettid(void) { - return (pid_t) syscall(SYS_gettid); + return (pid_t)syscall(SYS_gettid); +} +#elif defined(__FreeBSD__) +DISPATCH_ALWAYS_INLINE +static inline pid_t +gettid(void) +{ + return (pid_t)pthread_getthreadid_np(); } #else #error "SYS_gettid unavailable on this system" @@ -4668,11 +4675,13 @@ DISPATCH_NOINLINE static void _dispatch_return_to_kernel(void) { +#if DISPATCH_USE_KEVENT_WORKQUEUE if (unlikely(_dispatch_get_wlh() == DISPATCH_WLH_ANON)) { _dispatch_clear_return_to_kernel(); } else { _dispatch_event_loop_drain(KEVENT_FLAG_IMMEDIATE); } +#endif } void diff --git a/src/shims.h b/src/shims.h index fad36bcd3..af3bef02c 100644 --- a/src/shims.h +++ b/src/shims.h @@ -28,8 +28,8 @@ #define __DISPATCH_OS_SHIMS__ #include -#ifdef __linux__ -#include "shims/linux_stubs.h" +#if defined(__linux__) || defined(__FreeBSD__) +#include "shims/generic_unix_stubs.h" #endif #ifdef __ANDROID__ diff --git a/src/shims/atomic.h b/src/shims/atomic.h index 64af8b272..5c9ce5a04 100644 --- a/src/shims/atomic.h +++ b/src/shims/atomic.h @@ -31,6 +31,10 @@ #error libdispatch requires C11 with #endif +// FreeBSD only defines _Bool in C mode. In C++ mode _Bool is not being defined. +#if defined(__cplusplus) && defined(__FreeBSD__) +#define _Bool bool +#endif #include #define memory_order_ordered memory_order_seq_cst diff --git a/src/shims/linux_stubs.c b/src/shims/generic_unix_stubs.c similarity index 92% rename from src/shims/linux_stubs.c rename to src/shims/generic_unix_stubs.c index 4923eb0ca..e1eb93e13 100644 --- a/src/shims/linux_stubs.c +++ b/src/shims/generic_unix_stubs.c @@ -17,11 +17,11 @@ */ #include -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__FreeBSD__) #include #else #include -#endif /* __ANDROID__ */ +#endif /* __ANDROID__ || __FreeBSD__ */ #if __has_include() #include @@ -30,7 +30,7 @@ #endif #include "pthread.h" -#include "os/linux_base.h" +#include "os/generic_unix_base.h" #include "internal.h" diff --git a/src/shims/linux_stubs.h b/src/shims/generic_unix_stubs.h similarity index 100% rename from src/shims/linux_stubs.h rename to src/shims/generic_unix_stubs.h diff --git a/src/transform.c b/src/transform.c index 91fed5b26..44a1271e4 100644 --- a/src/transform.c +++ b/src/transform.c @@ -26,6 +26,13 @@ #include #define OSLittleEndian __LITTLE_ENDIAN #define OSBigEndian __BIG_ENDIAN +#elif defined(__FreeBSD__) +#include +#define OSLittleEndian _LITTLE_ENDIAN +#define OSBigEndian _BIG_ENDIAN +#endif + +#if defined(__linux__) || defined(__FreeBSD__) #define OSSwapLittleToHostInt16 le16toh #define OSSwapBigToHostInt16 be16toh #define OSSwapHostToLittleInt16 htole16 diff --git a/tests/bsdtestharness.c b/tests/bsdtestharness.c index eab84b3ea..7aad1c07b 100644 --- a/tests/bsdtestharness.c +++ b/tests/bsdtestharness.c @@ -31,7 +31,7 @@ #endif #include #include -#ifdef __linux__ +#if defined(__linux__) || defined(__FreeBSD__) #include #endif diff --git a/tests/bsdtests.c b/tests/bsdtests.c index 09ab000ca..2c07a5d0b 100644 --- a/tests/bsdtests.c +++ b/tests/bsdtests.c @@ -18,7 +18,7 @@ * @APPLE_APACHE_LICENSE_HEADER_END@ */ -#ifdef __linux__ +#if defined(__linux__) || defined(__FreeBSD__) // for asprintf #define _GNU_SOURCE 1 #endif @@ -452,7 +452,7 @@ test_start(const char* desc) usleep(100000); // give 'gdb --waitfor=' a chance to find this proc } -#if __linux__ +#if defined(__linux__) || defined(__FreeBSD__) static char** get_environment(void) { extern char **environ; diff --git a/tests/bsdtests.h b/tests/bsdtests.h index 8bf733f7f..f2961945b 100644 --- a/tests/bsdtests.h +++ b/tests/bsdtests.h @@ -41,6 +41,7 @@ #include #endif +#include #include #include @@ -152,7 +153,7 @@ void _test_errno(const char* file, long line, const char* desc, int actual, int #define test_errno(a,b,c) _test_errno(__SOURCE_FILE__, __LINE__, a, b, c) void test_errno_format(int actual, int expected, const char *format, ...) __printflike(3,4); -#ifndef __linux__ +#if defined(__APPLE__) void _test_mach_error(const char* file, long line, const char* desc, mach_error_t actual, mach_error_t expected); #define test_mach_error(a,b,c) _test_mach_error(__SOURCE_FILE__, __LINE__, a, b, c) void test_mach_error_format(mach_error_t actual, mach_error_t expected, const char *format, ...) __printflike(3,4); diff --git a/tests/dispatch_io_net.c b/tests/dispatch_io_net.c index 4d02751df..fd680aef1 100644 --- a/tests/dispatch_io_net.c +++ b/tests/dispatch_io_net.c @@ -47,7 +47,7 @@ extern char **environ; #endif #endif -#ifdef __linux__ +#if defined(__linux__) || defined(__FreeBSD__) #define _NSGetExecutablePath(ef,bs) (*(bs)=(size_t)snprintf(ef,*(bs),"%s",argv[0]),0) #endif diff --git a/tests/dispatch_test.c b/tests/dispatch_test.c index a8f40d2bf..ea581945b 100644 --- a/tests/dispatch_test.c +++ b/tests/dispatch_test.c @@ -56,7 +56,7 @@ dispatch_test_check_evfilt_read_for_fd(int fd) int kq = kqueue(); assert(kq != -1); struct kevent ke = { - .ident = fd, + .ident = (uintptr_t)fd, .filter = EVFILT_READ, .flags = EV_ADD|EV_ENABLE, }; diff --git a/tests/dispatch_test.h b/tests/dispatch_test.h index 392b7f922..fdcffd269 100644 --- a/tests/dispatch_test.h +++ b/tests/dispatch_test.h @@ -22,8 +22,8 @@ #include #include -#ifdef __linux__ -#include +#if defined(__linux__) || defined(__FreeBSD__) +#include #endif #define test_group_wait(g) do { \ @@ -42,7 +42,7 @@ bool dispatch_test_check_evfilt_read_for_fd(int fd); void _dispatch_test_current(const char* file, long line, const char* desc, dispatch_queue_t expected); #define dispatch_test_current(a,b) _dispatch_test_current(__SOURCE_FILE__, __LINE__, a, b) -#ifndef __linux__ +#if __APPLE__ int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t *newpl); #endif diff --git a/tests/linux_port.h b/tests/generic_unix_port.h similarity index 100% rename from tests/linux_port.h rename to tests/generic_unix_port.h