#include #include /* 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);