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/fiber/mutex.h"
#include "serene/rt/impl/hashmap.h"
#include "serene/rt/mm/interface.h"
#include "serene/rt/reactor.h"
#include "serene/rt/source_manager.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_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.
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 44 of file engine.c.

◆ XXH_IMPLEMENTATION

#define XXH_IMPLEMENTATION

Definition at line 51 of file engine.c.

◆ XXH_INLINE_ALL

#define XXH_INLINE_ALL

Definition at line 42 of file engine.c.

◆ XXH_NO_LONG_LONG

#define XXH_NO_LONG_LONG

Definition at line 49 of file engine.c.

◆ XXH_NO_STDLIB

#define XXH_NO_STDLIB

Definition at line 46 of file engine.c.

◆ XXH_NO_STREAM

#define XXH_NO_STREAM

Definition at line 50 of file engine.c.

◆ XXH_NO_XXH3

#define XXH_NO_XXH3

Definition at line 48 of file engine.c.

◆ XXH_STATIC_LINKING_ONLY

#define XXH_STATIC_LINKING_ONLY

Definition at line 43 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 193 of file engine.c.

193 {
194 PANIC_IF_NULL(engine);
195 return atomic_fetch_add_explicit(&engine->object_id_counter, 1, memory_order_relaxed);
196}
_Atomic srn_object_id_t object_id_counter
An unsigned counter to allocate object ids atomically.
Definition engine.h:60
#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 103 of file engine.c.

103 {
104 PANIC_IF_NULL(mm);
106
107 if (engine == nullptr) {
108 return nullptr;
109 }
110
111 // A null `config` means "use the defaults"; otherwise copy the caller's
112 // knobs. Either way the engine owns its copy, so the caller's `config` need
113 // not outlive this call. Validating the copy makes a bad knob fail loudly
114 // here, before anything is sized or bounded by it.
115 engine->config = (config != nullptr) ? *config : SRN_CONFIG_DEFAULTS;
116 srn_config_validate(&engine->config);
117
118 engine->seed = srn_generate_seed();
119 // Just reserving 0..100 for any unpredicted needs
120 engine->mm = mm;
121
122#if !defined(_WIN32)
123 // A fiber writing to a peer that has closed its end would otherwise raise
124 // SIGPIPE and take the whole process down. The reactor's WRITE path uses
125 // write(), which cannot pass MSG_NOSIGNAL, so suppress SIGPIPE process-wide
126 // and let the operation fail with -EPIPE instead. Idempotent across engines.
127 // Something to have a look at:
128 // https://stackoverflow.com/questions/8369506/why-does-sigpipe-exist
129 // Also since we're ignoring sigpipe here permanently, we can safely ignore
130 // the returning previous signal handler by the signal function call
131 UNUSED(signal(SIGPIPE, SIG_IGN));
132#endif
133
134#ifdef SRN_WITH_SERENE
135 // engine->jit = srn_jit_create(mm, nullptr);
136 // PANIC_IF_NULL(engine->jit);
137#endif
138 engine->scheduler = srn_sched_init(engine);
139 engine->reactor = srn_reactor_init(engine);
140
141#ifdef SRN_WITH_SERENE
142 // Both registries outlive every user context, so they are pinned to a
143 // context the engine itself owns. Every trie node an insert creates lands
144 // in this context's block chain, which is released only at engine
145 // shutdown.
146 engine->root_context = srn_context_make(engine);
147
148 // Each registry head is an immutable, heap allocated map that readers load
149 // atomically without a lock. Writers replace the head under the matching
150 // mutex, so the mutexes live in the same context as the heads. Nothing
151 // else can see the engine yet, so the atomics are initialized instead of stored.
152 hmap_t *namespaces = ALLOC_OR_PANIC(engine->root_context, hmap_t);
153 *namespaces = hmap_empty(engine->root_context);
154 atomic_init(&engine->namespaces, namespaces);
155
156 engine->ns_lock = ALLOC_OR_PANIC(engine->root_context, srn_fiber_mutex_t);
157 srn_fiber_mutex_init(engine->ns_lock);
158
159 hmap_t *keywords = ALLOC_OR_PANIC(engine->root_context, hmap_t);
160 *keywords = hmap_empty(engine->root_context);
161 atomic_init(&engine->keywords, keywords);
162
163 engine->keywords_lock = ALLOC_OR_PANIC(engine->root_context, srn_fiber_mutex_t);
164 srn_fiber_mutex_init(engine->keywords_lock);
165#endif
166 atomic_init(&engine->object_id_counter, ENGINE_FIRST_OBJECT_ID);
167
168 // TODO(lxsameer): Should we create a sub context out of root?
169 engine->source_manager = srn_sm_init(engine->root_context);
170
171 return engine;
172}
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
#define ALLOC_OR_PANIC(ctx, T)
Definition context.h:98
static srn_seed_t srn_generate_seed()
Definition engine.c:67
#define ENGINE_FIRST_OBJECT_ID
Start allocating IDs from 100, earlier IDs are reserved.
Definition engine.h:47
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:188
void srn_fiber_mutex_init(srn_fiber_mutex_t *m)
Initialise m to the unlocked state.
Definition mutex.c:76
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:263
srn_sm_t * srn_sm_init(srn_context_t *ctx)
Initialize the source manager, as an immortal data structure.
Engine is a structure to own the long living and main pieces of the compiler.
Definition engine.h:54
srn_configuration_t config
The runtime's tunable knobs, the single source for every configurable value (see configuration....
Definition engine.h:65
srn_scheduler_t * scheduler
The fiber scheduler, that is the entry point of the fiber subsystem.
Definition engine.h:78
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:89
srn_mm_t * mm
Memory manager.
Definition engine.h:68
srn_reactor_t * reactor
The I/O reactor, that is in charge of handling everything I/O.
Definition engine.h:81
#define UNUSED(x)
Definition utils.h:45
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 174 of file engine.c.

