Skip to content

Commit 089b658

Browse files
authored
Merge pull request #861 from michael-yuji/freebsd-dev
[FreeBSD] support FreeBSD
2 parents beb137b + 17ed7bd commit 089b658

16 files changed

+137
-17
lines changed

private/private.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,9 @@ void _dispatch_prohibit_transition_to_multithreaded(bool prohibit);
189189

190190
#if TARGET_OS_MAC
191191
typedef mach_port_t dispatch_runloop_handle_t;
192-
#elif defined(__linux__) || defined(__FreeBSD__)
192+
#elif defined(__linux__)
193193
typedef int dispatch_runloop_handle_t;
194-
#elif defined(__unix__) && !defined(__linux__) && !defined(__FreeBSD__)
194+
#elif defined(__unix__)
195195
typedef uint64_t dispatch_runloop_handle_t;
196196
#elif defined(_WIN32)
197197
typedef void *dispatch_runloop_handle_t;

src/event/workqueue.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,52 @@ _dispatch_workq_count_runnable_workers(dispatch_workq_monitor_t mon)
293293

294294
_dispatch_unfair_lock_unlock(&mon->registered_tid_lock);
295295
}
296+
#elif defined(__FreeBSD__)
297+
#include <sys/sysctl.h>
298+
#include <sys/proc.h>
299+
#include <sys/user.h>
300+
301+
static void
302+
_dispatch_workq_count_runnable_workers(dispatch_workq_monitor_t mon)
303+
{
304+
struct kinfo_proc kp[WORKQ_MAX_TRACKED_TIDS];
305+
size_t size;
306+
int count, runners = 0;
307+
int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD, (int)getpid()};
308+
309+
// get size we need
310+
if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0) {
311+
_dispatch_debug("workq: failed to get size for kinfo_proc[] from sysctll");
312+
return;
313+
}
314+
315+
// only care about up to WORKQ_MAX_TRACKED_TIDS threads
316+
size = MIN(sizeof(kp), size);
317+
318+
if (sysctl(mib, 4, kp, &size, NULL, 0) < 0) {
319+
_dispatch_debug("workq: failed to get kinfo_proc[] from sysctl");
320+
return;
321+
}
322+
323+
count = (int)(size / sizeof(struct kinfo_proc));
324+
325+
_dispatch_unfair_lock_lock(&mon->registered_tid_lock);
326+
327+
for (int i = 0; i < mon->num_registered_tids; ++i) {
328+
dispatch_tid tid = mon->registered_tids[i];
329+
for (int j = 0; i < count; ++i) {
330+
if ((dispatch_tid)kp[j].ki_tid != tid) { continue; }
331+
if (kp[j].ki_stat == SRUN || kp[j].ki_stat == SIDL) {
332+
++runners;
333+
break;
334+
}
335+
}
336+
}
337+
338+
mon->num_runnable = runners;
339+
340+
_dispatch_unfair_lock_unlock(&mon->registered_tid_lock);
341+
}
296342
#else
297343
#error must define _dispatch_workq_count_runnable_workers
298344
#endif

src/event/workqueue_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
void _dispatch_workq_worker_register(dispatch_queue_global_t root_q);
3131
void _dispatch_workq_worker_unregister(dispatch_queue_global_t root_q);
3232

33-
#if defined(__linux__) || defined(_WIN32) || defined(__OpenBSD__)
33+
#if defined(__linux__) || defined(_WIN32) || defined(__OpenBSD__) || defined(__FreeBSD__)
3434
#define HAVE_DISPATCH_WORKQ_MONITORING 1
3535
#else
3636
#define HAVE_DISPATCH_WORKQ_MONITORING 0

src/init.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,7 +1049,11 @@ _dispatch_bug_kevent_vanished(dispatch_unote_t du)
10491049
"{ %p[%s], ident: %" PRIdPTR " / 0x%" PRIxPTR ", handler: %p }",
10501050
dux_type(du._du)->dst_kind, dou._dq,
10511051
dou._dq->dq_label ? dou._dq->dq_label : "<unknown>",
1052+
#if defined(__FreeBSD__)
1053+
(intptr_t)du._du->du_ident, (intptr_t)du._du->du_ident, func);
1054+
#else
10521055
(intptr_t)du._du->du_ident, (uintptr_t)du._du->du_ident, func);
1056+
#endif
10531057
}
10541058

