Skip to content

Commit 6a357d1

Browse files
cryptocodenikneym
authored andcommitted
Initial FreeBSD support
1 parent ac452bc commit 6a357d1

File tree

5 files changed

+90
-75
lines changed

5 files changed

+90
-75
lines changed

src/backend/kqueue.zig

Lines changed: 79 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ pub fn available() bool {
2727
};
2828
}
2929

30+
const NOTE_EXIT_FLAGS = switch (builtin.os.tag) {
31+
.ios, .macos => posix.system.NOTE_EXIT | posix.system.NOTE_EXITSTATUS,
32+
.freebsd => posix.system.NOTE_EXIT,
33+
else => @compileError("kqueue not supported yet for target OS"),
34+
};
35+
3036
pub const Loop = struct {
3137
const TimerHeap = heap.Intrusive(Timer, void, Timer.less);
3238
const TaskCompletionQueue = queue_mpsc.Intrusive(Completion);
@@ -38,8 +44,8 @@ pub const Loop = struct {
3844
/// an empty message to this port can be used to wake up the loop
3945
/// at any time. Waking up the loop via this port won't trigger any
4046
/// particular completion, it just forces tick to cycle.
41-
mach_port: xev.Async,
42-
mach_port_buffer: [32]u8 = undefined,
47+
//mach_port: xev.Async,
48+
//mach_port_buffer: [32]u8 = undefined,
4349

4450
/// The number of active completions. This DOES NOT include completions that
4551
/// are queued in the submissions queue.
@@ -99,7 +105,7 @@ pub const Loop = struct {
99105

100106
var res: Loop = .{
101107
.kqueue_fd = fd,
102-
.mach_port = mach_port,
108+
// .mach_port = mach_port,
103109
.thread_pool = options.thread_pool,
104110
.thread_pool_completions = undefined,
105111
.cached_now = undefined,
@@ -310,30 +316,30 @@ pub const Loop = struct {
310316

311317
// Add our event so that we wake up when our mach port receives an
312318
// event. We have to add here because we need a stable self pointer.
313-
const events = [_]Kevent{.{
314-
.ident = @as(usize, @intCast(self.mach_port.port)),
315-
.filter = std.c.EVFILT.MACHPORT,
316-
.flags = std.c.EV.ADD | std.c.EV.ENABLE,
317-
.fflags = darwin.MACH_RCV_MSG,
318-
.data = 0,
319-
.udata = 0,
320-
.ext = .{
321-
@intFromPtr(&self.mach_port_buffer),
322-
self.mach_port_buffer.len,
323-
},
324-
}};
325-
const n = kevent_syscall(
326-
self.kqueue_fd,
327-
&events,
328-
events[0..0],
329-
null,
330-
) catch |err| {
331-
// We reset initialization because we can't do anything
332-
// safely unless we get this mach port registered!
333-
self.flags.init = false;
334-
return err;
335-
};
336-
assert(n == 0);
319+
//const events = [_]Kevent{.{
320+
// .ident = @as(usize, @intCast(self.mach_port.port)),
321+
// .filter = std.c.EVFILT.MACHPORT,
322+
// .flags = std.c.EV.ADD | std.c.EV.ENABLE,
323+
// .fflags = darwin.MACH_RCV_MSG,
324+
// .data = 0,
325+
// .udata = 0,
326+
// .ext = .{
327+
// @intFromPtr(&self.mach_port_buffer),
328+
// self.mach_port_buffer.len,
329+
// },
330+
//}};
331+
//const n = kevent_syscall(
332+
// self.kqueue_fd,
333+
// &events,
334+
// events[0..0],
335+
// null,
336+
//) catch |err| {
337+
// // We reset initialization because we can't do anything
338+
// // safely unless we get this mach port registered!
339+
// self.flags.init = false;
340+
// return err;
341+
//};
342+
//assert(n == 0);
337343
}
338344

339345
// The list of events, used as both a changelist and eventlist.
@@ -793,10 +799,10 @@ pub const Loop = struct {
793799
break :action .{ .kevent = {} };
794800
},
795801

796-
.machport => action: {
797-
ev.* = c.kevent().?;
798-
break :action .{ .kevent = {} };
799-
},
802+
// .machport => action: {
803+
// ev.* = c.kevent().?;
804+
// break :action .{ .kevent = {} };
805+
// },
800806

801807
.proc => action: {
802808
ev.* = c.kevent().?;
@@ -966,7 +972,7 @@ pub const Loop = struct {
966972
/// Sends an empty message to this loop's mach port so that it wakes
967973
/// up if it is blocking on kevent().
968974
fn wakeup(self: *Loop) !void {
969-
try self.mach_port.notify();
975+
//try self.mach_port.notify();
970976
}
971977
};
972978

@@ -1073,27 +1079,27 @@ pub const Completion = struct {
10731079
.udata = @intFromPtr(self),
10741080
}),
10751081

1076-
.machport => kevent: {
1077-
// We can't use |*v| above because it crahses the Zig
1078-
// compiler (as of 0.11.0-dev.1413). We can retry another time.
1079-
const v = &self.op.machport;
1080-
const slice: []u8 = switch (v.buffer) {
1081-
.slice => |slice| slice,
1082-
.array => |*arr| arr,
1083-
};
1082+
// .machport => kevent: {
1083+
// // We can't use |*v| above because it crahses the Zig
1084+
// // compiler (as of 0.11.0-dev.1413). We can retry another time.
1085+
// const v = &self.op.machport;
1086+
// const slice: []u8 = switch (v.buffer) {
1087+
// .slice => |slice| slice,
1088+
// .array => |*arr| arr,
1089+
// };
10841090

10851091
// The kevent below waits for a machport to have a message
10861092
// available AND automatically reads the message into the
10871093
// buffer since MACH_RCV_MSG is set.
1088-
break :kevent .{
1089-
.ident = @intCast(v.port),
1090-
.filter = std.c.EVFILT.MACHPORT,
1091-
.flags = std.c.EV.ADD | std.c.EV.ENABLE,
1092-
.fflags = darwin.MACH_RCV_MSG,
1093-
.data = 0,
1094-
.udata = @intFromPtr(self),
1095-
.ext = .{ @intFromPtr(slice.ptr), slice.len },
1096-
};
1094+
//break :kevent .{
1095+
// .ident = @intCast(v.port),
1096+
// .filter = std.c.EVFILT.MACHPORT,
1097+
// .flags = std.c.EV.ADD | std.c.EV.ENABLE,
1098+
// .fflags = darwin.MACH_RCV_MSG,
1099+
// .data = 0,
1100+
// .udata = @intFromPtr(self),
1101+
// .ext = .{ @intFromPtr(slice.ptr), slice.len },
1102+
//};
10971103
},
10981104

10991105
.proc => |v| kevent_init(.{
@@ -1257,16 +1263,16 @@ pub const Completion = struct {
12571263
// Our machport operation ALWAYS has MACH_RCV set so there
12581264
// is no operation to perform. kqueue automatically reads in
12591265
// the mach message into the read buffer.
1260-
.machport => .{
1261-
.machport = {},
1262-
},
1266+
// .machport => .{
1267+
// .machport = {},
1268+
// },
12631269

12641270
// For proc watching, it is identical to the syscall result.
12651271
.proc => res: {
12661272
const ev = ev_ orelse break :res .{ .proc = ProcError.MissingKevent };
12671273

12681274
// If we have the exit status, we read it.
1269-
if (ev.fflags & (std.c.NOTE.EXIT | std.c.NOTE.EXITSTATUS) > 0) {
1275+
if (ev.fflags & NOTE_EXIT_FLAGS > 0) {
12701276
const data: u32 = @intCast(ev.data);
12711277
if (posix.W.IFEXITED(data)) break :res .{
12721278
.proc = posix.W.EXITSTATUS(data),
@@ -1373,13 +1379,13 @@ pub const Completion = struct {
13731379
},
13741380
},
13751381

1376-
.machport => .{
1377-
.machport = switch (errno) {
1378-
.SUCCESS => {},
1379-
.CANCELED => error.Canceled,
1380-
else => |err| posix.unexpectedErrno(err),
1381-
},
1382-
},
1382+
// .machport => .{
1383+
// .machport = switch (errno) {
1384+
// .SUCCESS => {},
1385+
// .CANCELED => error.Canceled,
1386+
// else => |err| posix.unexpectedErrno(err),
1387+
// },
1388+
// },
13831389

13841390
.proc => .{
13851391
.proc = switch (errno) {
@@ -1449,7 +1455,7 @@ pub const OperationType = enum {
14491455
shutdown,
14501456
timer,
14511457
cancel,
1452-
machport,
1458+
// machport,
14531459
proc,
14541460
};
14551461

@@ -1535,14 +1541,14 @@ pub const Operation = union(OperationType) {
15351541
c: *Completion,
15361542
},
15371543

1538-
machport: struct {
1539-
port: posix.system.mach_port_name_t,
1540-
buffer: ReadBuffer,
1541-
},
1544+
// machport: struct {
1545+
// port: posix.system.mach_port_name_t,
1546+
// buffer: ReadBuffer,
1547+
// },
15421548

15431549
proc: struct {
15441550
pid: posix.pid_t,
1545-
flags: u32 = std.c.NOTE.EXIT | std.c.NOTE.EXITSTATUS,
1551+
flags: u32 = NOTE_EXIT_FLAGS,
15461552
},
15471553
};
15481554

@@ -1562,7 +1568,7 @@ pub const Result = union(OperationType) {
15621568
shutdown: ShutdownError!void,
15631569
timer: TimerError!TimerTrigger,
15641570
cancel: CancelError!void,
1565-
machport: MachPortError!void,
1571+
// machport: MachPortError!void,
15661572
proc: ProcError!u32,
15671573
};
15681574

@@ -1609,10 +1615,10 @@ pub const WriteError = posix.KEventError ||
16091615
Unexpected,
16101616
};
16111617

1612-
pub const MachPortError = posix.KEventError || error{
1613-
Canceled,
1614-
Unexpected,
1615-
};
1618+
// pub const MachPortError = posix.KEventError || error{
1619+
// Canceled,
1620+
// Unexpected,
1621+
// };
16161622

16171623
pub const ProcError = posix.KEventError || error{
16181624
Canceled,
@@ -1734,6 +1740,7 @@ const Timer = struct {
17341740
/// This lets us support both Mac and non-Mac platforms.
17351741
const Kevent = switch (builtin.os.tag) {
17361742
.ios, .macos => posix.system.kevent64_s,
1743+
.freebsd => std.c.Kevent,
17371744
else => @compileError("kqueue not supported yet for target OS"),
17381745
};
17391746

@@ -2416,6 +2423,7 @@ test "kqueue: socket accept/connect/send/recv/close" {
24162423
}
24172424

24182425
test "kqueue: file IO on thread pool" {
2426+
if (builtin.os.tag != .macos) return error.SkipZigTest;
24192427
const testing = std.testing;
24202428

24212429
var tpool = main.ThreadPool.init(.{});

src/main.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub const Backend = enum {
5252
pub fn default() Backend {
5353
return switch (builtin.os.tag) {
5454
.linux => .io_uring,
55-
.ios, .macos => .kqueue,
55+
.ios, .macos, .freebsd => .kqueue,
5656
.wasi => .wasi_poll,
5757
.windows => .iocp,
5858
else => {

src/watcher/async.zig

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,23 @@ const posix = std.posix;
66
const common = @import("common.zig");
77
const darwin = @import("../darwin.zig");
88

9+
pub extern "c" fn eventfd(initval: c_uint, flags: c_uint) c_int;
10+
911
pub fn Async(comptime xev: type) type {
1012
if (xev.dynamic) return AsyncDynamic(xev);
1113

1214
return switch (xev.backend) {
1315
// Supported, uses eventfd
1416
.io_uring,
1517
.epoll,
18+
.kqueue,
1619
=> AsyncEventFd(xev),
1720

1821
// Supported, uses the backend API
1922
.wasi_poll => AsyncLoopState(xev, xev.Loop.threaded),
2023

2124
// Supported, uses mach ports
22-
.kqueue => AsyncMachPort(xev),
25+
// .kqueue => AsyncMachPort(xev),
2326
.iocp => AsyncIOCP(xev),
2427
};
2528
}
@@ -39,7 +42,8 @@ fn AsyncEventFd(comptime xev: type) type {
3942
/// to be woken up. The completion must be allocated in advance.
4043
pub fn init() !Self {
4144
return .{
42-
.fd = try std.posix.eventfd(0, std.os.linux.EFD.CLOEXEC),
45+
//.fd = try std.posix.eventfd(0, std.os.linux.EFD.CLOEXEC),
46+
.fd = eventfd(0, 0),
4347
};
4448
}
4549

src/watcher/file.zig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ fn FileTests(
575575
if (builtin.os.tag == .wasi) return error.SkipZigTest;
576576
// windows: std.fs.File is not opened with OVERLAPPED flag.
577577
if (builtin.os.tag == .windows) return error.SkipZigTest;
578+
if (builtin.os.tag == .freebsd) return error.SkipZigTest;
578579

579580
const testing = std.testing;
580581

@@ -649,6 +650,7 @@ fn FileTests(
649650
if (builtin.os.tag == .wasi) return error.SkipZigTest;
650651
// windows: std.fs.File is not opened with OVERLAPPED flag.
651652
if (builtin.os.tag == .windows) return error.SkipZigTest;
653+
if (builtin.os.tag == .freebsd) return error.SkipZigTest;
652654

653655
const testing = std.testing;
654656

@@ -721,6 +723,7 @@ fn FileTests(
721723
if (builtin.os.tag == .wasi) return error.SkipZigTest;
722724
// windows: std.fs.File is not opened with OVERLAPPED flag.
723725
if (builtin.os.tag == .windows) return error.SkipZigTest;
726+
if (builtin.os.tag == .freebsd) return error.SkipZigTest;
724727

725728
const testing = std.testing;
726729

src/watcher/process.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ fn ProcessKqueue(comptime xev: type) type {
183183
.op = .{
184184
.proc = .{
185185
.pid = self.pid,
186-
.flags = std.c.NOTE.EXIT | std.c.NOTE.EXITSTATUS,
186+
.flags = xev.Sys.NOTE_EXIT_FLAGS,
187187
},
188188
},
189189

0 commit comments

Comments
 (0)