Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
internal.h File Reference
#include <stdatomic.h>
#include "serene/rt/context.h"
#include "serene/rt/fiber/thread.h"
#include "serene/rt/impl/pqmh.h"
#include "serene/rt/impl/spsc_ring.h"
#include "serene/rt/reactor.h"
Include dependency graph for internal.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  srn_reactor_io_channel_t
 A channel, the per-worker submission and completion ring pair. More...
struct  srn_reactor_t

Typedefs

typedef struct srn_reactor_io_channel_t srn_reactor_io_channel_t
 A channel, the per-worker submission and completion ring pair.

Functions

void srn_reactor_post_completion (srn_reactor_t *reactor, size_t channel, srn_reactor_io_completion_t completion)
 Post a finished operation to channel's completion queue and rouse the channel's worker through the notify mechanism.
srn_error_t * srn_reactor_errors_static (srn_error_tag_t tag)
 Return the shared, immutable error for an IO failure tag.

Typedef Documentation

◆ srn_reactor_io_channel_t

typedef struct srn_reactor_io_channel_t srn_reactor_io_channel_t

A channel, the per-worker submission and completion ring pair.

Function Documentation

◆ srn_reactor_errors_static()

srn_error_t * srn_reactor_errors_static ( srn_error_tag_t tag)

Return the shared, immutable error for an IO failure tag.

These live in static storage, not a context, so a completion or result can point one at maybe_error with no allocation and no lifetime concern, and it is safe to share across threads. A backend maps its native code (via srn_errno_to_tag on POSIX) to a tag, then to one of these. Any tag without a dedicated entry yields the UNKNOWN_IO_ERROR error.

Because they are shared they are never written to. In particular they are not trace targets, srn_error_trace_push, PUSH_TRACE and PUSH_AND_MOVE would allocate frames in one caller's context and record unrelated call sites into every later failure with the same tag. A caller that wants a trace on an IO failure builds its own error from the static one with ERR_FROM and traces that.

Definition at line 194 of file reactor.c.

194 {
195
196 size_t count = sizeof(io_errors) / sizeof(io_errors[0]);
197
198 for (size_t i = 0; i < count; i++) {
199 if (io_errors[i].tag == tag) {
200 return &io_errors[i];
201 }
202 }
203 // the UNKNOWN_IO_ERROR fallback
204 return &io_errors[count - 1];
205}
static srn_error_t io_errors[]
Definition reactor.c:99
Here is the caller graph for this function:

◆ srn_reactor_post_completion()

void srn_reactor_post_completion ( srn_reactor_t * reactor,
size_t channel,
srn_reactor_io_completion_t completion )

Post a finished operation to channel's completion queue and rouse the channel's worker through the notify mechanism.

Runs on the reactor thread, called by the core for ops it completes itself (such as NOP) and by a backend when a descriptor operation finishes. It does NOT drop the in-flight count: that is the consumer's job via srn_reactor_op_done, so an op counts as gone only once the waiting fiber has been readied, never in the gap between.

Definition at line 210 of file reactor.c.

212 {
213 srn_reactor_io_channel_t *ch = &reactor->channels[channel];
214 // Admission control bounds a channel's in-flight ops at the ring capacity,
215 // and the op being posted is one of them and not yet in the CQ, so the CQ
216 // always has a slot. A full CQ here means the accounting is broken; a spin
217 // in its place would stall the whole reactor behind one busy worker.
218 PANIC_IF(
219 !srn_spsc_ring_push(ch->cq, &completion),
220 "reactor: completion queue full despite admission control; this is a bug"
221 );
222
224 reactor_complete, channel, completion.result, completion.maybe_error != nullptr,
225 completion.fiber_data
226 );
227
228 // The in-flight count is dropped by the consumer through srn_reactor_op_done,
229 // not here. A fiber's waiter must be readied before the op counts as gone, or
230 // quiescence could fire in the gap between posting and readying.
231 if (reactor->notify != nullptr) {
232 reactor->notify(reactor->ctx->engine->scheduler, channel);
233 }
234}
#define REACTOR_TRACEPOINT(...)
Definition reactor.h:58
bool srn_spsc_ring_push(srn_spsc_ring_t *r, const void *elem)
Producer side.
Definition spsc_ring.c:61
srn_engine_t * engine
Long term state of the compiler.
Definition context.h:49
srn_scheduler_t * scheduler
The fiber scheduler, that is the entry point of the fiber subsystem.
Definition engine.h:78
A channel, the per-worker submission and completion ring pair.
Definition internal.h:30
srn_spsc_ring_t * cq
Definition internal.h:34
void * fiber_data
The fiber_data of the submission this completes.
Definition reactor.h:162
size_t result
The result of the operation on success, bytes transferred for the transfers, the accepted descriptor ...
Definition reactor.h:166
srn_reactor_io_channel_t * channels
One channel per worker, there is a 1to1 mapping between worker ids and channel ids.
Definition internal.h:56
srn_reactor_notify_fn notify
Wakes the worker that owns a channel a completion landed on.
Definition internal.h:52
srn_context_t * ctx
Definition internal.h:44
#define PANIC_IF(cond, msg)
Definition utils.h:59
Here is the call graph for this function:
Here is the caller graph for this function: