diff options
Diffstat (limited to 'src/micro/micro.c')
| -rw-r--r-- | src/micro/micro.c | 50 |
1 files changed, 44 insertions, 6 deletions
diff --git a/src/micro/micro.c b/src/micro/micro.c index 23994dd..e095451 100644 --- a/src/micro/micro.c +++ b/src/micro/micro.c @@ -34,6 +34,10 @@ #include "micro_port.h" #include "fops.h" #include "bops.h" +#ifdef ZY_THREADS +#define HOLD_THREADS +#endif +#include "hold.h" #define NENH 512 #define XOP0 22 #define XPOOL 4096 @@ -537,6 +541,11 @@ static int run_from(int p, int s, int r) /* poll: a streaming port suspends once, so its host can deliver input that is waiting */ result = micro_syscall(m, b, 0, 0, 0); if (result == MICRO_WAIT) { sus_p = p - 1; sus_s = s; sus_r = r; return MICRO_SUSPENDED; } + } else if (b == 57) { + result = hold_enter(m, mw, m[a + 1], m[a + 2]); + if (result == -2) { micro_msg("zy: a hold block was entered while a later one was held; hold blocks are entered in the order they are declared\n"); context_call(7, 2, 0, 0, s + 2, r); return 1; } /* a trap: exit status 2 */ + } else if (b == 58) { + result = hold_leave(m, mw, m[a + 1], m[a + 2]); } else result = context_call(b, m[a + 1], m[a + 2], m[a + 3], s + 2, r); m[a] = result; s += 2; @@ -647,6 +656,11 @@ extern size_t micro_context_port_size(void); extern void micro_context_port_save(void *); extern void micro_context_port_restore(const void *); extern void micro_context_port_free(void); +#ifndef _WIN32 +extern Cell *micro_mem_clone(void); +extern void micro_mem_adopt(Cell *mem, UCell words); +extern void micro_mem_release(Cell *mem); +#endif #define CONTEXT_HANDLE_LO 0x40000000 typedef struct ContextChannel { Cell handle; int fd; struct ContextChannel *next; } ContextChannel; typedef struct VmContext { @@ -658,6 +672,7 @@ typedef struct VmContext { UCell words, limit, initial; int sp, rp, exit_code, requested_exit, enhancement_count, input_flag, input_known; Cell *memory; + int memory_mapped; void *port; Xop operations[XPOOL]; Enh enhancements[NENH]; @@ -683,15 +698,26 @@ static int context_close(Cell handle) { } static void context_snapshot_free(VmContext *context) { free(context->port); - if (context->memory) { free(context->memory); atomic_fetch_sub(&context_memory_live, 1); } + if (context->memory) { +#ifndef _WIN32 + if (context->memory_mapped) micro_mem_release(context->memory); else +#endif + free(context->memory); + atomic_fetch_sub(&context_memory_live, 1); + } } static void *context_worker(void *opaque) { VmContext *context = opaque; context_current = context; context->worker_channel.next = context_channels; context_channels = &context->worker_channel; micro_context_port_restore(context->port); free(context->port); context->port = 0; memory_limit = context->limit; memory_initial = context->initial; + if (context->memory_mapped) { +#ifndef _WIN32 + micro_mem_adopt(context->memory, context->words); context->memory = 0; +#endif + } if (!mem_grow_words(context->words)) { context->exit_code = -1; context_close(context->worker_channel.handle); return 0; } - memcpy(m, context->memory, (size_t)context->words * sizeof(Cell)); free(context->memory); context->memory = 0; + if (context->memory) { memcpy(m, context->memory, (size_t)context->words * sizeof(Cell)); free(context->memory); context->memory = 0; } stack_control = context->stack; jflag = context->input_flag; jknown = context->input_known; xuse = context->enhancement_count; memcpy(xops, context->operations, sizeof xops); memcpy(enh, context->enhancements, sizeof enh); int sp = context->sp, rp = context->rp; Cell entry = context->entry; @@ -701,7 +727,7 @@ static void *context_worker(void *opaque) { if (!context->requested_exit) context->exit_code = context_cancelled() ? 0 : result ? -1 : inmem(final_s) ? (int)m[final_s] : 0; context_close(context->worker_channel.handle); while (context_children) context_join(context_children->token, 1); - micro_context_port_free(); m = 0; atomic_fetch_sub(&context_memory_live, 1); context_current = 0; return 0; + hold_release_all(); micro_context_port_free(); m = 0; atomic_fetch_sub(&context_memory_live, 1); context_current = 0; return 0; } static Cell context_start(Cell entry, Cell channel, int sp, int rp) { if (!inmem(entry) || !inmem(channel) || (entry >= HEAP_LO && (!inmem(entry - 3) || m[entry - 3] != (entry ^ 0x2B7E1516)))) return -1; @@ -714,12 +740,17 @@ static Cell context_start(Cell entry, Cell channel, int sp, int rp) { context->parent_channel.handle = CONTEXT_HANDLE_LO + atomic_fetch_add(&context_sequence, 1) + 1; context->worker_channel.handle = CONTEXT_HANDLE_LO + atomic_fetch_add(&context_sequence, 1) + 1; context->parent_channel.fd = fd[0]; context->worker_channel.fd = fd[1]; atomic_init(&context->stop, 0); - context->port = malloc(micro_context_port_size()); context->memory = malloc((size_t)mw * sizeof(Cell)); + context->port = malloc(micro_context_port_size()); +#ifndef _WIN32 + context->memory = micro_mem_clone(); context->memory_mapped = context->memory != 0; + if (!context->memory) +#endif + context->memory = malloc((size_t)mw * sizeof(Cell)); if (context->memory) atomic_fetch_add(&context_memory_live, 1); if (!context->port || !context->memory) goto failed; - micro_context_port_save(context->port); memcpy(context->memory, m, (size_t)mw * sizeof(Cell)); context->memory[channel] = context->worker_channel.handle; + micro_context_port_save(context->port); if (!context->memory_mapped) memcpy(context->memory, m, (size_t)mw * sizeof(Cell)); context->memory[channel] = context->worker_channel.handle; memcpy(context->operations, xops, sizeof xops); memcpy(context->enhancements, enh, sizeof enh); - pthread_attr_t attributes; pthread_attr_init(&attributes); pthread_attr_setstacksize(&attributes, 16u << 20); + pthread_attr_t attributes; pthread_attr_init(&attributes); pthread_attr_setstacksize(&attributes, 4u << 20); /* the vm keeps its own stacks in vm memory; 4 MB of address space covers the deepest native recursion (jit compile, o3) */ int result = pthread_create(&context->thread, &attributes, context_worker, context); pthread_attr_destroy(&attributes); if (result) goto failed; context->parent_channel.next = context_channels; context_channels = &context->parent_channel; @@ -776,6 +807,13 @@ int micro_run(void) micro_msg("zy: genome does not fit\n"); return 1; } +#ifdef MICRO_PORT_IMAGE + /* the port may hand over an image of its own in place of the embedded one + (the wasm bootstrap seed does, to run a freshly built compiler) */ + i = micro_port_image(m, (UCell)GORG, (UCell)FBOT); + if (i < 0) { micro_msg("zy: bad image\n"); return 1; } + if (i == 0) +#endif for (i = 0; i < GLEN; i++) m[GORG + i] = genome_word(i); jknown = 0; return run(GORG); |
