Skip to content

Commit

Permalink
Add basic preemption support
Browse files Browse the repository at this point in the history
  • Loading branch information
sargun committed Mar 16, 2017
1 parent 9f9c955 commit 9be16a9
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 24 deletions.
24 changes: 22 additions & 2 deletions src/cli/gravity.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,18 @@ static void gravity_repl (void) {

// MARK: -

int x = 0;

static bool should_preempt(void *xdata) {
x++;
if (x % 3 == 0) {
return true;
}
return false;
}

// MARK: -

int main (int argc, const char* argv[]) {
// parse arguments and return operation type
op_type type = parse_args(argc, argv);
Expand Down Expand Up @@ -158,6 +170,7 @@ int main (int argc, const char* argv[]) {

// create VM
gravity_vm *vm = gravity_vm_new(&delegate);
delegate.preempt_callback = &should_preempt;

// check if input file is source code that needs to be compiled
if ((type == OP_COMPILE) || (type == OP_COMPILE_RUN)) {
Expand Down Expand Up @@ -198,8 +211,15 @@ int main (int argc, const char* argv[]) {

// sanity check
assert(closure);

if (gravity_vm_runmain(vm, closure)) {

bool result;
result = gravity_vm_runmain(vm, closure, true);

while (!result && gravity_vm_preempted(vm)) {
result = gravity_vm_run_resume_main(vm, closure, true);
}

if (result) {
gravity_value_t result = gravity_vm_result(vm);
double t = gravity_vm_time(vm);

Expand Down
2 changes: 1 addition & 1 deletion src/cli/unittest.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ static void test_folder (const char *folder_path, test_data *data) {
gravity_compiler_free(compiler);

if (closure) {
if (gravity_vm_runmain(vm, closure)) {
if (gravity_vm_runmain(vm, closure, NULL)) {
data->processed = true;
gravity_value_t result = gravity_vm_result(vm);
if (gravity_value_equals(result, data->expected_value)) {
Expand Down
87 changes: 69 additions & 18 deletions src/runtime/gravity_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// Copyright (c) 2014 CreoLabs. All rights reserved.
//

#include <gravity_delegate.h>
#include "gravity_hash.h"
#include "gravity_array.h"
#include "gravity_debug.h"
Expand All @@ -27,6 +28,15 @@ static void gravity_gc_transform (gravity_hash_t *hashtable, gravity_value_t key
static uint32_t cache_refcount = 0;
static gravity_value_t cache[GRAVITY_VTABLE_SIZE];

struct vm_state {
gravity_fiber_t *fiber;
gravity_delegate_t *delegate;
gravity_callframe_t *frame;
gravity_function_t *func;
gravity_value_t *stackstart;
uint32_t *ip;
};

// Opaque VM struct
struct gravity_vm {
gravity_hash_t *context; // context hash table
Expand Down Expand Up @@ -67,6 +77,7 @@ struct gravity_vm {
#endif

bool preempted; // Set to true if the VM was preempted -- check flag if returns false
struct vm_state vm_state;
};

// MARK: -
Expand Down Expand Up @@ -288,16 +299,36 @@ static bool gravity_vm_exec(gravity_vm *vm, bool preemptable) {
register uint32_t *ip; // IP => instruction pointer
register uint32_t inst; // IR => instruction register
register opcode_t op; // OP => opcode register

// load current callframe
LOAD_FRAME();
DEBUG_CALL("Executing", func);

// sanity check
if ((ip == NULL) || (!func->bytecode) || (func->ninsts == 0)) return true;

DEBUG_STACK();

gravity_preempt_callback preempt_cb = NULL; // Callback to cause preemption



// Set preempt_cb if running in a preemptable context
if (preemptable) {
preempt_cb = vm->delegate->preempt_callback;
}

if (vm->preempted) {
// Restore the VM state
delegate = vm->vm_state.delegate;
fiber = vm->vm_state.fiber;
frame = vm->vm_state.frame;
func = vm->vm_state.func;
ip = vm->vm_state.ip;
stackstart = vm->vm_state.stackstart;
vm->preempted = false;
} else {
// load current callframe
LOAD_FRAME();
DEBUG_CALL("Executing", func);

// sanity check
if ((ip == NULL) || (!func->bytecode) || (func->ninsts == 0)) return true;

DEBUG_STACK();
}


while (1) {
INTERPRET_LOOP {

Expand Down Expand Up @@ -1265,6 +1296,14 @@ static bool gravity_vm_exec(gravity_vm *vm, bool preemptable) {
return true;

PREEMPT:
vm->preempted = true;
vm->vm_state.delegate = delegate;
vm->vm_state.fiber = fiber;
vm->vm_state.frame = frame;
vm->vm_state.func = func;
vm->vm_state.ip = ip;
vm->vm_state.stackstart = stackstart;

return false;
}

Expand Down Expand Up @@ -1502,7 +1541,7 @@ bool gravity_vm_runclosure (gravity_vm *vm, gravity_closure_t *closure, gravity_
return result;
}

bool gravity_vm_runmain (gravity_vm *vm, gravity_closure_t *closure) {
bool gravity_vm_runmain(gravity_vm *vm, gravity_closure_t *closure, bool preemptable) {
// first load closure into vm
if (closure) gravity_vm_loadclosure(vm, closure);

Expand All @@ -1519,15 +1558,23 @@ bool gravity_vm_runmain (gravity_vm *vm, gravity_closure_t *closure) {

// execute main function
RESET_STATS(vm);
nanotime_t tstart = nanotime();
bool result = gravity_vm_exec(vm, false);
nanotime_t tend = nanotime();
vm->time = millitime(tstart, tend);

PRINT_STATS(vm);
return result;

return gravity_vm_run_resume_main(vm, closure, preemptable);
}

bool gravity_vm_run_resume_main(gravity_vm *vm, gravity_closure_t *closure, bool preemptable) {
nanotime_t tstart = nanotime();
bool result = gravity_vm_exec(vm, preemptable);
nanotime_t tend = nanotime();
vm->time += millitime(tstart, tend);

if (!gravity_vm_preempted(vm))
PRINT_STATS(vm);

return result;
}


// MARK: - User -

void gravity_vm_setslot (gravity_vm *vm, gravity_value_t value, uint32_t index) {
Expand Down Expand Up @@ -2064,3 +2111,7 @@ void gravity_gc_push (gravity_vm *vm, gravity_object_t *obj) {
void gravity_gc_pop (gravity_vm *vm) {
marray_pop(vm->gcsave);
}

bool gravity_vm_preempted (gravity_vm *vm) {
return vm->preempted;
}
4 changes: 3 additions & 1 deletion src/runtime/gravity_vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ void gravity_vm_set_callbacks (gravity_vm *vm, vm_transfer_cb vm_transfer, vm
void gravity_vm_free (gravity_vm *vm);
void gravity_vm_reset (gravity_vm *vm);
bool gravity_vm_runclosure (gravity_vm *vm, gravity_closure_t *closure, gravity_value_t selfvalue, gravity_value_t params[], uint16_t nparams);
bool gravity_vm_runmain (gravity_vm *vm, gravity_closure_t *closure);

bool gravity_vm_runmain(gravity_vm *vm, gravity_closure_t *closure, bool preemptable);
bool gravity_vm_run_resume_main(gravity_vm *vm, gravity_closure_t *closure, bool preemptable);
void gravity_vm_loadclosure (gravity_vm *vm, gravity_closure_t *closure);
void gravity_vm_setvalue (gravity_vm *vm, const char *key, gravity_value_t value);
gravity_value_t gravity_vm_lookup (gravity_vm *vm, gravity_value_t key);
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/gravity_vmmacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
#define GRAVITY_GC_STRESSTEST 0
#define GRAVITY_GC_DEBUG 0
#define GRAVITY_STACK_DEBUG 0
#define GRAVITY_VM_PREEMPTION 0
#define GRAVITY_VM_PREEMPTION 1

#if GRAVITY_STACK_DEBUG
#define DEBUG_STACK() gravity_stack_dump(fiber)
Expand Down Expand Up @@ -117,7 +117,7 @@
#define FN_COUNTREG(_f,_nargs) (MAXNUM(_f->nparams,_nargs) + _f->nlocals + _f->ntemps)

#if GRAVITY_VM_PREEMPTION
#define SHOULD_PREEMPT
#define SHOULD_PREEMPT if (preempt_cb && preempt_cb(vm->delegate->xdata)) goto PREEMPT;
#else
#define SHOULD_PREEMPT
#endif
Expand Down

0 comments on commit 9be16a9

Please sign in to comment.