make tracy work for multilpe contexts
Some checks failed
Build and Deploy / build-windows (CLANG64) (push) Has been cancelled
Build and Deploy / package-dist (push) Has been cancelled
Build and Deploy / deploy-itch (push) Has been cancelled
Build and Deploy / deploy-gitea (push) Has been cancelled
Build and Deploy / build-linux (push) Has been cancelled

This commit is contained in:
2025-03-15 20:49:53 -05:00
parent d90d81d7ff
commit 813cc8dbbc
6 changed files with 184 additions and 66 deletions

View File

@@ -22,6 +22,13 @@ prosperon.dispatch = function(type, data) {
}
var os = use_embed('os')
var tracy = use_embed('tracy')
os.trace = true;
if (os.trace)
tracy.level(1);
var js = use_embed('js')
prosperon.on('exit', _ => {
@@ -58,7 +65,7 @@ Object.defineProperty(Function.prototype, "hashify", {
})
var io = use_embed('io')
var tracy = use_embed('tracy')
var RESPATH = 'scripts/modules/resources.js'
var canonical = io.realdir(RESPATH) + 'resources.js'
@@ -285,27 +292,27 @@ var time = use('time')
function parse_file(content, file) {
if (!content) return {}
var parts = content.split(/\n\s*---\s*\n/)
if (parts.length === 1) {
var part = parts[0]
if (!/^\s*---\s*$/m.test(content)) {
var part = content.trim()
if (part.match(/return\s+[^;]+;?\s*$/))
return { module: part }
return { program: part }
}
var parts = content.split(/\n\s*---\s*\n/)
var module = parts[0]
if (!/\breturn\b/.test(module))
throw new Error(`Malformed file: ${file}. Module section must end with a return statement.`);
throw new Error(`Malformed file: ${file}. Module section must end with a return statement.`)
try {
new Function(module)()
} catch (e) {
throw new Error(`Malformed file: ${file}. Module section must end with a return statement.\n` + e.message);
throw new Error(`Malformed file: ${file}. Module section must end with a return statement.\n` + e.message)
}
var pad = '\n'.repeat(module.split('\n').length+4)
var pad = '\n'.repeat(module.split('\n').length + 4)
return {
module,
program: pad+parts[1]
program: pad + parts[1]
}
}
@@ -755,8 +762,8 @@ var timers = []
var timer_id = 0
$_.delay = function(fn, seconds) {
timers[timer_id++] = {seconds, fn}
return function() { delete timers[timer_id] }
var id = os.os.addtimer(prosperon.id, fn, seconds);
return function() { os.removetimer(id); }
}
$_.delay[prosperon.DOC] = "used to schedule the invocation of a function..."
@@ -836,6 +843,8 @@ cmd.process(prosperon.argv)
if (!prosperon.args.id) prosperon.id = util.guid()
else prosperon.id = prosperon.args.id
tracy.thread_name(prosperon.id)
$_.__ACTORDATA__.id = prosperon.id
if (prosperon.args.overling) overling = { __ACTORDATA__: {id: prosperon.args.overling} }
@@ -923,14 +932,14 @@ function handle_message(msg) {
unneeded_timer = $_.delay(unneeded_fn, unneeded_time)
}
var hang = 0.01
var hang = 0.1
var last_t = os.now()
var doexit = false
while (!doexit) {
if (portal) portal.service(handle_host, hang)
if (contactor) contactor.service(handle_host, hang)
os.mailbox_service(prosperon.id, handle_local)
os.mailbox_service(prosperon.id, handle_local, hang)
var elapsed = os.now() - last_t
last_t = os.now()
for (var i in timers) {

View File

@@ -70,6 +70,7 @@ typedef struct rtree rtree;
int randombytes(void *buf, size_t n);
static Uint32 timer_cb_event;
static int trace = 0;
#ifdef __APPLE__
#include <Accelerate/Accelerate.h>
@@ -7093,37 +7094,50 @@ typedef struct {
int create_new_runtime(cmdargs *data)
{
script_startup(data->argc, data->argv);
printf("THREAD IS STOPPING\n");
for (int i = 0; i < data->argc; i++) free(data->argv[i]);
free(data->argv);
free(data);
return 0;
}
JSC_CCALL(os_createthread,
cmdargs cmd;
cmd.argc = JS_ArrayLength(js,argv[0]);
cmd.argv = (char **)calloc(cmd.argc, sizeof(char *));
// Convert JS array elements to C strings
for (int i = 0; i < cmd.argc; i++) {
JSValue val = JS_GetPropertyUint32(js, argv[0], i);
if (JS_IsException(val)) {
free(cmd.argv);
return val;
}
const char *str = JS_ToCString(js, val);
if (!str) {
free(cmd.argv);
JS_FreeValue(js, val);
return JS_ThrowInternalError(js, "Could not convert argument to string");
}
cmd.argv[i] = strdup(str); // Make a copy of the string
JS_FreeCString(js, str);
JS_FreeValue(js, val);
cmdargs *cmd = malloc(sizeof(cmdargs));
if (!cmd) return JS_ThrowInternalError(js, "Out of memory");
cmd->argc = JS_ArrayLength(js, argv[0]);
cmd->argv = (char **)calloc(cmd->argc, sizeof(char *));
if (!cmd->argv) {
free(cmd);
return JS_ThrowInternalError(js, "Out of memory");
}
for (int i = 0; i < cmd->argc; i++) {
JSValue val = JS_GetPropertyUint32(js, argv[0], i);
if (JS_IsException(val)) {
for (int j = 0; j < i; j++) free(cmd->argv[j]);
free(cmd->argv);
free(cmd);
return val;
}
const char *str = JS_ToCString(js, val);
if (!str) {
for (int j = 0; j < i; j++) free(cmd->argv[j]);
free(cmd->argv);
free(cmd);
JS_FreeValue(js, val);
return JS_ThrowInternalError(js, "Could not convert argument to string");
}
cmd->argv[i] = strdup(str);
JS_FreeCString(js, str);
JS_FreeValue(js, val);
}
SDL_Thread *thread = SDL_CreateThread(create_new_runtime, "newrt", cmd);
if (!thread) {
for (int i = 0; i < cmd->argc; i++) free(cmd->argv[i]);
free(cmd->argv);
free(cmd);
return JS_ThrowInternalError(js, "Could not create a new thread: %s", SDL_GetError());
}
SDL_Thread *thread = SDL_CreateThread(create_new_runtime, "newrt", &cmd);
if (!thread) return JS_ThrowInternalError(js, "Could not create a new thread: %s", SDL_GetError());
SDL_DetachThread(thread);
return JS_UNDEFINED;
)
struct message {
@@ -7133,6 +7147,7 @@ struct message {
typedef struct mailbox {
SDL_Mutex *mutex;
SDL_Condition *cond;
struct message *messages;
} mailbox;
@@ -7141,29 +7156,28 @@ static SDL_Mutex *mailboxes_mutex = NULL;
JSC_CCALL(os_mailbox_push,
if (argc < 2) return JS_ThrowInternalError(js, "Need an actor and a message");
if (!JS_IsArrayBuffer(js, argv[1])) return JS_ThrowInternalError(js, "Object to push into the mailbox must be an array buffer.");
if (!JS_IsArrayBuffer(js, argv[1])) return JS_ThrowInternalError(js, "Object to push must be an array buffer");
const char *id = JS_ToCString(js, argv[0]);
int mailbox_index = shgeti(mailboxes, id);
JS_FreeCString(js, id);
if (mailbox_index == -1)
return JS_ThrowInternalError(js, "No mailbox found for given ID");
if (mailbox_index == -1) return JS_ThrowInternalError(js, "No mailbox found for given ID");
size_t size;
uint8_t *buf = JS_GetArrayBuffer(js, &size, argv[1]);
if (!buf) return JS_ThrowInternalError(js, "Could not get data from arraybuffer.");
if (!buf) return JS_ThrowInternalError(js, "Could not get data from arraybuffer");
void *data = js_malloc_rt(JS_GetRuntime(js), size);
if (!data) return JS_ThrowInternalError(js, "Memory allocation failed.");
if (!data) return JS_ThrowInternalError(js, "Memory allocation failed");
memcpy(data,buf,size);
memcpy(data, buf, size);
mailbox *mb = &mailboxes[mailbox_index].value;
SDL_LockMutex(mb->mutex);
struct message msg = {data, size};
arrput(mb->messages, msg);
SDL_SignalCondition(mb->cond); // Signal waiting threads
SDL_UnlockMutex(mb->mutex);
)
@@ -7174,6 +7188,7 @@ void js_dofree(JSRuntime *rt, void *opaque, void *ptr)
JSC_CCALL(os_mailbox_service,
if (!JS_IsFunction(js, argv[1])) return JS_ThrowInternalError(js, "Arg 2 must be a function");
if (argc < 3 || !JS_IsNumber(argv[2])) return JS_ThrowInternalError(js, "Arg 3 must be a number (timeout in seconds)");
const char *id = JS_ToCString(js, argv[0]);
int mb_index = shgeti(mailboxes, id);
@@ -7181,9 +7196,25 @@ JSC_CCALL(os_mailbox_service,
if (mb_index == -1) return JS_ThrowInternalError(js, "No mailbox found for given ID");
// Get timeout in seconds and convert to milliseconds
int32_t timeout_seconds;
if (JS_ToInt32(js, &timeout_seconds, argv[2]) != 0) return JS_ThrowInternalError(js, "Invalid timeout value");
int timeout_ms = timeout_seconds * 1000; // Convert to milliseconds for SDL
mailbox *mb = &mailboxes[mb_index].value;
struct message *temp = NULL;
SDL_LockMutex(mb->mutex);
// Wait for messages if the mailbox is empty
while (arrlen(mb->messages) == 0) {
bool signaled = SDL_WaitConditionTimeout(mb->cond, mb->mutex, timeout_ms);
if (!signaled) { // Timeout occurred
SDL_UnlockMutex(mb->mutex);
return JS_UNDEFINED;
}
}
// Process messages after wait
int count = arrlen(mb->messages);
if (count > 0) {
arrsetlen(temp, count);
@@ -7200,7 +7231,7 @@ JSC_CCALL(os_mailbox_service,
JSValue arg = JS_NewArrayBuffer(js, temp[i].data, temp[i].size, js_dofree, NULL, 0);
JSValue call = JS_Call(js, fn, JS_UNDEFINED, 1, &arg);
uncaught_exception(js, call);
JS_FreeValue(js,arg);
JS_FreeValue(js, arg);
}
arrfree(temp);
@@ -7218,6 +7249,7 @@ JSC_CCALL(os_mailbox_start,
const char *id = JS_ToCString(js, argv[0]);
mailbox mb;
mb.mutex = SDL_CreateMutex();
mb.cond = SDL_CreateCondition();
mb.messages = NULL;
if (!mailboxes_mutex) mailboxes_mutex = SDL_CreateMutex();
@@ -7245,6 +7277,7 @@ JSC_CCALL(os_mailbox_destroy,
SDL_UnlockMutex(mb->mutex);
SDL_DestroyMutex(mb->mutex);
SDL_DestroyCondition(mb->cond);
SDL_LockMutex(mailboxes_mutex);
shdel(mailboxes, id);
@@ -7273,16 +7306,68 @@ JSC_CCALL(os_waitevent,
return JS_UNDEFINED;
)
JSValue js_os_get_trace(JSContext *js, JSValue self)
{
return JS_NewBool(js, trace);
}
JSValue js_os_set_trace(JSContext *js, JSValue self, JSValue value)
{
trace = JS_ToBool(js, value);
return JS_UNDEFINED;
}
typedef struct {
char *timer_id; // Unique timer identifier
char *mailbox_id; // Mailbox to send the message to
} timer_data;
typedef struct {
char *timer_id; // Timer ID
JSValue fn; // Function to invoke
} timer_mapping;
static timer_mapping *timers = NULL; // Dynamic array of timer mappings
static SDL_Mutex *timers_mutex = NULL; // Mutex for thread-safe access to timers
void init_timers(void)
{
if (!timers_mutex) timers_mutex = SDL_CreateMutex();
}
typedef struct {
JSValue fn;
const char *id;
} timer_cb;
JSC_CCALL(os_addtimer,
Uint64 ns = js2number(js,argv[1])*1000000000.0;
timer_cb cb;
cb.fn = JS_DupValue(js,argv[0]);
cb.id = JS_ToCString(js,argv[2]);
)
JSC_CCALL(os_removetimer,
)
static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, make_transform, 0),
MIST_FUNC_DEF(os, clean_transforms, 0),
MIST_FUNC_DEF(os, addtimer, 3),
MIST_FUNC_DEF(os, removetimer, 1),
MIST_FUNC_DEF(os, platform, 0),
MIST_FUNC_DEF(os, arch, 0),
MIST_FUNC_DEF(os, totalmem, 0),
MIST_FUNC_DEF(os, freemem, 0),
MIST_FUNC_DEF(os, hostname, 0),
MIST_FUNC_DEF(os, version, 0),
JS_CGETSET_DEF("trace", js_os_get_trace, js_os_set_trace),
MIST_FUNC_DEF(os, kill, 1),
MIST_FUNC_DEF(os, exit, 1),
@@ -8005,8 +8090,6 @@ void ffi_load(JSContext *js, int argc, char **argv) {
QJSCLASSPREP_FUNCS(datastream);
QJSCLASSPREP_FUNCS(timer);
timer_cb_event = SDL_RegisterEvents(1);
JS_SetPropertyStr(js, globalThis, "use_dyn", JS_NewCFunction(js,js_os_use_dyn,"use_dyn", 1));

View File

@@ -109,6 +109,5 @@ int main(int argc, char **argv) {
}
script_startup(argc, argv); // runs engine.js
printf("MADE IT HERE AT BOTTOM OF MAIN\n");
return 0;
}

View File

@@ -496,26 +496,57 @@ static JSValue js_tracy_image(JSContext *js, JSValue self, int argc, JSValue *ar
#endif
static TracyCZoneCtx *tracy_stack;
// Wrapper struct to keep the array pointer stable
typedef struct {
TracyCZoneCtx *arr; // stb_ds dynamic array
} tracy_stack_t;
// Global TLS ID for the Tracy stack
static SDL_TLSID tracy_stack_id = {0};
// Cleanup function for the wrapper struct
static void tracy_cleanup_stack(void *value)
{
tracy_stack_t *stack = value;
if (stack) {
arrfree(stack->arr);
free(stack);
}
}
// Get or initialize the thread-local Tracy stack
static tracy_stack_t *get_tracy_stack(void)
{
tracy_stack_t *stack = SDL_GetTLS(&tracy_stack_id);
if (!stack) {
stack = malloc(sizeof(tracy_stack_t));
stack->arr = NULL; // stb_ds starts with NULL
arrsetcap(stack->arr, 5); // Initial capacity
SDL_SetTLS(&tracy_stack_id, stack, tracy_cleanup_stack);
}
return stack;
}
void tracy_call_hook(JSContext *js, JSValue fn)
{
tracy_stack_t *stack = get_tracy_stack();
js_debug debug;
js_debug_info(js,fn,&debug);
js_debug_info(js, fn, &debug);
uint64_t srcloc;
srcloc = ___tracy_alloc_srcloc(debug.line, debug.source, debug.srclen, debug.name, strlen(debug.name), (int)debug.source);
uint64_t srcloc = ___tracy_alloc_srcloc(debug.line, debug.filename, strlen(debug.filename), debug.name, strlen(debug.name), debug.unique);
arrput(stack->arr, ___tracy_emit_zone_begin_alloc(srcloc, 1));
arrput(tracy_stack, ___tracy_emit_zone_begin_alloc(srcloc,1));
free_js_debug_info(js, &debug);
}
void tracy_end_hook(JSContext *js, JSValue fn)
{
if (arrlen(tracy_stack) >0)
___tracy_emit_zone_end(arrpop(tracy_stack));
tracy_stack_t *stack = get_tracy_stack();
if (arrlen(stack->arr) > 0)
___tracy_emit_zone_end(arrpop(stack->arr));
}
JSValue js_tracy_level(JSContext *js, JSValue selff, int argc, JSValue *argv)
JSValue js_tracy_level(JSContext *js, JSValue self, int argc, JSValue *argv)
{
int32_t level;
JS_ToInt32(js,&level, argv[0]);

View File

@@ -188,7 +188,6 @@ void script_stop(JSContext *js)
free(prt);
printf("STOPPING CONTEXT %p\n", js);
JSValue *onexp = SDL_GetTLS(&on_exception);
JS_FreeValue(js,*onexp);
JSRuntime *rt = JS_GetRuntime(js);

View File

@@ -1,7 +1,5 @@
var os = use('os')
$_.stop()
$_.start(e => {
switch(e.type) {
case "actor_started":
@@ -13,6 +11,5 @@ $_.start(e => {
$_.couple(e.actor)
$_.stop(e.actor)
$_.stop()
}
}, "tests/underling.js");