/** * \brief Removes a zombie domain. */ static void cleanup_domain(domainid_t domainid) { errval_t err; struct ps_entry *ps = ps_get(domainid); assert(ps != NULL); // Tell all waiters of exit and free list as we go for(struct ps_waiter *w = ps->waiters; w != NULL;) { debug_printf("informing waiter\n"); err = w->binding->tx_vtbl.wait_response (w->binding, NOP_CONT, ps->exitcode, SYS_ERR_OK); if(err_is_fail(err)) { DEBUG_ERR(err, "wait_response"); } struct ps_waiter *oldw = w; w = w->next; free(oldw); } ps->waiters = NULL; // Cleanup rest of ps entry free(ps->argbuf); ps_remove(domainid); }
static void wait_handler(struct spawn_binding *b, domainid_t domainid, bool nohang) { errval_t err; struct ps_entry *ps = ps_get(domainid); if(ps == NULL) { err = b->tx_vtbl.wait_response(b, NOP_CONT, 0, SPAWN_ERR_DOMAIN_NOTFOUND); if(err_is_fail(err)) { DEBUG_ERR(err, "wait_response"); } } if(!nohang || ps->status == PS_STATUS_ZOMBIE) { // Enqueue the waiter struct ps_waiter *waiter = malloc(sizeof(struct ps_waiter)); assert(waiter != NULL); waiter->next = ps->waiters; waiter->binding = b; ps->waiters = waiter; } else { // nohang and no zombie, return error err = b->tx_vtbl.wait_response(b, NOP_CONT, 0, SPAWN_ERR_DOMAIN_RUNNING); if(err_is_fail(err)) { DEBUG_ERR(err, "wait_response"); } } // Cleanup if zombie (will send the reply) if(ps->status == PS_STATUS_ZOMBIE) { cleanup_domain(domainid); } }
static VALUE rg_get(int argc, VALUE *argv, VALUE self) { VALUE key, type, unit_or_default, result; rb_scan_args(argc, argv, "12", &key, &type, &unit_or_default); if (NIL_P(type) || (RVAL2CBOOL(rb_equal(type, s_string)))) { result = ps_get(self, key); } else if (RVAL2CBOOL(rb_equal(type, s_bool))) { result = rg_get_bool(self, key); } else if (RVAL2CBOOL(rb_equal(type, s_double))) { VALUE double_argv[2]; double_argv[0] = key; double_argv[1] = unit_or_default; result = rg_get_double(2, double_argv, self); } else if (RVAL2CBOOL(rb_equal(type, s_length))) { result = rg_get_length(self, key, unit_or_default); } else if (RVAL2CBOOL(rb_equal(type, s_int))) { VALUE int_argv[2]; int_argv[0] = key; int_argv[1] = unit_or_default; result = rg_get_int(2, int_argv, self); } else { VALUE inspected_type; inspected_type = rb_inspect(type); rb_raise(rb_eArgError, "%s must be nil, :string, :bool, :double, :length or :int", RVAL2CSTR(inspected_type)); } return result; }
static void exit_handler(struct spawn_binding *b, domainid_t domainid, uint8_t exitcode) { errval_t err = kill_domain(domainid, exitcode); struct ps_entry *ps = ps_get(domainid); if(err_is_fail(err)) { DEBUG_ERR(err, "kill_domain"); } if(ps == NULL) { // XXX: Can't do nothing return; } // May never return anything to client }
static errval_t kill_domain(domainid_t domainid, uint8_t exitcode) { struct ps_entry *ps = ps_get(domainid); if(ps == NULL) { return SPAWN_ERR_DOMAIN_NOTFOUND; } ps->status = PS_STATUS_ZOMBIE; ps->exitcode = exitcode; // Garbage collect victim's capabilities cleanup_cap(ps->dcb); // Deschedule dispatcher (do this first!) cleanup_cap(ps->rootcn_cap); if(ps->waiters != NULL) { // Cleanup local data structures and inform waiters cleanup_domain(domainid); } return SYS_ERR_OK; }
static void status_handler(struct spawn_binding *b, domainid_t domainid) { errval_t err; struct ps_entry *ps = ps_get(domainid); spawn_ps_entry_t pse; memset(&pse, 0, sizeof(pse)); if(ps == NULL) { err = b->tx_vtbl.status_response(b, NOP_CONT, pse, NULL, 0, SPAWN_ERR_DOMAIN_NOTFOUND); if(err_is_fail(err)) { DEBUG_ERR(err, "status_response"); } } pse.status = ps->status; err = b->tx_vtbl.status_response(b, NOP_CONT, pse, ps->argbuf, ps->argbytes, SYS_ERR_OK); if(err_is_fail(err)) { DEBUG_ERR(err, "status_response"); } }
void Interactive(HPSCRIPTVM v) { #define MAXINPUT 1024 PSChar buffer[MAXINPUT]; PSInteger blocks =0; PSInteger string=0; PSInteger retval=0; PSInteger done=0; PrintVersionInfos(); ps_pushroottable(v); ps_pushstring(v,_SC("quit"),-1); ps_pushuserpointer(v,&done); ps_newclosure(v,quit,1); ps_setparamscheck(v,1,NULL); ps_newslot(v,-3,PSFalse); ps_pop(v,1); while (!done) { PSInteger i = 0; scprintf(_SC("\nps>")); for(;;) { int c; if(done)return; c = getchar(); if (c == _SC('\n')) { if (i>0 && buffer[i-1] == _SC('\\')) { buffer[i-1] = _SC('\n'); } else if(blocks==0)break; buffer[i++] = _SC('\n'); } else if (c==_SC('}')) {blocks--; buffer[i++] = (PSChar)c;} else if(c==_SC('{') && !string){ blocks++; buffer[i++] = (PSChar)c; } else if(c==_SC('"') || c==_SC('\'')){ string=!string; buffer[i++] = (PSChar)c; } else if (i >= MAXINPUT-1) { scfprintf(stderr, _SC("ps : input line too long\n")); break; } else{ buffer[i++] = (PSChar)c; } } buffer[i] = _SC('\0'); if(buffer[0]==_SC('=')){ scsprintf(ps_getscratchpad(v,MAXINPUT),(size_t)MAXINPUT,_SC("return (%s)"),&buffer[1]); memcpy(buffer,ps_getscratchpad(v,-1),(scstrlen(ps_getscratchpad(v,-1))+1)*sizeof(PSChar)); retval=1; } i=scstrlen(buffer); if(i>0){ PSInteger oldtop=ps_gettop(v); if(PS_SUCCEEDED(ps_compilebuffer(v,buffer,i,_SC("interactive console"),PSTrue))){ ps_pushroottable(v); if(PS_SUCCEEDED(ps_call(v,1,retval,PSTrue)) && retval){ scprintf(_SC("\n")); ps_pushroottable(v); ps_pushstring(v,_SC("print"),-1); ps_get(v,-2); ps_pushroottable(v); ps_push(v,-4); ps_call(v,2,PSFalse,PSTrue); retval=0; scprintf(_SC("\n")); } } ps_settop(v,oldtop); } } }
void ps_removeset(pageset_t ps, pageset_t set) { for (int i = ps_size(set); i--; ) ps_remove(ps, ps_get(set, i)); }