From 7f80dcbeb09f4dd743cdccfb2cfed10bfdeb07ab Mon Sep 17 00:00:00 2001 From: Willow Barraco Date: Fri, 13 Dec 2024 14:47:33 +0100 Subject: [PATCH] Controll concurrent events priority This new file.prio parameter give some control to the user over concurrent events. Say that a timer expires, but a concurrent event would re-arm it, the user have no way to predict if the timer callback will trigger. Signed-off-by: Willow Barraco --- ev/+linux/file.ha | 22 ++++++++++++++++++++++ ev/+linux/loop.ha | 3 +++ diff --git a/ev/+linux/file.ha b/ev/+linux/file.ha index e79e35fa4a0892f71f30064ebdce8902ba85c8f9..b412408490d25c806f7a54d36cf5a3a99fc33155 100644 --- a/ev/+linux/file.ha +++ b/ev/+linux/file.ha @@ -38,6 +38,8 @@ cb: nullable *opaque, cb2: nullable *opaque, user: nullable *opaque, + prio: int, + // Operation-specific data union { struct { @@ -151,6 +153,26 @@ // Returns the event loop for a given file. export fn getloop(file: *file) *loop = { return file.ev; +}; + +// Sets the priority on this file object. Used to priorize concurrent events, +// starting on the next dispatch. The lowest run first. +export fn setprio(file: *file, prio: int) void = { + file.prio = prio; +}; + +fn sort_events(a: const *opaque, b: const *opaque) int = { + const a = a: *rt::epoll_event; + const b = b: *rt::epoll_event; + + if (a.data.fd == 0 || b.data.fd == 0) { + return 0; + }; + + const a = a.data.ptr: *file; + const b = b.data.ptr: *file; + + return a.prio - b.prio; }; // Updates epoll events for a given file. For internal use. diff --git a/ev/+linux/loop.ha b/ev/+linux/loop.ha index 98ff45a9033d908eb041a133a1e83665a8253b44..145273adf7db6f9b7949c5e73cef130ec32b5e75 100644 --- a/ev/+linux/loop.ha +++ b/ev/+linux/loop.ha @@ -1,6 +1,7 @@ use errors; use io; use rt; +use sort; use time; use types; use unix::signal; @@ -151,6 +152,8 @@ if (nevent == 0) { return true; }; + + sort::sort(loop.events[..nevent], size(rt::epoll_event), &sort_events); for (let ev &.. loop.events[..nevent]) { const file = ev.data.ptr: *file; -- 2.48.1