static void emonk_outputv(ErlDrvData handle, ErlIOVec *ev) { unsigned char cmd; emonk_drv_t* drv = (emonk_drv_t*) handle; ErlDrvBinary* args = ev->binv[1]; unsigned char* b = args->orig_bytes; int l = args->orig_size; emonk_req_t* req = read_req_info(drv->vm->cx, &cmd, b, l); void* data = NULL; int length; int resp; if(cmd == 0) { data = vm_eval(drv->vm, req, &length); } else { data = vm_call(drv->vm, req, &length); } if(data == NULL) { resp = send_undefined(drv, req); } else { resp = send_response(drv, req, data, length); } if(data != NULL) driver_free(data); if(req != NULL) free_req_info(req); }
static int emonk_control(ErlDrvData handle, uint ignore, char* b, int l, char **rb, int rl) { unsigned char cmd; emonk_drv_t* drv = (emonk_drv_t*) handle; emonk_req_t* req = read_req_info(drv->vm->cx, &cmd, (unsigned char*) b, l); void* data = NULL; int length; int resp; if(req == NULL) { *rb[0] = 0; return 1; } if(cmd == 0) { data = vm_eval(drv->vm, req, &length); } else { data = vm_call(drv->vm, req, &length); } if(data == NULL) { resp = send_undefined(drv, req); } else { resp = send_response(drv, req, data, length); } if(data != NULL) driver_free(data); if(req != NULL) free_req_info(req); if(resp < 0) { *rb[0] = 0; return 1; } return 0; }
void* vm_run(void* arg) { vm_ptr vm = (vm_ptr) arg; JSContext* cx; JSObject* gl; job_ptr job; ENTERM resp; int flags; cx = JS_NewContext(vm->runtime, vm->stack_size); if(cx == NULL) { fprintf(stderr, "Failed to create context.\n"); goto done; } JS_BeginRequest(cx); flags = 0; flags |= JSOPTION_VAROBJFIX; flags |= JSOPTION_STRICT; flags |= JSVERSION_LATEST; flags |= JSOPTION_COMPILE_N_GO; flags |= JSOPTION_XML; JS_SetOptions(cx, JS_GetOptions(cx) | flags); gl = JS_NewObject(cx, &global_class, NULL, NULL); if(gl == NULL) { fprintf(stderr, "Failed to create global object.\n"); goto done; } if(!JS_InitStandardClasses(cx, gl)) { fprintf(stderr, "Failed to initialize classes.\n"); goto done; } if(!install_jserl(cx, gl)) { fprintf(stderr, "Failed to install erlang object."); goto done; } JS_SetErrorReporter(cx, vm_report_error); JS_SetContextPrivate(cx, (void*) vm); JS_EndRequest(cx); while(1) { job = queue_pop(vm->jobs); if(job->type == job_close) { job_destroy(job); break; } JS_BeginRequest(cx); assert(vm->curr_job == NULL && "vm already has a job set."); vm->curr_job = job; if(job->type == job_eval) { resp = vm_eval(cx, gl, job); } else if(job->type == job_call) { resp = vm_call(cx, gl, job); } else { assert(0 && "Invalid job type."); } vm->curr_job = NULL; JS_EndRequest(cx); JS_MaybeGC(cx); // XXX: If pid is not alive, we just ignore it. enif_send(NULL, &(job->pid), job->env, resp); job_destroy(job); } done: JS_BeginRequest(cx); if(cx != NULL) JS_DestroyContext(cx); return NULL; }