Skip to content

Linux fixes for dispatch-806 merge #216

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,13 @@ 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

SUBDIRS= \
dispatch \
$(MAYBE_PTHREAD_WORKQUEUES) \
$(MAYBE_KQUEUES) \
man \
os \
private \
Expand Down
10 changes: 10 additions & 0 deletions os/linux_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
*/
Expand Down
5 changes: 0 additions & 5 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion src/event/event_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
49 changes: 33 additions & 16 deletions src/event/event_epoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;

Expand All @@ -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];
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 },
Expand All @@ -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;
Expand All @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this diff is wrong, it should always use DISPATCH_WLH_GLOBAL

Copy link
Contributor Author

@dgrove-oss dgrove-oss Feb 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok; I think I should then add an assert that the value of the wlh parameter is DISPATCH_WLH_GLOBAL. I don't like ignoring the value the caller passed in without asserting it has a known value.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no it needs to be GLOBAL here, event_kevent.c does the same. it is meant to be that.

Copy link
Contributor Author

@dgrove-oss dgrove-oss Feb 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we're looking at different pieces of code. In event_kevent.c, I think the matching piece of code is:

bool
_dispatch_unote_register(dispatch_unote_t du, dispatch_wlh_t wlh,
		dispatch_priority_t pri)
{
	dispatch_assert(!_dispatch_unote_registered(du));
	du._du->du_priority = pri;
	switch (du._du->du_filter) {
	case DISPATCH_EVFILT_CUSTOM_ADD:
	case DISPATCH_EVFILT_CUSTOM_OR:
	case DISPATCH_EVFILT_CUSTOM_REPLACE:
		du._du->du_wlh = wlh;
		return true;
	}
	if (!du._du->du_is_direct) {
		return _dispatch_unote_register_muxed(du, DISPATCH_WLH_GLOBAL);
	}
	return _dispatch_kq_unote_update(wlh, du, EV_ADD | EV_ENABLE);
}
```
``

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, event_kevent.c also sets it to 'wlh'. I think these are arguably both wrong and should both be the GLOBAL constant (but it also doesn't really matter for this 'synthetic event' case)

return true;
case EVFILT_WRITE:
events |= EPOLLOUT;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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 = {
Expand Down Expand Up @@ -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);
}
Expand All @@ -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]);
Expand All @@ -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));
}

Expand All @@ -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);
}
}

Expand All @@ -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;
Expand All @@ -467,15 +484,15 @@ _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);
}
}

if (events & EPOLLOUT) {
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);
}
}
}
Expand All @@ -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;

Expand Down
2 changes: 2 additions & 0 deletions src/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion src/shims.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions src/shims/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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), \
Expand All @@ -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, +)
Expand Down
1 change: 1 addition & 0 deletions src/shims/priority.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions src/shims/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/shims/tsd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
4 changes: 2 additions & 2 deletions src/source.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 (;;) {
Expand Down
11 changes: 3 additions & 8 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -75,24 +75,19 @@ 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

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
Expand All @@ -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)
Expand Down
Loading