Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 2 additions & 0 deletions cmake/modules/SwiftSupport.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,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")
Expand Down
4 changes: 3 additions & 1 deletion private/private.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,10 @@ void _dispatch_prohibit_transition_to_multithreaded(bool prohibit);

#if TARGET_OS_MAC
typedef mach_port_t dispatch_runloop_handle_t;
#elif defined(__linux__) || defined(__FreeBSD__)
#elif defined(__linux__)
typedef int dispatch_runloop_handle_t;
#elif defined(__FreeBSD__)
typedef uint64_t dispatch_runloop_handle_t;
#elif defined(_WIN32)
typedef void *dispatch_runloop_handle_t;
#else
Expand Down
18 changes: 14 additions & 4 deletions src/event/event_kevent.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,15 +389,23 @@ _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 :
ke->flags & EV_DELETE ? "delete" :
ke->flags & EV_ADD ? "add" :
ke->flags & EV_ENABLE ? "enable" : "monitor",
(int)ke->data, ke->ident, ke->udata, du);
#else
break;
#endif
}
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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:
Expand All @@ -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");
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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)",
Expand All @@ -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)
Expand Down
45 changes: 45 additions & 0 deletions src/event/workqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,51 @@ _dispatch_workq_count_runnable_workers(dispatch_workq_monitor_t mon)

_dispatch_unfair_lock_unlock(&mon->registered_tid_lock);
}
#elif defined(__FreeBSD__)
#include <sys/sysctl.h>
#include <sys/proc.h>
#include <sys/user.h>

static void
_dispatch_workq_count_runnable_workers(dispatch_workq_monitor_t mon)
{
struct kinfo_proc kp[WORKQ_MAX_TRACKED_TIDS];
size_t size;
int count, runners = 0;
int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD, (int)getpid()};

// get size we need
if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0) {
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we should use ARRAY_SIZEOF for the second parameter.

#define ARRAY_SIZEOF(array) (sizeof((array))/sizeof(*(array)))

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't really think it's a good idea to introduce a macro, especially just for one place.

Although it makes it more readable, but I think it is reasonable to expect the next person who need to change this line are already familiar with the correct usage of sysctl

_dispatch_debug("workq: failed to get size for kinfo_proc[] from sysctll");
return;
}

// only care about up to WORKQ_MAX_TRACKED_TIDS threads
size = size > sizeof(kp) ? sizeof(kp) : size;
count = (int)(size / sizeof(struct kinfo_proc));

if (sysctl(mib, 4, kp, &size, NULL, 0) < 0) {
_dispatch_debug("workq: failed to get kinfo_proc[] from sysctl");
return;
}

_dispatch_unfair_lock_lock(&mon->registered_tid_lock);

for (int i = 0; i < mon->num_registered_tids; ++i) {
dispatch_tid tid = mon->registered_tids[i];
for (int j = 0; i < count; ++i) {
if ((dispatch_tid)kp[j].ki_tid != tid) { continue; }
if (kp[j].ki_stat == SRUN || kp[j].ki_stat == SIDL) {
++runners;
break;
}
}
}

mon->num_runnable = runners;

_dispatch_unfair_lock_unlock(&mon->registered_tid_lock);
}
#else
#error must define _dispatch_workq_count_runnable_workers
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/event/workqueue_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
void _dispatch_workq_worker_register(dispatch_queue_global_t root_q);
void _dispatch_workq_worker_unregister(dispatch_queue_global_t root_q);

#if defined(__linux__) || defined(_WIN32)
#if defined(__linux__) || defined(_WIN32) || defined(__FreeBSD__)
#define HAVE_DISPATCH_WORKQ_MONITORING 1
#else
#define HAVE_DISPATCH_WORKQ_MONITORING 0
Expand Down
2 changes: 1 addition & 1 deletion src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,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 : "<unknown>",
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
Expand Down
3 changes: 3 additions & 0 deletions src/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@ upcast(dispatch_object_t dou)
#include <sys/sysctl.h>
#include <sys/queue.h>
#endif
#if defined(__FreeBSD__)
#include <sys/eventfd.h>
#endif // __FreeBSD__
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/mman.h>
Expand Down
1 change: 0 additions & 1 deletion src/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@

#if defined(__FreeBSD__)
#include <fcntl.h>
#define F_RDADVISE F_RDAHEAD
#endif

#ifndef DISPATCH_IO_DEBUG
Expand Down
33 changes: 33 additions & 0 deletions src/queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -6474,6 +6474,8 @@ _dispatch_runloop_handle_is_valid(dispatch_runloop_handle_t handle)
return MACH_PORT_VALID(handle);
#elif defined(__linux__)
return handle >= 0;
#elif defined(__FreeBSD__)
return handle > 0;
#elif defined(_WIN32)
return handle != NULL;
#else
Expand All @@ -6490,6 +6492,8 @@ _dispatch_runloop_queue_get_handle(dispatch_lane_t dq)
#elif defined(__linux__)
// 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(__FreeBSD__)
return (dispatch_runloop_handle_t)(uintptr_t)dq->do_ctxt;
#elif defined(_WIN32)
return ((dispatch_runloop_handle_t)(uintptr_t)dq->do_ctxt);
#else
Expand All @@ -6507,13 +6511,21 @@ _dispatch_runloop_queue_set_handle(dispatch_lane_t dq,
#elif defined(__linux__)
// encode: 0 is a valid fd, so offset by 1 to distinguish from NULL
dq->do_ctxt = (void *)(uintptr_t)(handle + 1);
#elif defined(__FreeBSD__)
dq->do_ctxt = (void *)(uintptr_t)handle;
#elif defined(_WIN32)
dq->do_ctxt = (void *)(uintptr_t)handle;
#else
#error "runloop support not implemented on this platform"
#endif
}

#if defined(__unix__)
#define DISPATCH_RUNLOOP_HANDLE_PACK(rfd, wfd) (((uint64_t)(rfd) << 32) | (wfd))
#define DISPATCH_RUNLOOP_HANDLE_RFD(h) ((int)((h) >> 32))
#define DISPATCH_RUNLOOP_HANDLE_WFD(h) ((int)((h) & 0xffffffff))
#endif

static void
_dispatch_runloop_queue_handle_init(void *ctxt)
{
Expand Down Expand Up @@ -6563,6 +6575,15 @@ _dispatch_runloop_queue_handle_init(void *ctxt)
}
}
handle = fd;
#elif defined(__unix__) && !defined(__linux__)
// swift-corelib-foundation PR #3004 implemented a pipe based queue handle
int fds[2];
int r = pipe2(fds, O_CLOEXEC | O_NONBLOCK);
if (r == -1) {
DISPATCH_CLIENT_CRASH(errno, "pipe2 failure");
}
uint32_t rfd = (uint32_t)fds[0], wfd = (uint32_t)fds[1];
handle = DISPATCH_RUNLOOP_HANDLE_PACK(rfd, wfd);
#elif defined(_WIN32)
HANDLE hEvent;
hEvent = CreateEventW(NULL, /*bManualReset=*/FALSE,
Expand Down Expand Up @@ -6597,6 +6618,11 @@ _dispatch_runloop_queue_handle_dispose(dispatch_lane_t dq)
#elif defined(__linux__)
int rc = close(handle);
(void)dispatch_assume_zero(rc);
#elif defined(__unix__) && !defined(__linux__)
int rc = close(DISPATCH_RUNLOOP_HANDLE_WFD(handle));
(void)dispatch_assume_zero(rc);
rc = close(DISPATCH_RUNLOOP_HANDLE_RFD(handle));
(void)dispatch_assume_zero(rc);
#elif defined(_WIN32)
BOOL bSuccess;
bSuccess = CloseHandle(handle);
Expand Down Expand Up @@ -6633,6 +6659,13 @@ _dispatch_runloop_queue_class_poke(dispatch_lane_t dq)
result = eventfd_write(handle, 1);
} while (result == -1 && errno == EINTR);
(void)dispatch_assume_zero(result);
#elif defined(__unix__) && !defined(__linux__)
int wfd = DISPATCH_RUNLOOP_HANDLE_WFD(handle);
ssize_t result;
do {
result = write(wfd, "x", 1);
} while (result == -1 && errno == EINTR);
(void)dispatch_assume_zero(result - 1);
#elif defined(_WIN32)
BOOL bSuccess;
bSuccess = SetEvent(handle);
Expand Down
29 changes: 28 additions & 1 deletion src/shims/lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -516,6 +531,16 @@ _dispatch_wait_on_address(uint32_t volatile *_address, uint32_t value,
? INFINITE : ((nsecs + 1000000) / 1000000);
if (dwMilliseconds == 0) return ETIMEDOUT;
return WaitOnAddress(address, &value, sizeof(value), dwMilliseconds) == 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
Expand All @@ -530,6 +555,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
Expand Down Expand Up @@ -689,7 +716,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;
}
Expand Down
22 changes: 22 additions & 0 deletions src/shims/lock.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,28 @@ _dispatch_lock_owner(dispatch_lock lock_value)
return lock_value & DLOCK_OWNER_MASK;
}

#elif defined(__FreeBSD__)

#include <sys/types.h>
#include <sys/umtx.h>
#include <sched.h>

typedef uint32_t dispatch_tid;
typedef uint32_t dispatch_lock;

#define DLOCK_OWNER_NULL ((dispatch_tid)0)
#define DLOCK_OWNER_MASK ((dispatch_lock)0xfffffffc)
#define DLOCK_WAITERS_BIT ((dispatch_lock)0x00000001)
#define DLOCK_FAILED_TRYLOCK_BIT ((dispatch_lock)0x00000002)
#define _dispatch_tid_self() ((dispatch_tid)(_dispatch_get_tsd_base()->tid << 2))

DISPATCH_ALWAYS_INLINE
static inline dispatch_tid
_dispatch_lock_owner(dispatch_lock lock_value)
{
return lock_value & DLOCK_OWNER_MASK;
}

#elif defined(_WIN32)

#include <Windows.h>
Expand Down
Loading