10551059
#endif // RDAR_49023449

src/internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ upcast(dispatch_object_t dou)
277277
#include <sys/sysctl.h>
278278
#include <sys/queue.h>
279279
#endif
280+
#if defined(__FreeBSD__)
281+
#include <sys/eventfd.h>
282+
#endif // __FreeBSD__
280283
#include <sys/socket.h>
281284
#include <sys/time.h>
282285
#include <sys/mman.h>

src/io.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222

2323
#if defined(__FreeBSD__)
2424
#include <fcntl.h>
25-
#define F_RDADVISE F_RDAHEAD
2625
#endif
2726

2827
#ifndef DISPATCH_IO_DEBUG

src/queue.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6490,7 +6490,7 @@ _dispatch_runloop_queue_get_handle(dispatch_lane_t dq)
64906490
#elif defined(__linux__)
64916491
// decode: 0 is a valid fd, so offset by 1 to distinguish from NULL
64926492
return ((dispatch_runloop_handle_t)(uintptr_t)dq->do_ctxt) - 1;
6493-
#elif defined(__unix__) && !defined(__linux__)
6493+
#elif defined(__unix__)
64946494
return ((dispatch_runloop_handle_t)(uintptr_t)dq->do_ctxt);
64956495
#elif defined(_WIN32)
64966496
return ((dispatch_runloop_handle_t)(uintptr_t)dq->do_ctxt);
@@ -6509,7 +6509,7 @@ _dispatch_runloop_queue_set_handle(dispatch_lane_t dq,
65096509
#elif defined(__linux__)
65106510
// encode: 0 is a valid fd, so offset by 1 to distinguish from NULL
65116511
dq->do_ctxt = (void *)(uintptr_t)(handle + 1);
6512-
#elif defined(__unix__) && !defined(__linux__)
6512+
#elif defined(__unix__)
65136513
dq->do_ctxt = (void *)(uintptr_t)handle;
65146514
#elif defined(_WIN32)
65156515
dq->do_ctxt = (void *)(uintptr_t)handle;
@@ -6574,6 +6574,7 @@ _dispatch_runloop_queue_handle_init(void *ctxt)
65746574
}
65756575
handle = fd;
65766576
#elif defined(__unix__) && !defined(__linux__)
6577+
// swift-corelib-foundation PR #3004 implemented a pipe based queue handle
65776578
int fds[2];
65786579
int r = pipe2(fds, O_CLOEXEC | O_NONBLOCK);
65796580
if (r == -1) {

src/shims/lock.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,20 @@ _dispatch_thread_switch(dispatch_lock value, dispatch_lock_options_t flags,
5454
SwitchToThread();
5555
}
5656
#endif
57-
#endif
58-
59-
#if defined(__unix__)
57+
#elif defined(__FreeBSD__)
58+
#if !HAVE_UL_UNFAIR_LOCK
59+
DISPATCH_ALWAYS_INLINE
60+
static inline void
61+
_dispatch_thread_switch(dispatch_lock value, dispatch_lock_options_t flags,
62+
uint32_t timeout)
63+
{
64+
(void)value;
65+
(void)flags;
66+
(void)timeout;
67+
sched_yield();
68+
}
69+
#endif // HAVE_UL_UNFAIR_LOCK
70+
#elif defined(__unix__)
6071
#if !HAVE_UL_UNFAIR_LOCK && !HAVE_FUTEX_PI
6172
DISPATCH_ALWAYS_INLINE
6273
static inline void
@@ -539,6 +550,16 @@ _dispatch_wait_on_address(uint32_t volatile *_address, uint32_t value,
539550
? INFINITE : ((nsecs + 1000000) / 1000000);
540551
if (dwMilliseconds == 0) return ETIMEDOUT;
541552
return WaitOnAddress(address, &value, sizeof(value), dwMilliseconds) == TRUE;
553+
#elif defined(__FreeBSD__)
554+
(void)flags;
555+
if (nsecs != DISPATCH_TIME_FOREVER) {
556+
struct timespec ts = {
557+
.tv_sec = (__typeof__(ts.tv_sec))(nsecs / NSEC_PER_SEC),
558+
.tv_nsec = (__typeof__(ts.tv_nsec))(nsecs % NSEC_PER_SEC),
559+
};
560+
return _umtx_op((void*)address, UMTX_OP_WAIT_UINT, value, (void*)(uintptr_t)sizeof(struct timespec), (void*)&ts);
561+
}
562+
return _umtx_op((void*)address, UMTX_OP_WAIT_UINT, value, 0, 0);
542563
#else
543564
#error _dispatch_wait_on_address unimplemented for this platform
544565
#endif
@@ -553,6 +574,8 @@ _dispatch_wake_by_address(uint32_t volatile *address)
553574
_dispatch_futex_wake((uint32_t *)address, INT_MAX, FUTEX_PRIVATE_FLAG);
554575
#elif defined(_WIN32)
555576
WakeByAddressAll((uint32_t *)address);
577+
#elif defined(__FreeBSD__)
578+
_umtx_op((void*)address, UMTX_OP_WAKE, INT_MAX, 0, 0);
556579
#else
557580
(void)address;
558581
#endif
@@ -712,7 +735,7 @@ _dispatch_once_wait(dispatch_once_gate_t dgo)
712735
_dispatch_futex_wait(lock, (dispatch_lock)new_v, NULL,
713736
FUTEX_PRIVATE_FLAG);
714737
#else
715-
_dispatch_thread_switch(new_v, 0, timeout++);
738+
_dispatch_thread_switch((dispatch_lock)new_v, 0, timeout++);
716739
#endif
717740
(void)timeout;
718741
}

src/shims/lock.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,28 @@ _dispatch_lock_owner(dispatch_lock lock_value)
7979
return lock_value & DLOCK_OWNER_MASK;
8080
}
8181

