From 7b4281ea50b6e86d8739bea1c62c56a602b13852 Mon Sep 17 00:00:00 2001 From: David Grove Date: Tue, 21 Feb 2017 20:58:00 -0500 Subject: [PATCH] Linux fixes for dispatch-806 merge Collection of small fixes to dispatch-806 merge to allow code to compile/link/run on Linux. --- Makefile.am | 5 ---- os/linux_base.h | 10 ++++++++ src/Makefile.am | 5 ---- src/event/event_config.h | 1 - src/event/event_epoll.c | 49 +++++++++++++++++++++++++++------------- src/object.c | 2 ++ src/shims.h | 2 +- src/shims/atomic.h | 8 +++---- src/shims/priority.h | 1 + src/shims/time.h | 4 ++-- src/shims/tsd.h | 2 +- src/source.c | 4 ++-- tests/Makefile.am | 11 +++------ tests/dispatch_test.c | 8 +++++++ 14 files changed, 67 insertions(+), 45 deletions(-) diff --git a/Makefile.am b/Makefile.am index 63c8b17aa..ffc82df29 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,10 +8,6 @@ if BUILD_OWN_PTHREAD_WORKQUEUES MAYBE_PTHREAD_WORKQUEUES = libpwq endif -if BUILD_OWN_KQUEUES - MAYBE_KQUEUES = libkqueue -endif - if BUILD_TESTS MAYBE_TESTS = tests endif @@ -19,7 +15,6 @@ endif SUBDIRS= \ dispatch \ $(MAYBE_PTHREAD_WORKQUEUES) \ - $(MAYBE_KQUEUES) \ man \ os \ private \ diff --git a/os/linux_base.h b/os/linux_base.h index 8173e12bf..d0048d615 100644 --- a/os/linux_base.h +++ b/os/linux_base.h @@ -17,8 +17,10 @@ #if __GNUC__ #define OS_EXPECT(x, v) __builtin_expect((x), (v)) +#define OS_UNUSED __attribute__((__unused__)) #else #define OS_EXPECT(x, v) (x) +#define OS_UNUSED #endif #ifndef os_likely @@ -67,6 +69,14 @@ #define __OS_CONCAT(x, y) x ## y #define OS_CONCAT(x, y) __OS_CONCAT(x, y) +#if __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums) +#define OS_ENUM(_name, _type, ...) \ +typedef enum : _type { __VA_ARGS__ } _name##_t +#else +#define OS_ENUM(_name, _type, ...) \ +enum { __VA_ARGS__ }; typedef _type _name##_t +#endif + /* * Stub out misc linking and compilation attributes */ diff --git a/src/Makefile.am b/src/Makefile.am index 6517b7418..f774e9fe1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,11 +77,6 @@ AM_OBJCFLAGS=$(DISPATCH_CFLAGS) $(CBLOCKS_FLAGS) AM_CXXFLAGS=$(PTHREAD_WORKQUEUE_CFLAGS) $(DISPATCH_CFLAGS) $(CXXBLOCKS_FLAGS) AM_OBJCXXFLAGS=$(DISPATCH_CFLAGS) $(CXXBLOCKS_FLAGS) -if BUILD_OWN_KQUEUES - KQUEUE_LIBS+=$(top_builddir)/libkqueue/libkqueue.la - KQUEUE_CFLAGS+=-I$(top_srcdir)/libkqueue/include -endif - if BUILD_OWN_PTHREAD_WORKQUEUES PTHREAD_WORKQUEUE_LIBS=$(top_builddir)/libpwq/libpthread_workqueue.la PTHREAD_WORKQUEUE_CFLAGS=-I$(top_srcdir)/libpwq/include diff --git a/src/event/event_config.h b/src/event/event_config.h index 889fa9005..7f7761c32 100644 --- a/src/event/event_config.h +++ b/src/event/event_config.h @@ -133,7 +133,6 @@ # define EV_ONESHOT 0x0010 # define EV_CLEAR 0x0020 # define EV_DISPATCH 0x0080 -# define EV_UDATA_SPECIFIC 0x0100 # define EVFILT_READ (-1) # define EVFILT_WRITE (-2) diff --git a/src/event/event_epoll.c b/src/event/event_epoll.c index 53aff72c2..2788b1008 100644 --- a/src/event/event_epoll.c +++ b/src/event/event_epoll.c @@ -35,6 +35,8 @@ #error unsupported configuration #endif +#define DISPATCH_EPOLL_MAX_EVENT_COUNT 16 + enum { DISPATCH_EPOLL_EVENTFD = 0x0001, DISPATCH_EPOLL_CLOCK_WALL = 0x0002, @@ -47,8 +49,8 @@ typedef struct dispatch_muxnote_s { TAILQ_HEAD(, dispatch_unote_linkage_s) dmn_writers_head; int dmn_fd; int dmn_ident; + uint32_t dmn_events; int16_t dmn_filter; - int16_t dmn_events; bool dmn_socket_listener; } *dispatch_muxnote_t; @@ -60,6 +62,10 @@ typedef struct dispatch_epoll_timeout_s { } *dispatch_epoll_timeout_t; static int _dispatch_epfd, _dispatch_eventfd; + +static dispatch_once_t epoll_init_pred; +static void _dispatch_epoll_init(void *); + DISPATCH_CACHELINE_ALIGN static TAILQ_HEAD(dispatch_muxnote_bucket_s, dispatch_muxnote_s) _dispatch_sources[DSL_HASH_SIZE]; @@ -112,7 +118,7 @@ _dispatch_muxnote_dispose(dispatch_muxnote_t dmn) } static dispatch_muxnote_t -_dispatch_muxnote_create(dispatch_unote_t du, int16_t events) +_dispatch_muxnote_create(dispatch_unote_t du, uint32_t events) { dispatch_muxnote_t dmn; struct stat sb; @@ -173,6 +179,7 @@ _dispatch_muxnote_create(dispatch_unote_t du, int16_t events) static int _dispatch_epoll_update(dispatch_muxnote_t dmn, int op) { + dispatch_once_f(&epoll_init_pred, NULL, _dispatch_epoll_init); struct epoll_event ev = { .events = dmn->dmn_events, .data = { .ptr = dmn }, @@ -181,11 +188,12 @@ _dispatch_epoll_update(dispatch_muxnote_t dmn, int op) } bool -_dispatch_unote_register(dispatch_unote_t du, dispatch_priority_t pri) +_dispatch_unote_register(dispatch_unote_t du, dispatch_wlh_t wlh, + dispatch_priority_t pri) { struct dispatch_muxnote_bucket_s *dmb; dispatch_muxnote_t dmn; - int16_t events = EPOLLFREE; + uint32_t events = EPOLLFREE; dispatch_assert(!_dispatch_unote_registered(du)); du._du->du_priority = pri; @@ -194,7 +202,7 @@ _dispatch_unote_register(dispatch_unote_t du, dispatch_priority_t pri) case DISPATCH_EVFILT_CUSTOM_ADD: case DISPATCH_EVFILT_CUSTOM_OR: case DISPATCH_EVFILT_CUSTOM_REPLACE: - du._du->du_wlh = DISPATCH_WLH_GLOBAL; + du._du->du_wlh = wlh; return true; case EVFILT_WRITE: events |= EPOLLOUT; @@ -264,7 +272,7 @@ _dispatch_unote_unregister(dispatch_unote_t du, uint32_t flags) if (_dispatch_unote_registered(du)) { dispatch_unote_linkage_t dul = _dispatch_unote_get_linkage(du); dispatch_muxnote_t dmn = dul->du_muxnote; - int16_t events = dmn->dmn_events; + uint32_t events = dmn->dmn_events; if (du._du->du_filter == EVFILT_WRITE) { TAILQ_REMOVE(&dmn->dmn_writers_head, dul, du_link); @@ -300,8 +308,6 @@ _dispatch_unote_unregister(dispatch_unote_t du, uint32_t flags) static void _dispatch_event_merge_timer(dispatch_clock_t clock) { - int qos; - _dispatch_timers_expired = true; _dispatch_timers_processing_mask |= 1 << DISPATCH_TIMER_INDEX(clock, 0); #if DISPATCH_USE_DTRACE @@ -314,7 +320,6 @@ _dispatch_event_merge_timer(dispatch_clock_t clock) static void _dispatch_timeout_program(uint32_t tidx, uint64_t target, uint64_t leeway) { - uint32_t qos = DISPATCH_TIMER_QOS(tidx); dispatch_clock_t clock = DISPATCH_TIMER_CLOCK(tidx); dispatch_epoll_timeout_t timer = &_dispatch_epoll_timeout[clock]; struct epoll_event ev = { @@ -371,7 +376,7 @@ _dispatch_event_loop_timer_arm(uint32_t tidx, dispatch_timer_delay_s range, dispatch_clock_now_cache_t nows) { uint64_t target = range.delay; - target += _dispatch_time_cached_now(nows, DISPATCH_TIMER_CLOCK(tidx)); + target += _dispatch_time_now_cached(DISPATCH_TIMER_CLOCK(tidx), nows); _dispatch_timers_heap[tidx].dth_flags |= DTH_ARMED; _dispatch_timeout_program(tidx, target, range.leeway); } @@ -393,6 +398,13 @@ _dispatch_event_loop_atfork_child(void) void _dispatch_event_loop_init(void) { +} + +static void +_dispatch_epoll_init(void *context DISPATCH_UNUSED) +{ + _dispatch_fork_becomes_unsafe(); + unsigned int i; for (i = 0; i < DSL_HASH_SIZE; i++) { TAILQ_INIT(&_dispatch_sources[i]); @@ -413,15 +425,20 @@ _dispatch_event_loop_init(void) .data = { .u32 = DISPATCH_EPOLL_EVENTFD, }, }; unsigned long op = EPOLL_CTL_ADD; - if (epoll_ctl(_dispatch_eventfd, op, _dispatch_eventfd, &ev) < 0) { + if (epoll_ctl(_dispatch_epfd, op, _dispatch_eventfd, &ev) < 0) { DISPATCH_INTERNAL_CRASH(errno, "epoll_ctl() failed"); } + +#if DISPATCH_USE_MGR_THREAD + dx_push(_dispatch_mgr_q.do_targetq, &_dispatch_mgr_q, 0); +#endif } void _dispatch_event_loop_poke(dispatch_wlh_t wlh DISPATCH_UNUSED, dispatch_priority_t pri DISPATCH_UNUSED, uint32_t flags DISPATCH_UNUSED) { + dispatch_once_f(&epoll_init_pred, NULL, _dispatch_epoll_init); dispatch_assume_zero(eventfd_write(_dispatch_eventfd, 1)); } @@ -435,7 +452,7 @@ _dispatch_event_merge_signal(dispatch_muxnote_t dmn) TAILQ_FOREACH_SAFE(dul, &dmn->dmn_readers_head, du_link, dul_next) { dispatch_unote_t du = _dispatch_unote_linkage_get_unote(dul); - dux_merge_evt(du._du, EV_ADD|EV_ENABLE|EV_CLEAR, 1, 0); + dux_merge_evt(du._du, EV_ADD|EV_ENABLE|EV_CLEAR, 1, 0, 0); } } @@ -458,7 +475,7 @@ _dispatch_get_buffer_size(dispatch_muxnote_t dmn, bool writer) } static void -_dispatch_event_merge_fd(dispatch_muxnote_t dmn, int16_t events) +_dispatch_event_merge_fd(dispatch_muxnote_t dmn, uint32_t events) { dispatch_unote_linkage_t dul, dul_next; uintptr_t data; @@ -467,7 +484,7 @@ _dispatch_event_merge_fd(dispatch_muxnote_t dmn, int16_t events) data = _dispatch_get_buffer_size(dmn, false); TAILQ_FOREACH_SAFE(dul, &dmn->dmn_readers_head, du_link, dul_next) { dispatch_unote_t du = _dispatch_unote_linkage_get_unote(dul); - dux_merge_evt(du._du, EV_ADD|EV_ENABLE|EV_DISPATCH, ~data, 0); + dux_merge_evt(du._du, EV_ADD|EV_ENABLE|EV_DISPATCH, ~data, 0, 0); } } @@ -475,7 +492,7 @@ _dispatch_event_merge_fd(dispatch_muxnote_t dmn, int16_t events) data = _dispatch_get_buffer_size(dmn, true); TAILQ_FOREACH_SAFE(dul, &dmn->dmn_writers_head, du_link, dul_next) { dispatch_unote_t du = _dispatch_unote_linkage_get_unote(dul); - dux_merge_evt(du._du, EV_ADD|EV_ENABLE|EV_DISPATCH, ~data, 0); + dux_merge_evt(du._du, EV_ADD|EV_ENABLE|EV_DISPATCH, ~data, 0, 0); } } } @@ -484,7 +501,7 @@ DISPATCH_NOINLINE void _dispatch_event_loop_drain(uint32_t flags) { - struct epoll_event ev[DISPATCH_DEFERRED_ITEMS_EVENT_COUNT]; + struct epoll_event ev[DISPATCH_EPOLL_MAX_EVENT_COUNT]; int i, r; int timeout = (flags & KEVENT_FLAG_IMMEDIATE) ? 0 : -1; diff --git a/src/object.c b/src/object.c index c5c333b40..1ca41bc73 100644 --- a/src/object.c +++ b/src/object.c @@ -179,8 +179,10 @@ _dispatch_xref_dispose(dispatch_object_t dou) } if (dx_type(dou._do) == DISPATCH_SOURCE_KEVENT_TYPE) { _dispatch_source_xref_dispose(dou._ds); +#if HAVE_MACH } else if (dx_type(dou._do) == DISPATCH_MACH_CHANNEL_TYPE) { _dispatch_mach_xref_dispose(dou._dm); +#endif } else if (dx_type(dou._do) == DISPATCH_QUEUE_RUNLOOP_TYPE) { _dispatch_runloop_queue_xref_dispose(dou._dq); } diff --git a/src/shims.h b/src/shims.h index 8a79acac6..8434341ec 100644 --- a/src/shims.h +++ b/src/shims.h @@ -135,7 +135,7 @@ _pthread_qos_override_end_direct(mach_port_t thread, void *resource) #endif #if PTHREAD_WORKQUEUE_SPI_VERSION < 20160427 -bool +static inline bool _pthread_workqueue_should_narrow(pthread_priority_t priority) { (void)priority; diff --git a/src/shims/atomic.h b/src/shims/atomic.h index fae05b760..64af8b272 100644 --- a/src/shims/atomic.h +++ b/src/shims/atomic.h @@ -43,14 +43,14 @@ // This removes the _Atomic and volatile qualifiers on the type of *p #define _os_atomic_basetypeof(p) \ - typeof(atomic_load(_os_atomic_c11_atomic(p), memory_order_relaxed)) + typeof(atomic_load_explicit(_os_atomic_c11_atomic(p), memory_order_relaxed)) #define os_atomic_load(p, m) \ atomic_load_explicit(_os_atomic_c11_atomic(p), memory_order_##m) #define os_atomic_store(p, v, m) \ - atomic_store_explicit(_os_atomic_c11_atomic(p), _v, memory_order_##m) + atomic_store_explicit(_os_atomic_c11_atomic(p), v, memory_order_##m) #define os_atomic_xchg(p, v, m) \ - atomic_exchange_explicit(_os_atomic_c11_atomic(p), _v, memory_order_##m) + atomic_exchange_explicit(_os_atomic_c11_atomic(p), v, memory_order_##m) #define os_atomic_cmpxchg(p, e, v, m) \ ({ _os_atomic_basetypeof(p) _r = (e); \ atomic_compare_exchange_strong_explicit(_os_atomic_c11_atomic(p), \ @@ -69,7 +69,7 @@ atomic_fetch_##o##_explicit(_os_atomic_c11_atomic(p), _v, \ memory_order_##m); (typeof(*(p)))(_r op _v); }) #define _os_atomic_c11_op_orig(p, v, m, o, op) \ - atomic_fetch_##o##_explicit(_os_atomic_c11_atomic(p), _v, \ + atomic_fetch_##o##_explicit(_os_atomic_c11_atomic(p), v, \ memory_order_##m) #define os_atomic_add(p, v, m) \ _os_atomic_c11_op((p), (v), m, add, +) diff --git a/src/shims/priority.h b/src/shims/priority.h index 897d518ab..948e4c7af 100644 --- a/src/shims/priority.h +++ b/src/shims/priority.h @@ -66,6 +66,7 @@ typedef unsigned long pthread_priority_t; #define _PTHREAD_PRIORITY_DEFAULTQUEUE_FLAG 0x04000000 #define _PTHREAD_PRIORITY_EVENT_MANAGER_FLAG 0x02000000 #define _PTHREAD_PRIORITY_NEEDS_UNBIND_FLAG 0x01000000 +#define _PTHREAD_PRIORITY_ENFORCE_FLAG 0x10000000 #endif // HAVE_PTHREAD_QOS_H diff --git a/src/shims/time.h b/src/shims/time.h index 761f33167..3010f08da 100644 --- a/src/shims/time.h +++ b/src/shims/time.h @@ -172,11 +172,11 @@ _dispatch_approximate_time(void) #if HAVE_MACH_APPROXIMATE_TIME return mach_approximate_time(); #elif HAVE_DECL_CLOCK_UPTIME_FAST && !defined(__linux__) - struct timesmec ts; + struct timespec ts; dispatch_assume_zero(clock_gettime(CLOCK_UPTIME_FAST, &ts)); return _dispatch_timespec_to_nano(ts); #elif defined(__linux__) - struct timesmec ts; + struct timespec ts; dispatch_assume_zero(clock_gettime(CLOCK_REALTIME_COARSE, &ts)); return _dispatch_timespec_to_nano(ts); #else diff --git a/src/shims/tsd.h b/src/shims/tsd.h index 91c675a62..f3d3cea5f 100644 --- a/src/shims/tsd.h +++ b/src/shims/tsd.h @@ -118,7 +118,7 @@ struct dispatch_tsd { #endif void *dispatch_priority_key; void *dispatch_r2k_key; - void *dispatch_wlh_key + void *dispatch_wlh_key; void *dispatch_voucher_key; void *dispatch_deferred_items_key; }; diff --git a/src/source.c b/src/source.c index 1e17fb8f7..c2020462c 100644 --- a/src/source.c +++ b/src/source.c @@ -134,8 +134,8 @@ dispatch_source_get_handle(dispatch_source_t ds) unsigned long dispatch_source_get_data(dispatch_source_t ds) { - dispatch_source_refs_t dr = ds->ds_refs; #if DISPATCH_USE_MEMORYSTATUS + dispatch_source_refs_t dr = ds->ds_refs; if (dr->du_vmpressure_override) { return NOTE_VM_PRESSURE; } @@ -2300,7 +2300,7 @@ _dispatch_mgr_invoke(void) #if DISPATCH_EVENT_BACKEND_KEVENT ddi.ddi_nevents = 0; #endif - _dispatch_set_wlh(DISPATCH_WLH_GLOBAL); + dispatch_assert(_dispatch_get_wlh() == DISPATCH_WLH_GLOBAL); _dispatch_deferred_items_set(&ddi); for (;;) { diff --git a/tests/Makefile.am b/tests/Makefile.am index 1688fc95c..a47613097 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -75,7 +75,7 @@ TESTS= \ $(ADDITIONAL_TESTS) -dispatch_c99_CFLAGS=$(DISPATCH_TESTS_CFLAGS) $(CBLOCKS_FLAGS) $(KQUEUE_CFLAGS) -std=c99 +dispatch_c99_CFLAGS=$(DISPATCH_TESTS_CFLAGS) $(CBLOCKS_FLAGS) -std=c99 dispatch_plusplus_SOURCES=dispatch_plusplus.cpp dispatch_priority2_SOURCES=dispatch_priority.c dispatch_priority2_CPPFLAGS=$(AM_CPPFLAGS) -DUSE_SET_TARGET_QUEUE=1 @@ -83,16 +83,11 @@ dispatch_priority2_CPPFLAGS=$(AM_CPPFLAGS) -DUSE_SET_TARGET_QUEUE=1 AM_CPPFLAGS=-I$(top_builddir) -I$(top_srcdir) DISPATCH_TESTS_CFLAGS=-Wall -Wno-deprecated-declarations $(MARCH_FLAGS) -AM_CFLAGS=$(DISPATCH_TESTS_CFLAGS) $(CBLOCKS_FLAGS) $(KQUEUE_CFLAGS) $(BSD_OVERLAY_CFLAGS) +AM_CFLAGS=$(DISPATCH_TESTS_CFLAGS) $(CBLOCKS_FLAGS) $(BSD_OVERLAY_CFLAGS) AM_OBJCFLAGS=$(DISPATCH_TESTS_CFLAGS) $(CBLOCKS_FLAGS) AM_CXXFLAGS=$(DISPATCH_TESTS_CFLAGS) $(CXXBLOCKS_FLAGS) $(BSD_OVERLAY_CFLAGS) AM_OBJCXXFLAGS=$(DISPATCH_TESTS_CFLAGS) $(CXXBLOCKS_FLAGS) -if BUILD_OWN_KQUEUES - KQUEUE_LIBS+=$(top_builddir)/libkqueue/libkqueue.la - KQUEUE_CFLAGS+=-I$(top_srcdir)/libkqueue/include -endif - if !BUILD_OWN_PTHREAD_WORKQUEUES if HAVE_PTHREAD_WORKQUEUES PTHREAD_WORKQUEUE_LIBS=-lpthread_workqueue @@ -109,7 +104,7 @@ if HAVE_SWIFT AM_LDFLAGS=-rpath $(SWIFT_LIBDIR) endif -LDADD=libbsdtests.la $(top_builddir)/src/libdispatch.la $(KQUEUE_LIBS) $(PTHREAD_WORKQUEUE_LIBS) $(BSD_OVERLAY_LIBS) $(SWIFT_LIBS) +LDADD=libbsdtests.la $(top_builddir)/src/libdispatch.la $(PTHREAD_WORKQUEUE_LIBS) $(BSD_OVERLAY_LIBS) $(SWIFT_LIBS) libbsdtests_la_LDFLAGS=-avoid-version bsdtestsummarize_LDADD=-lm $(BSD_OVERLAY_LIBS) diff --git a/tests/dispatch_test.c b/tests/dispatch_test.c index ce92ae00c..52c61cfaf 100644 --- a/tests/dispatch_test.c +++ b/tests/dispatch_test.c @@ -28,7 +28,10 @@ #include #include #include +#if __has_include() +#define HAS_SYS_EVENT_H 1 #include +#endif #include #include @@ -47,6 +50,7 @@ dispatch_test_start(const char* desc) bool dispatch_test_check_evfilt_read_for_fd(int fd) { +#if HAS_SYS_EVENT_H int kq = kqueue(); assert(kq != -1); struct kevent ke = { @@ -60,6 +64,10 @@ dispatch_test_check_evfilt_read_for_fd(int fd) int r = kevent(kq, &ke, 1, &ke, 1, &t); close(kq); return r > 0; +#else + // TODO: Need to write a real check for epoll-backend here + return true; +#endif } void