119 lines
3.8 KiB
C
119 lines
3.8 KiB
C
|
|
#include <pthread.h>
|
|
#include <stdatomic.h>
|
|
|
|
/* Internal runtime accessors — not in public cell.h API */
|
|
void *JS_GetContextOpaque (JSContext *ctx);
|
|
void JS_SetContextOpaque (JSContext *ctx, void *opaque);
|
|
void JS_SetPauseFlag(JSContext *ctx, int value);
|
|
JSValue JS_GetStack (JSContext *ctx);
|
|
|
|
/* Letter type for unified message queue */
|
|
typedef enum {
|
|
LETTER_BLOB, /* Blob message */
|
|
LETTER_CALLBACK /* JSValue callback function */
|
|
} letter_type;
|
|
|
|
typedef struct letter {
|
|
letter_type type;
|
|
union {
|
|
blob *blob_data; /* For LETTER_BLOB */
|
|
JSValue callback; /* For LETTER_CALLBACK */
|
|
};
|
|
} letter;
|
|
|
|
#define ACTOR_IDLE 0 // Actor not doing anything
|
|
#define ACTOR_READY 1 // Actor ready for a turn
|
|
#define ACTOR_RUNNING 2 // Actor taking a turn
|
|
#define ACTOR_EXHAUSTED 3 // Actor waiting for GC
|
|
#define ACTOR_RECLAIMING 4 // Actor running GC
|
|
#define ACTOR_SLOW 5 // Actor going slowly; deprioritize
|
|
#define ACTOR_REFRESHED 6 // GC finished, ready to resume
|
|
|
|
// #define ACTOR_TRACE
|
|
|
|
#define ACTOR_FAST_TIMER_NS (10ULL * 1000000) // 10ms per turn
|
|
#define ACTOR_SLOW_TIMER_NS (60000ULL * 1000000) // 60s for slow actors
|
|
#define ACTOR_SLOW_STRIKES_MAX 3 // consecutive slow turns -> kill
|
|
#define ACTOR_MEMORY_LIMIT (16ULL * 1024 * 1024) // 16MB heap cap
|
|
|
|
typedef struct cell_rt {
|
|
JSContext *context;
|
|
|
|
/* JSValues on the GC heap — each paired with a JSGCRef so the
|
|
Cheney GC can relocate them during compaction. */
|
|
JSGCRef idx_buffer_ref;
|
|
JSGCRef on_exception_ref;
|
|
JSGCRef message_handle_ref;
|
|
JSGCRef unneeded_ref;
|
|
JSGCRef actor_sym_ref;
|
|
|
|
void *init_wota;
|
|
|
|
/* Protects JSContext usage */
|
|
pthread_mutex_t *mutex; /* for everything else */
|
|
pthread_mutex_t *msg_mutex; /* For message queue and timers queue */
|
|
|
|
char *id;
|
|
|
|
int idx_count;
|
|
|
|
/* The "mailbox" for incoming messages + a dedicated lock for it: */
|
|
letter *letters;
|
|
|
|
/* CHANGED FOR EVENTS: a separate lock for the actor->events queue */
|
|
struct { uint32_t key; JSValue value; } *timers;
|
|
|
|
int state;
|
|
uint32_t ar; // timer for unneeded
|
|
double ar_secs; // time for unneeded
|
|
|
|
int disrupt;
|
|
int is_quiescent; // tracked by scheduler for quiescence detection
|
|
int main_thread_only;
|
|
int affinity;
|
|
|
|
uint64_t turn_start_ns; // cell_ns() when turn began
|
|
_Atomic uint32_t turn_gen; // incremented each turn start
|
|
int slow_strikes; // consecutive slow-completed turns
|
|
int vm_suspended; // 1 if VM is paused mid-turn
|
|
|
|
const char *name; // human friendly name
|
|
cell_hook trace_hook;
|
|
} cell_rt;
|
|
|
|
/* Set by actor_turn/CLI before entering the VM, cleared after.
|
|
Read by signal_handler to print JS stack on crash. */
|
|
extern volatile JSContext *g_crash_ctx;
|
|
|
|
cell_rt *create_actor(void *wota);
|
|
const char *register_actor(const char *id, cell_rt *actor, int mainthread, double ar);
|
|
void actor_disrupt(cell_rt *actor);
|
|
|
|
const char *send_message(const char *id, void *msg);
|
|
const char *register_actor(const char *id, cell_rt *actor, int mainthread, double ar);
|
|
void actor_unneeded(cell_rt *actor, JSValue fn, double seconds);
|
|
void script_startup(cell_rt *rt);
|
|
int uncaught_exception(JSContext *js, JSValue v);
|
|
int actor_exists(const char *id);
|
|
|
|
void set_actor_state(cell_rt *actor);
|
|
void enqueue_actor_priority(cell_rt *actor);
|
|
void actor_clock(cell_rt *actor, JSValue fn);
|
|
uint32_t actor_delay(cell_rt *actor, JSValue fn, double seconds);
|
|
JSValue actor_remove_timer(cell_rt *actor, uint32_t timer_id);
|
|
void exit_handler(void);
|
|
void actor_loop();
|
|
void actor_initialize(void);
|
|
void actor_free(cell_rt *actor);
|
|
void actor_gc_scan(JSContext *ctx, uint8_t *fb, uint8_t *fe,
|
|
uint8_t *tb, uint8_t **tf, uint8_t *te);
|
|
int scheduler_actor_count(void);
|
|
void scheduler_enable_quiescence(void);
|
|
|
|
JSValue JS_ResumeRegisterVM(JSContext *ctx);
|
|
|
|
uint64_t cell_ns();
|
|
void cell_sleep(double seconds);
|
|
int randombytes(void *buf, size_t n);
|