82+
#elif defined(__FreeBSD__)
83+
84+
#include <sys/types.h>
85+
#include <sys/umtx.h>
86+
#include <sched.h>
87+
88+
typedef uint32_t dispatch_tid;
89+
typedef uint32_t dispatch_lock;
90+
91+
#define DLOCK_OWNER_NULL ((dispatch_tid)0)
92+
#define DLOCK_OWNER_MASK ((dispatch_lock)0xfffffffc)
93+
#define DLOCK_WAITERS_BIT ((dispatch_lock)0x00000001)
94+
#define DLOCK_FAILED_TRYLOCK_BIT ((dispatch_lock)0x00000002)
95+
#define _dispatch_tid_self() ((dispatch_tid)(_dispatch_get_tsd_base()->tid << 2))
96+
97+
DISPATCH_ALWAYS_INLINE
98+
static inline dispatch_tid
99+
_dispatch_lock_owner(dispatch_lock lock_value)
100+
{
101+
return lock_value & DLOCK_OWNER_MASK;
102+
}
103+
82104
#elif defined(_WIN32)
83105

84106
#include <Windows.h>

src/swift/Source.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,17 @@ extension DispatchSource {
124124
public static let exit = ProcessEvent(rawValue: 0x80000000)
125125
public static let fork = ProcessEvent(rawValue: 0x40000000)
126126
public static let exec = ProcessEvent(rawValue: 0x20000000)
127+
#if os(FreeBSD)
128+
public static let track = ProcessEvent(rawValue: 0x00000001)
129+
#else
127130
public static let signal = ProcessEvent(rawValue: 0x08000000)
131+
#endif
132+
133+
#if os(FreeBSD)
134+
public static let all: ProcessEvent = [.exit, .fork, .exec, .track]
135+
#else
128136
public static let all: ProcessEvent = [.exit, .fork, .exec, .signal]
137+
#endif
129138
}
130139
#endif
131140

@@ -224,7 +233,7 @@ extension DispatchSource {
224233
return DispatchSource(source: source) as DispatchSourceUserDataReplace
225234
}
226235

227-
#if !os(Linux) && !os(Android) && !os(Windows) && !os(OpenBSD)
236+
#if !os(Linux) && !os(Android) && !os(Windows) && !os(OpenBSD) && !os(FreeBSD)
228237
public class func makeFileSystemObjectSource(fileDescriptor: Int32, eventMask: FileSystemEvent, queue: DispatchQueue? = nil) -> DispatchSourceFileSystemObject {
229238
let source = dispatch_source_create(_swift_dispatch_source_type_VNODE(), UInt(fileDescriptor), eventMask.rawValue, queue?.__wrapped)
230239
return DispatchSource(source: source) as DispatchSourceFileSystemObject
@@ -293,7 +302,7 @@ extension DispatchSourceMemoryPressure {
293302
#if !os(Linux) && !os(Android) && !os(Windows) && !os(OpenBSD)
294303
extension DispatchSourceProcess {
295304
public var handle: pid_t {
296-
return pid_t(dispatch_source_get_handle(self as! DispatchSource))
305+
return pid_t(CDispatch.dispatch_source_get_handle((self as! DispatchSource).__wrapped))
297306
}
298307

299308
public var data: DispatchSource.ProcessEvent {

src/swift/Wrapper.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,12 @@ extension DispatchSource : DispatchSourceMachSend,
183183
#endif
184184

185185
#if !os(Linux) && !os(Android) && !os(Windows) && !os(OpenBSD)
186-
extension DispatchSource : DispatchSourceProcess,
187-
DispatchSourceFileSystemObject {
186+
extension DispatchSource : DispatchSourceProcess {
187+
}
188+
#endif
189+
190+
#if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) && !os(OpenBSD)
191+
extension DispatchSource : DispatchSourceFileSystemObject {
188192
}
189193
#endif
190194

src/swift/shims/DispatchOverlayShims.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ SWIFT_DISPATCH_SOURCE_TYPE(PROC)
8888
SWIFT_DISPATCH_SOURCE_TYPE(VNODE)
8989
#endif
9090

91+
#if defined(__FreeBSD__)
92+
SWIFT_DISPATCH_SOURCE_TYPE(PROC)
93+
SWIFT_DISPATCH_SOURCE_TYPE(VNODE)
94+
#endif
95+
9196
extern void
9297
_swift_dispatch_source_create_abort(void);
9398

tests/bsdtestharness.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ main(int argc, char *argv[])
212212
#else
213213
dispatch_queue_t main_q = dispatch_get_main_queue();
214214

215-
dispatch_source_t tmp_ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid, DISPATCH_PROC_EXIT, main_q);
215+
dispatch_source_t tmp_ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, (uintptr_t)pid, DISPATCH_PROC_EXIT, main_q);
216216
assert(tmp_ds);
217217
dispatch_source_set_event_handler(tmp_ds, ^{
218218
int status;

tests/dispatch_apply.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ static void busythread(void *ignored)
8181
static void test_apply_contended(dispatch_queue_t dq)
8282
{
8383
uint32_t activecpu;
84-
#if defined(__linux__) || defined(__OpenBSD__)
84+
#if defined(__linux__) || defined(__OpenBSD__) || defined(__FreeBSD__)
8585
activecpu = (uint32_t)sysconf(_SC_NPROCESSORS_ONLN);
8686
#elif defined(_WIN32)
8787
SYSTEM_INFO si;

tests/dispatch_io_pipe.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ test_get_pipe_buffer_size(int kind)
9090
CloseHandle(write_handle);
9191
});
9292
return size;
93+
#elif defined(__FreeBSD__)
94+
// buffer size of blocking and non-blocking pipes is different on FreeBSD
95+
(void)kind;
96+
return PIPE_BUF;
9397
#else
9498
(void)kind;
9599
static dispatch_once_t once;

tests/dispatch_select.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ void finish(void* cxt);
3939
void
4040
stage1(int stage)
4141
{
42-
#if defined(_WIN32)
42+
#if defined(_WIN32) || defined(__FreeBSD__)
4343
char *path = dispatch_test_get_large_file();
4444
dispatch_fd_t fd = dispatch_test_fd_open(path, O_RDONLY);
4545
if (fd == -1)

0 commit comments

Comments
 (0)