Genode: add scheduleCallbacks to asyncdispatch (#20708)
* Genode: add native signal handler * Genode: add scheduleCallbacks to asyncdispatch This resolves some awkwardness where an RPC server may or may not use callSoon while dispatching RPC but without scheduling timers or I/O.
This commit is contained in:
parent
39f925b95d
commit
0b262e9496
5 changed files with 188 additions and 3 deletions
|
|
@ -281,6 +281,8 @@ proc adjustTimeout(
|
|||
result = max(nextTimer.get(), 0)
|
||||
result = min(pollTimeout, result)
|
||||
|
||||
proc runOnce(timeout: int): bool {.gcsafe.}
|
||||
|
||||
proc callSoon*(cbproc: proc () {.gcsafe.}) {.gcsafe.}
|
||||
## Schedule `cbproc` to be called as soon as possible.
|
||||
## The callback is called when control returns to the event loop.
|
||||
|
|
@ -390,7 +392,7 @@ when defined(windows) or defined(nimdoc):
|
|||
let p = getGlobalDispatcher()
|
||||
p.handles.len != 0 or p.timers.len != 0 or p.callbacks.len != 0
|
||||
|
||||
proc runOnce(timeout = 500): bool =
|
||||
proc runOnce(timeout: int): bool =
|
||||
let p = getGlobalDispatcher()
|
||||
if p.handles.len == 0 and p.timers.len == 0 and p.callbacks.len == 0:
|
||||
raise newException(ValueError,
|
||||
|
|
@ -1169,6 +1171,9 @@ else:
|
|||
MSG_NOSIGNAL
|
||||
when declared(posix.accept4):
|
||||
from posix import accept4, SOCK_CLOEXEC
|
||||
when defined(genode):
|
||||
include genode/env # get the implicit Genode env
|
||||
import genode/signals
|
||||
|
||||
const
|
||||
InitCallbackListSize = 4 # initial size of callbacks sequence,
|
||||
|
|
@ -1187,6 +1192,8 @@ else:
|
|||
|
||||
PDispatcher* = ref object of PDispatcherBase
|
||||
selector: Selector[AsyncData]
|
||||
when defined(genode):
|
||||
signalHandler: SignalHandler
|
||||
|
||||
proc `==`*(x, y: AsyncFD): bool {.borrow.}
|
||||
proc `==`*(x, y: AsyncEvent): bool {.borrow.}
|
||||
|
|
@ -1202,6 +1209,10 @@ else:
|
|||
result.selector = newSelector[AsyncData]()
|
||||
result.timers.clear()
|
||||
result.callbacks = initDeque[proc () {.closure, gcsafe.}](InitDelayedCallbackListSize)
|
||||
when defined(genode):
|
||||
let entrypoint = ep(cast[GenodeEnv](runtimeEnv))
|
||||
result.signalHandler = newSignalHandler(entrypoint):
|
||||
discard runOnce(0)
|
||||
|
||||
var gDisp{.threadvar.}: owned PDispatcher ## Global dispatcher
|
||||
|
||||
|
|
@ -1371,10 +1382,11 @@ else:
|
|||
ValueError, "Expecting async operations to stop when fd has closed."
|
||||
)
|
||||
|
||||
|
||||
proc runOnce(timeout = 500): bool =
|
||||
proc runOnce(timeout: int): bool =
|
||||
let p = getGlobalDispatcher()
|
||||
if p.selector.isEmpty() and p.timers.len == 0 and p.callbacks.len == 0:
|
||||
when defined(genode):
|
||||
if timeout == 0: return
|
||||
raise newException(ValueError,
|
||||
"No handles or timers registered in dispatcher.")
|
||||
|
||||
|
|
@ -2025,3 +2037,17 @@ when defined(linux) or defined(windows) or defined(macosx) or defined(bsd) or
|
|||
if getrlimit(RLIMIT_NOFILE, fdLim) < 0:
|
||||
raiseOSError(osLastError())
|
||||
result = int(fdLim.rlim_cur) - 1
|
||||
|
||||
when defined(genode):
|
||||
proc scheduleCallbacks*(): bool {.discardable.} =
|
||||
## *Genode only.*
|
||||
## Schedule callback processing and return immediately.
|
||||
## Returns `false` if there is nothing to schedule.
|
||||
## RPC servers should call this to dispatch `callSoon`
|
||||
## bodies after retiring an RPC to its client.
|
||||
## This is effectively a non-blocking `poll(…)` and is
|
||||
## equivalent to scheduling a momentary no-op timeout
|
||||
## but faster and with less overhead.
|
||||
let dis = getGlobalDispatcher()
|
||||
result = dis.callbacks.len > 0
|
||||
if result: submit(dis.signalHandler.cap)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue