aboutsummaryrefslogtreecommitdiff
path: root/src/micro/micro.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/micro/micro.c')
-rw-r--r--src/micro/micro.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/src/micro/micro.c b/src/micro/micro.c
index 39a22b2..9924d5e 100644
--- a/src/micro/micro.c
+++ b/src/micro/micro.c
@@ -647,6 +647,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 +663,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 +689,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;
@@ -714,12 +731,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;