Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
engine.c File Reference
#include "serene/rt/engine.h"
#include "serene/rt/context.h"
#include "serene/rt/fiber.h"
#include "serene/rt/impl/hashmap.h"
#include "serene/rt/mm/interface.h"
#include "serene/rt/reactor.h"
#include "serene/utils.h"
#include <assert.h>
#include <signal.h>
#include <string.h>
#include "third_party/xxhash.h"
Include dependency graph for engine.c:

Go to the source code of this file.

Macros

#define XXH_INLINE_ALL
#define XXH_STATIC_LINKING_ONLY
#define XXH_ENABLE_AUTOVECTORIZE
#define XXH_NO_STDLIB
#define XXH_NO_XXH3
#define XXH_NO_LONG_LONG
#define XXH_NO_STREAM
#define XXH_IMPLEMENTATION

Functions

static srn_seed_t srn_generate_seed ()
srn_engine_tsrn_engine_make (srn_mm_t *mm, const srn_configuration_t *config)
 Create the engine over mm, copying config (the runtime's knobs) into it.
void srn_engine_shutdown (srn_engine_t *engine)
srn_hash_t srn_hash (const srn_engine_t *engine, const void *data, size_t len)
srn_object_id_t srn_allocate_object_id (srn_engine_t *engine)

Macro Definition Documentation

◆ XXH_ENABLE_AUTOVECTORIZE

#define XXH_ENABLE_AUTOVECTORIZE

Definition at line 42 of file engine.c.

◆ XXH_IMPLEMENTATION

#define XXH_IMPLEMENTATION

Definition at line 49 of file engine.c.

◆ XXH_INLINE_ALL

#define XXH_INLINE_ALL

Definition at line 40 of file engine.c.

◆ XXH_NO_LONG_LONG

#define XXH_NO_LONG_LONG

Definition at line 47 of file engine.c.

◆ XXH_NO_STDLIB

#define XXH_NO_STDLIB

Definition at line 44 of file engine.c.

◆ XXH_NO_STREAM

#define XXH_NO_STREAM

Definition at line 48 of file engine.c.

◆ XXH_NO_XXH3

#define XXH_NO_XXH3

Definition at line 46 of file engine.c.

◆ XXH_STATIC_LINKING_ONLY

#define XXH_STATIC_LINKING_ONLY

Definition at line 41 of file engine.c.

Function Documentation

◆ srn_allocate_object_id()

srn_object_id_t srn_allocate_object_id ( srn_engine_t * engine)

Definition at line 172 of file engine.c.

172 {
173 PANIC_IF_NULL(engine);
174 return atomic_fetch_add_explicit(&engine->object_id_counter, 1, memory_order_relaxed);
175}
_Atomic srn_object_id_t object_id_counter
An unsigned counter to allocate object ids atomically.
Definition engine.h:57
#define PANIC_IF_NULL(ptr)
Definition utils.h:66
Here is the caller graph for this function:

◆ srn_engine_make()

srn_engine_t * srn_engine_make ( srn_mm_t * mm,
const srn_configuration_t * config )

Create the engine over mm, copying config (the runtime's knobs) into it.

Pass nullptr for config to use the defaults. config is read only during the call, so the caller may pass a stack value.

Definition at line 101 of file engine.c.

101 {
102 PANIC_IF_NULL(mm);
104
105 if (engine == nullptr) {
106 return nullptr;
107 }
108
109 // A null `config` means "use the defaults"; otherwise copy the caller's
110 // knobs. Either way the engine owns its copy, so the caller's `config` need
111 // not outlive this call. Validating the copy makes a bad knob fail loudly
112 // here, before anything is sized or bounded by it.
113 engine->config = (config != nullptr) ? *config : SRN_CONFIG_DEFAULTS;
114 srn_config_validate(&engine->config);
115
116 engine->seed = srn_generate_seed();
117 // Just reserving 0..100 for any unpredicted needs
118 engine->mm = mm;
119
120#if !defined(_WIN32)
121 // A fiber writing to a peer that has closed its end would otherwise raise
122 // SIGPIPE and take the whole process down. The reactor's WRITE path uses
123 // write(), which cannot pass MSG_NOSIGNAL, so suppress SIGPIPE process-wide
124 // and let the operation fail with -EPIPE instead. Idempotent across engines.
125 // Something to have a look at:
126 // https://stackoverflow.com/questions/8369506/why-does-sigpipe-exist
127 // Also since we're ignoring sigpipe here permanently, we can safely ignore
128 // the returning previous signal handler by the signal function call
129 UNUSED(signal(SIGPIPE, SIG_IGN));
130#endif
131
132#ifdef SRN_WITH_SERENE
133 engine->jit = srn_jit_make(mm);
134#endif
135 engine->scheduler = srn_sched_init(engine);
136 engine->reactor = srn_reactor_init(engine);
137
138#ifdef SRN_WITH_SERENE
139 // Both registries outlive every user context, so they are pinned to a
140 // context the engine itself owns. Every trie node an insert creates lands
141 // in this context's block chain, which is released only at engine
142 // shutdown.
143 engine->root_context = srn_context_make(engine);
144 engine->namespaces = hmap_empty(engine->root_context);
145 srn_spinlock_init(&engine->ns_lock);
146 engine->keywords = hmap_empty(engine->root_context);
147 srn_spinlock_init(&engine->keywords_lock);
148#endif
149 atomic_init(&engine->object_id_counter, ENGINE_FIRST_OBJECT_ID);
150
151 return engine;
152}
void srn_config_validate(const srn_configuration_t *config)
A configuration with every field set to its default.
#define SRN_CONFIG_DEFAULTS
srn_context_t * srn_context_make(srn_engine_t *engine)
Make an empty context, by allocating a new memory block.
Definition context.c:39
static srn_seed_t srn_generate_seed()
Definition engine.c:65
#define ENGINE_FIRST_OBJECT_ID
Start allocating IDs from 100, earlier IDs are reserved.
Definition engine.h:44
hmap_t hmap_empty(const srn_context_t *ctx)
Create, initialize and return a new hashmap pinned to ctx.
Definition hashmap.c:655
#define srn_mm_immortal_allocate(mm, T)
Definition interface.h:183
srn_jit_t * srn_jit_make(srn_mm_t *mm)
Definition jit.c:43
srn_reactor_t * srn_reactor_init(srn_engine_t *engine)
Allocate the IO reactor from the engine.
Definition reactor.c:34
srn_scheduler_t * srn_sched_init(srn_engine_t *engine)
Definition scheduler.c:257
Engine is a structure to own the long living and main pieces of the compiler.
Definition engine.h:51
srn_configuration_t config
The runtime's tunable knobs, the single source for every configurable value (see configuration....
Definition engine.h:62
srn_scheduler_t * scheduler
The fiber scheduler, that is the entry point of the fiber subsystem.
Definition engine.h:75
srn_seed_t seed
We use the seed for hashing and the value will be generated at random for each new context.
Definition engine.h:86
srn_mm_t * mm
Memory manager.
Definition engine.h:65
srn_reactor_t * reactor
The I/O reactor, that is in charge of handling everything I/O.
Definition engine.h:78
#define UNUSED(x)
Definition utils.h:45
static void srn_spinlock_init(srn_spinlock_t *lock)
Definition utils.h:280
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_engine_shutdown()

void srn_engine_shutdown ( srn_engine_t * engine)

Definition at line 154 of file engine.c.

154 {
155 PANIC_IF_NULL(engine);
156
159
160#ifdef SRN_WITH_SERENE
161 srn_jit_shutdown(engine->jit);
162 srn_context_release(engine->root_context);
163#endif
164}
int srn_context_release(srn_context_t *ctx)
Definition context.c:64
int srn_jit_shutdown(srn_jit_t *jit)
Definition jit.c:74
void srn_reactor_shutdown(srn_reactor_t *reactor)
Tear the reactor down, stop and join the reactor thread and release its channels.
Definition reactor.c:66
void srn_sched_shutdown(srn_scheduler_t *sched)
The one stop tear down of the fiber subsystem, should be called once srn_sched_run has returned.
Definition scheduler.c:327
Here is the call graph for this function:

◆ srn_generate_seed()

srn_seed_t srn_generate_seed ( )
inlinestatic

Definition at line 65 of file engine.c.

65 {
66 // A genuinely random zero is legal output from every source below, so a
67 // zero is retried rather than treated as a failure. Two zeros in a row
68 // from a working source is a 2^-64 event, so a tiny bound suffices.
69 for (int attempt = 0; attempt < 8; attempt++) {
70 srn_seed_t s = 0;
71
72#if defined(__linux__)
73 auto res = getrandom(&s, sizeof(s), 0);
74 if (res < 0) {
75 PANIC("Can't get a random number");
76 }
77#elif defined(__APPLE__)
78 arc4random_buf(&s, sizeof(s));
79#elif defined(_WIN32)
80 NTSTATUS st = BCryptGenRandom(nullptr, (PUCHAR)&s, sizeof(s), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
81 if (st != 0) {
82 PANIC("Couldn't allocate a seed");
83 }
84#else
85 // fallback: /dev/urandom
86 FILE *f = fopen("/dev/urandom", "rb");
88 size_t got = fread(&s, sizeof(s), 1, f);
89 UNUSED(fclose(f));
90 PANIC_IF(got != 1, "Couldn't read a seed from /dev/urandom");
91#endif
92
93 if (s != 0) {
94 return s;
95 }
96 }
97
98 PANIC("Couldn't generate a nonzero seed");
99}
SRN_SEED_TYPE srn_seed_t
Definition context.h:45
#define PANIC_IF(cond, msg)
Definition utils.h:59
#define PANIC(msg)
Definition utils.h:53
Here is the caller graph for this function:

◆ srn_hash()

srn_hash_t srn_hash ( const srn_engine_t * engine,
const void * data,
size_t len )

Definition at line 166 of file engine.c.

166 {
167 // NULL pointers are only valid if the length is zero
168 size_t length = (data == nullptr) ? 0 : len;
169 return XXH32(data, length, engine->seed);
170}
Here is the caller graph for this function: