Skip to content

Fix FreeBSD support #561

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions cmake/modules/SwiftSupport.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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")
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__)
Copy link
Member

Choose a reason for hiding this comment

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

We have DISPATCH_USE_KEVENT_QOS in src/event/event_config.h that might be more declarative here.

DISPATCH_INTERNAL_CRASH(ke->qos, "Invalid kevent priority");
#else
Copy link
Member

Choose a reason for hiding this comment

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

kevent on FreeBSD won't return ERANGE here, so we shouldn't need to trap this.

DISPATCH_INTERNAL_CRASH(0, "Invalid kevent priority");
#endif
default:
#if HAVE_MACH
Copy link
Member

Choose a reason for hiding this comment

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

We actually don't need to wrap HAVE_MACH here; we can remove the conditional in src/init.c (see 72eb2b2). Keeping the logging would be useful.

// 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
2 changes: 1 addition & 1 deletion src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 : "<unknown>",
du._du->du_ident, du._du->du_ident, func);
(intptr_t)du._du->du_ident, (intptr_t)du._du->du_ident, func);
Copy link
Member

Choose a reason for hiding this comment

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

If we're going to cast here, we might as well choose uintmax_t (in the alternative, I had suggested on the other pr defining some custom format strings because the type of dispatch_unote_ident_t is platform defined, but casting is a reasonable alternative here.)

}

#endif // RDAR_49023449
Expand Down
5 changes: 4 additions & 1 deletion src/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
#define __DISPATCH_BUILDING_DISPATCH__
#define __DISPATCH_INDIRECT__

#ifdef __APPLE__
#ifdef __APPLE__DISPATCH_USE_KEVENT_WORKLOOP
Copy link
Member

Choose a reason for hiding this comment

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

s/__APPLE__//?

#include <Availability.h>
#include <os/availability.h>
#include <TargetConditionals.h>
Expand Down 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
12 changes: 6 additions & 6 deletions src/queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
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__)
Copy link
Member

Choose a reason for hiding this comment

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

This could be merged above and the #ifdefput in the function body.

#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 @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down
25 changes: 24 additions & 1 deletion src/shims/lock.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -79,6 +79,29 @@ _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_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 <Windows.h>
Expand Down
1 change: 1 addition & 0 deletions src/swift/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions src/swift/Source.swift
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ extension DispatchSource {
}
#endif

#if !os(Linux) && !os(Android) && !os(Windows)
#if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD)
Copy link
Member

Choose a reason for hiding this comment

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

...and then we're going to have to eventually && !os(OpenBSD) -- should we just bite the bullet and rewrite this os(macOS)? (throughout)

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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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))
Expand Down
2 changes: 1 addition & 1 deletion src/swift/Wrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
}
Expand Down
4 changes: 2 additions & 2 deletions tests/bsdtestharness.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion tests/dispatch_apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions tests/dispatch_io_pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion tests/dispatch_select.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down