174 {
175 PANIC_IF_NULL(engine);
176
179 srn_sm_shutdown(engine->source_manager);
180
181#ifdef SRN_WITH_SERENE
182 // srn_jit_destroy(engine->jit);
183 srn_context_release(engine->root_context);
184#endif
185}
int srn_context_release(srn_context_t *ctx)
Definition context.c:64
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:333
void srn_sm_shutdown(srn_sm_t *sm)
Shutdown the source manager freeing all the buffers.
Here is the call graph for this function:

◆ srn_generate_seed()

srn_seed_t srn_generate_seed ( )
inlinestatic

Definition at line 67 of file engine.c.

67 {
68 // A genuinely random zero is legal output from every source below, so a
69 // zero is retried rather than treated as a failure. Two zeros in a row
70 // from a working source is a 2^-64 event, so a tiny bound suffices.
71 for (int attempt = 0; attempt < 8; attempt++) {
72 srn_seed_t s = 0;
73
74#if defined(__linux__)
75 auto res = getrandom(&s, sizeof(s), 0);
76 if (res < 0) {
77 PANIC("Can't get a random number");
78 }
79#elif defined(__APPLE__)
80 arc4random_buf(&s, sizeof(s));
81#elif defined(_WIN32)
82 NTSTATUS st = BCryptGenRandom(nullptr, (PUCHAR)&s, sizeof(s), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
83 if (st != 0) {
84 PANIC("Couldn't allocate a seed");
85 }
86#else
87 // fallback: /dev/urandom
88 FILE *f = fopen("/dev/urandom", "rb");
90 size_t got = fread(&s, sizeof(s), 1, f);
91 UNUSED(fclose(f));
92 PANIC_IF(got != 1, "Couldn't read a seed from /dev/urandom");
93#endif
94
95 if (s != 0) {
96 return s;
97 }
98 }
99
100 PANIC("Couldn't generate a nonzero seed");
101}
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 187 of file engine.c.

187 {
188 // NULL pointers are only valid if the length is zero
189 size_t length = (data == nullptr) ? 0 : len;
190 return XXH32(data, length, engine->seed);
191}
XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32(const void *input, size_t length, XXH32_hash_t seed)
Calculates the 32-bit hash of input using xxHash32.
const size_t len
Here is the call graph for this function:
Here is the caller graph for this function: