diff options
| author | Sébastien Marie <semarie@online.fr> | 2021-09-04 07:16:26 +0000 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-09-07 14:59:33 -0400 |
| commit | c2f585e4357f07761c522d67568ecedf8d22c668 (patch) | |
| tree | 97d9ace7857cfbc30518dfc7c5d5d5142823a927 /lib/std/event/loop.zig | |
| parent | f1126e854c9dbe6a58cef66b380c0a7bb95f06d4 (diff) | |
| download | zig-c2f585e4357f07761c522d67568ecedf8d22c668.tar.gz zig-c2f585e4357f07761c522d67568ecedf8d22c668.zip | |
openbsd: event loop: use EVFILT_TIMER instead of EVFILT_USER
OpenBSD doesn't implement EVFILT_USER filter for kqueue(2), so we couldn't use that for event loop.
instead, use a EVFILT_TIMER filter with EV_ONESHOT (trigger only once) and delay 0sec (which trigger immediatly).
it fits the usage of EVFILT_USER which is only used to "wakeup" the kevent(2) call from userland.
Diffstat (limited to 'lib/std/event/loop.zig')
| -rw-r--r-- | lib/std/event/loop.zig | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index 6a69d6fcc4..2e23704ec2 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -266,7 +266,7 @@ pub const Loop = struct { self.extra_threads[extra_thread_index] = try Thread.spawn(.{}, workerRun, .{self}); } }, - .macos, .freebsd, .netbsd, .dragonfly, .openbsd => { + .macos, .freebsd, .netbsd, .dragonfly => { self.os_data.kqfd = try os.kqueue(); errdefer os.close(self.os_data.kqfd); @@ -331,6 +331,69 @@ pub const Loop = struct { self.extra_threads[extra_thread_index] = try Thread.spawn(.{}, workerRun, .{self}); } }, + .openbsd => { + self.os_data.kqfd = try os.kqueue(); + errdefer os.close(self.os_data.kqfd); + + const empty_kevs = &[0]os.Kevent{}; + + for (self.eventfd_resume_nodes) |*eventfd_node, i| { + eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{ + .data = ResumeNode.EventFd{ + .base = ResumeNode{ + .id = ResumeNode.Id.EventFd, + .handle = undefined, + .overlapped = ResumeNode.overlapped_init, + }, + // this one is for sending events + .kevent = os.Kevent{ + .ident = i, + .filter = os.EVFILT_TIMER, + .flags = os.EV_CLEAR | os.EV_ADD | os.EV_DISABLE | os.EV_ONESHOT, + .fflags = 0, + .data = 0, + .udata = @ptrToInt(&eventfd_node.data.base), + }, + }, + .next = undefined, + }; + self.available_eventfd_resume_nodes.push(eventfd_node); + const kevent_array = @as(*const [1]os.Kevent, &eventfd_node.data.kevent); + _ = try os.kevent(self.os_data.kqfd, kevent_array, empty_kevs, null); + eventfd_node.data.kevent.flags = os.EV_CLEAR | os.EV_ENABLE; + } + + // Pre-add so that we cannot get error.SystemResources + // later when we try to activate it. + self.os_data.final_kevent = os.Kevent{ + .ident = extra_thread_count, + .filter = os.EVFILT_TIMER, + .flags = os.EV_ADD | os.EV_ONESHOT | os.EV_DISABLE, + .fflags = 0, + .data = 0, + .udata = @ptrToInt(&self.final_resume_node), + }; + const final_kev_arr = @as(*const [1]os.Kevent, &self.os_data.final_kevent); + _ = try os.kevent(self.os_data.kqfd, final_kev_arr, empty_kevs, null); + self.os_data.final_kevent.flags = os.EV_ENABLE; + + if (builtin.single_threaded) { + assert(extra_thread_count == 0); + return; + } + + var extra_thread_index: usize = 0; + errdefer { + _ = os.kevent(self.os_data.kqfd, final_kev_arr, empty_kevs, null) catch unreachable; + while (extra_thread_index != 0) { + extra_thread_index -= 1; + self.extra_threads[extra_thread_index].join(); + } + } + while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) { + self.extra_threads[extra_thread_index] = try Thread.spawn(.{}, workerRun, .{self}); + } + }, .windows => { self.os_data.io_port = try windows.CreateIoCompletionPort( windows.INVALID_HANDLE_VALUE, |
