33#define FUN_THREAD_CALL WINAPI 34#define fun_sleep_ms(ms) Sleep((DWORD)(ms)) 40#define FUN_THREAD_CALL 41static inline void fun_sleep_ms(
long ms) {
44 ts.tv_sec =
ms / 1000;
45 ts.tv_nsec = (
ms % 1000) * 1000000L;
50#ifndef FUN_MAX_THREADS 51#define FUN_MAX_THREADS 64 67static CRITICAL_SECTION g_thr_lock;
68static int g_thr_lock_inited = 0;
69static void fun_thr_lock_init(
void) {
70 if (!g_thr_lock_inited) {
71 InitializeCriticalSection(&g_thr_lock);
72 g_thr_lock_inited = 1;
75static void fun_lock(
void) {
76 if (!g_thr_lock_inited) fun_thr_lock_init();
77 EnterCriticalSection(&g_thr_lock);
79static void fun_unlock(
void) {
80 LeaveCriticalSection(&g_thr_lock);
83static pthread_mutex_t g_thr_lock = PTHREAD_MUTEX_INITIALIZER;
84static void fun_lock(
void) {
85 pthread_mutex_lock(&g_thr_lock);
87static void fun_unlock(
void) {
88 pthread_mutex_unlock(&g_thr_lock);
106 VM *tvm = (
VM *)malloc(
sizeof(
VM));
108 fprintf(stderr,
"Runtime error: failed to allocate thread VM\n");
126 for (
int i = 0; i < task->
argc; ++i) {
142 for (
int i = 0; i < task->
argc; ++i) {
152 g_threads[task->
slot].result =
res;
153 g_threads[task->
slot].done = 1;
165static int fun_alloc_thread_slot(
void) {
169 if (!g_threads[i].used) {
170 g_threads[i].used = 1;
171 g_threads[i].done = 0;
181static int fun_thread_spawn(
Value fnVal,
Value argsMaybe,
int hasArgs) {
183 fprintf(stderr,
"Runtime error: thread_spawn expects Function as first argument\n");
197 for (
int i = 0; i <
n; ++i) {
217 int slot = fun_alloc_thread_slot();
219 fprintf(stderr,
"Runtime error: too many threads\n");
221 for (
int i = 0; i < argc; ++i)
229 for (
int i = 0; i < argc; ++i)
233 g_threads[slot].used = 0;
243 HANDLE h = CreateThread(NULL, 0, fun_thread_main, (LPVOID)task, 0, &g_threads[slot].threadId);
245 fprintf(stderr,
"Runtime error: CreateThread failed\n");
246 for (
int i = 0; i < argc; ++i)
251 g_threads[slot].used = 0;
256 g_threads[slot].handle = h;
260 int rc = pthread_create(&
tid, NULL, fun_thread_main, (
void *)task);
262 fprintf(stderr,
"Runtime error: pthread_create failed\n");
263 for (
int i = 0; i < argc; ++i)
268 g_threads[slot].used = 0;
273 g_threads[slot].handle =
tid;
280static Value fun_thread_join(
int tid) {
282 fprintf(stderr,
"Runtime error: thread_join invalid id %d\n",
tid);
289 HANDLE h = g_threads[
idx].handle;
290 int used = g_threads[
idx].used;
293 WaitForSingleObject(h, INFINITE);
297 pthread_t h = g_threads[
idx].handle;
298 int used = g_threads[
idx].used;
301 pthread_join(h, NULL);
309 g_threads[
idx].used = 0;
310 g_threads[
idx].done = 0;
312 g_threads[
idx].threadId = 0;
Bytecode * bytecode_new(void)
Allocate and initialize an empty Bytecode object.
int bytecode_add_instruction(Bytecode *bc, OpCode op, int32_t operand)
Append a single instruction to the instruction stream.
void bytecode_free(Bytecode *bc)
Free a Bytecode and all memory it owns.
int bytecode_add_constant(Bytecode *bc, Value v)
Append a constant to a Bytecode's constant table.
fun_thread_handle_t handle
The Fun virtual machine state.
Tagged union representing a Fun value.
pthread_t fun_thread_handle_t
Value make_nil(void)
Construct a nil Value.
int array_length(const Value *v)
Get the element count of an array Value.
Value make_function(struct Bytecode *fn)
Construct a function Value referencing bytecode.
Value deep_copy_value(const Value *v)
Deep copy a Value, recursively copying arrays and maps.
void free_value(Value v)
Free dynamic storage owned by a Value.
int array_get_copy(const Value *v, int index, Value *out)
Copy an array element into out.
void vm_init(VM *vm)
Initialize a VM instance to its default state.
void vm_reset(VM *vm)
Reset the VM to a clean state.
void vm_run(VM *vm, Bytecode *entry)
Execute the provided entry bytecode in the VM. Pushes an initial frame and runs until HALT or an unre...