authorgravatar for semarie@online.frSébastien Marie <semarie@online.fr> 2021-09-04 07:16:26+00:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-07 14:59:33-04:00
logc2f585e4357f07761c522d67568ecedf8d22c668
tree97d9ace7857cfbc30518dfc7c5d5d5142823a927
parentf1126e854c9dbe6a58cef66b380c0a7bb95f06d4

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.

1 files changed, 64 insertions(+), 1 deletions(-)

lib/std/event/loop.zig+64-1
...@@ -266,7 +266,7 @@ pub const Loop = struct {...@@ -266,7 +266,7 @@ pub const Loop = struct {
266 self.extra_threads[extra_thread_index] = try Thread.spawn(.{}, workerRun, .{self});266 self.extra_threads[extra_thread_index] = try Thread.spawn(.{}, workerRun, .{self});
267 }267 }
268 },268 },
269 .macos, .freebsd, .netbsd, .dragonfly, .openbsd => {269 .macos, .freebsd, .netbsd, .dragonfly => {
270 self.os_data.kqfd = try os.kqueue();270 self.os_data.kqfd = try os.kqueue();
271 errdefer os.close(self.os_data.kqfd);271 errdefer os.close(self.os_data.kqfd);
272272
...@@ -331,6 +331,69 @@ pub const Loop = struct {...@@ -331,6 +331,69 @@ pub const Loop = struct {
331 self.extra_threads[extra_thread_index] = try Thread.spawn(.{}, workerRun, .{self});331 self.extra_threads[extra_thread_index] = try Thread.spawn(.{}, workerRun, .{self});
332 }332 }
333 },333 },
334 .openbsd => {
335 self.os_data.kqfd = try os.kqueue();
336 errdefer os.close(self.os_data.kqfd);
337
338 const empty_kevs = &[0]os.Kevent{};
339
340 for (self.eventfd_resume_nodes) |*eventfd_node, i| {
341 eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{
342 .data = ResumeNode.EventFd{
343 .base = ResumeNode{
344 .id = ResumeNode.Id.EventFd,
345 .handle = undefined,
346 .overlapped = ResumeNode.overlapped_init,
347 },
348 // this one is for sending events
349 .kevent = os.Kevent{
350 .ident = i,
351 .filter = os.EVFILT_TIMER,
352 .flags = os.EV_CLEAR | os.EV_ADD | os.EV_DISABLE | os.EV_ONESHOT,
353 .fflags = 0,
354 .data = 0,
355 .udata = @ptrToInt(&eventfd_node.data.base),
356 },
357 },
358 .next = undefined,
359 };
360 self.available_eventfd_resume_nodes.push(eventfd_node);
361 const kevent_array = @as(*const [1]os.Kevent, &eventfd_node.data.kevent);
362 _ = try os.kevent(self.os_data.kqfd, kevent_array, empty_kevs, null);
363 eventfd_node.data.kevent.flags = os.EV_CLEAR | os.EV_ENABLE;
364 }
365
366 // Pre-add so that we cannot get error.SystemResources
367 // later when we try to activate it.
368 self.os_data.final_kevent = os.Kevent{
369 .ident = extra_thread_count,
370 .filter = os.EVFILT_TIMER,
371 .flags = os.EV_ADD | os.EV_ONESHOT | os.EV_DISABLE,
372 .fflags = 0,
373 .data = 0,
374 .udata = @ptrToInt(&self.final_resume_node),
375 };
376 const final_kev_arr = @as(*const [1]os.Kevent, &self.os_data.final_kevent);
377 _ = try os.kevent(self.os_data.kqfd, final_kev_arr, empty_kevs, null);
378 self.os_data.final_kevent.flags = os.EV_ENABLE;
379
380 if (builtin.single_threaded) {
381 assert(extra_thread_count == 0);
382 return;
383 }
384
385 var extra_thread_index: usize = 0;
386 errdefer {
387 _ = os.kevent(self.os_data.kqfd, final_kev_arr, empty_kevs, null) catch unreachable;
388 while (extra_thread_index != 0) {
389 extra_thread_index -= 1;
390 self.extra_threads[extra_thread_index].join();
391 }
392 }
393 while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {
394 self.extra_threads[extra_thread_index] = try Thread.spawn(.{}, workerRun, .{self});
395 }
396 },
334 .windows => {397 .windows => {
335 self.os_data.io_port = try windows.CreateIoCompletionPort(398 self.os_data.io_port = try windows.CreateIoCompletionPort(
336 windows.INVALID_HANDLE_VALUE,399 windows.INVALID_HANDLE_VALUE,