static bool pbind_vars(obj* vars, obj lt){ obj utype; switch(lt->type){ default: break; case tSymbol: if(vars) add_assoc(vars, lt, nil); return true; case tRef: assert(0); let(&(uref(lt)), nil); return true; case INT: assert(0); // return equal(lt,rt); case tOp: utype = search_assoc(curr_interp->types, ult(lt)); if(utype){ return pbind_vars(vars, urt(lt)); } pbind_vars(vars, ult(lt)); return pbind_vars(vars, urt(lt)); case LIST: list x=ul(lt); for(; (x); x=rest(x)){ pbind_vars(vars, first(x)); } return true; } print(lt); assert(0); return nil; }
extern "C" struct hostent *gethostbyname_r(const char *name, struct hostent *result, char *buffer, int buflen, int *h_errnop) { if (!eminfo || eminfo->currently_detached()) { if (!shim_gethostbyname_r) { shim_gethostbyname_r = (gethostbyname_rFnType) dlsym (RTLD_NEXT, "gethostbyname_r"); } return ((shim_gethostbyname_r)(name, result, buffer, buflen, h_errnop)); } struct hostent *retval; int mgr_awake = eminfo->wake_another_thread(); oflux::WaitingToRunRAII wtr_raii(eminfo->thread()); SHIM_CALL("gethostbyname_r"); { oflux::UnlockRunTime urt(eminfo); retval = ((shim_gethostbyname_r)(name, result, buffer, buflen, h_errnop)); } SHIM_WAIT("gethostbyname_r"); if (mgr_awake == 0) { wtr_raii.state_wtr(); eminfo->wait_to_run(); } SHIM_RETURN("gethostbyname_r"); return retval; }
obj pop(obj* v){ obj lt = retain(ult(*v)); obj rt = retain(urt(*v)); release(*v); *v = rt; return lt; }
extern "C" int port_getn(int port, port_event_t list[], uint_t max, uint_t * nget, const timespec_t * timeout) { if (!eminfo || eminfo->currently_detached()) { if (!shim_port_getn) { shim_port_getn = (port_getnFnType) dlsym (RTLD_NEXT, "port_getn"); } return ((shim_port_getn)(port, list, max, nget, timeout)); } if(0 == max) { // if it won't block return ((shim_port_getn)(port, list, max, nget, timeout)); } int ret; int mgr_awake = eminfo->wake_another_thread(); oflux::WaitingToRunRAII wtr_raii(eminfo->thread()); SHIM_CALL("port_getn"); { oflux::UnlockRunTime urt(eminfo); ret = ((shim_port_getn)(port, list, max, nget, timeout)); } SHIM_WAIT("port_getn"); if (mgr_awake == 0) { wtr_raii.state_wtr(); eminfo->wait_to_run(); } SHIM_RETURN("port_getn"); return ret; }
extern "C" ssize_t send(int s, const void * msg, size_t len, int flags) { if (!eminfo || eminfo->currently_detached()) { if (!shim_send) { shim_send = (sendFnType) dlsym (RTLD_NEXT, "send"); } return ((shim_send)(s, msg, len, flags)); } struct pollfd pfd; pfd.fd = s; pfd.events = POLLOUT; ((shim_poll)(&pfd, 1, 0)); if (pfd.revents & POLLOUT) { // if it won't block return ((shim_send)(s, msg, len, flags)); } ssize_t ret; int mgr_awake = eminfo->wake_another_thread(); oflux::WaitingToRunRAII wtr_raii(eminfo->thread()); SHIM_CALL("send"); { oflux::UnlockRunTime urt(eminfo); ret = ((shim_send)(s, msg, len, flags)); } SHIM_WAIT("send"); if (mgr_awake == 0) { wtr_raii.state_wtr(); eminfo->wait_to_run(); } SHIM_RETURN("send"); return ret; }
extern "C" int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout) { if (!eminfo || eminfo->currently_detached()) { if (!shim_epoll_wait) { shim_epoll_wait = (epoll_waitFnType) dlsym (RTLD_NEXT, "epoll_wait"); } return ((shim_epoll_wait)(epfd, events, maxevents, timeout)); } int ret; int mgr_awake = eminfo->wake_another_thread(); oflux::WaitingToRunRAII wtr_raii(eminfo->thread()); SHIM_CALL("epoll_wait"); { oflux::UnlockRunTime urt(eminfo); ret = ((shim_epoll_wait)(epfd, events, maxevents, timeout)); } SHIM_WAIT("epoll_wait"); if (mgr_awake == 0) { wtr_raii.state_wtr(); eminfo->wait_to_run(); } SHIM_RETURN("epoll_wait"); return ret; }
extern "C" ssize_t recv(int s, void * buf, size_t len, int flags) { ssize_t ret; if (!eminfo || eminfo->currently_detached()) { if (!shim_recv) { shim_recv = (recvFnType) dlsym (RTLD_NEXT, "recv"); } return ((shim_recv)(s, buf, len, flags)); } struct pollfd pfd; pfd.fd = s; pfd.events = POLLIN; ((shim_poll)(&pfd, 1, 0)); if (pfd.revents & POLLIN || flags & MSG_DONTWAIT) { // if it won't block return ((shim_recv)(s, buf, len, flags)); } int mgr_awake = eminfo->wake_another_thread(); oflux::WaitingToRunRAII wtr_raii(eminfo->thread()); SHIM_CALL("recv"); { oflux::UnlockRunTime urt(eminfo); ret = ((shim_recv)(s, buf, len, flags)); } SHIM_WAIT("recv"); if (mgr_awake == 0) { wtr_raii.state_wtr(); eminfo->wait_to_run(); } SHIM_RETURN("recv"); return ret; }
extern "C" int poll(struct pollfd *fds, nfds_t nfds, int timeout) { if (!eminfo || eminfo->currently_detached()) { if (!shim_poll) { shim_poll = (pollFnType) dlsym (RTLD_NEXT, "poll"); } return ((shim_poll)(fds,nfds,timeout)); } int res = ((shim_poll)(fds, nfds, 0)); if(res == 0 && timeout != 0) { // timed out when timeout was 0 int mgr_awake = eminfo->wake_another_thread(); oflux::WaitingToRunRAII wtr_raii(eminfo->thread()); SHIM_CALL("poll"); { oflux::UnlockRunTime urt(eminfo); res = ((shim_poll)(fds, nfds, timeout)); } SHIM_WAIT("poll"); if (mgr_awake == 0) { wtr_raii.state_wtr(); eminfo->wait_to_run(); } SHIM_RETURN("poll"); } return res; }
extern "C" int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { if (!eminfo || eminfo->currently_detached()) { if (!shim_select) { shim_select = get_select_fn(); } return ((shim_select)(n, readfds, writefds, exceptfds, timeout)); } int ret; int mgr_awake = eminfo->wake_another_thread(); oflux::WaitingToRunRAII wtr_raii(eminfo->thread()); SHIM_CALL("select"); { oflux::UnlockRunTime urt(eminfo); ret = ((shim_select)(n, readfds, writefds, exceptfds, timeout)); } SHIM_WAIT("select"); if (mgr_awake == 0) { wtr_raii.state_wtr(); eminfo->wait_to_run(); } SHIM_RETURN("select"); return ret; }
extern "C" ssize_t write(int fd, const void *buf, size_t count) { if (!eminfo || eminfo->currently_detached()) { if (!shim_write) { shim_write = (writeFnType) dlsym (RTLD_NEXT, "write"); } return ((shim_write)(fd, buf, count)); } struct pollfd pfd; pfd.fd = fd; pfd.events = POLLOUT; ((shim_poll)(&pfd, 1, 0)); if (pfd.revents & POLLOUT) { // if it won't block return ((shim_write)(fd, buf, count)); } int ret; int mgr_awake = eminfo->wake_another_thread(); oflux::WaitingToRunRAII wtr_raii(eminfo->thread()); SHIM_CALL("write"); { oflux::UnlockRunTime urt(eminfo); ret = ((shim_write)(fd, buf, count)); } SHIM_WAIT("write"); if (mgr_awake == 0) { wtr_raii.state_wtr(); eminfo->wait_to_run(); } SHIM_RETURN("write"); return ret; }
extern "C" int accept(int s, struct sockaddr *addr, socklen_t *addrlen) { if (!eminfo || eminfo->currently_detached()) { if (!shim_accept) { shim_accept = (int (*) (int, struct sockaddr *, socklen_t *)) dlsym(RTLD_NEXT, "accept"); } return ((shim_accept)(s, addr, addrlen)); } struct pollfd pfd; pfd.fd = s; pfd.events = POLLIN; ((shim_poll)(&pfd, 1, 0)); if ((pfd.revents & POLLIN) != 0) return ((shim_accept)(s, addr, addrlen)); int ret; int mgr_awake = eminfo->wake_another_thread(); oflux::WaitingToRunRAII wtr_raii(eminfo->thread()); SHIM_CALL("accept"); { oflux::UnlockRunTime urt(eminfo); ret = ((shim_accept)(s, addr, addrlen)); } SHIM_WAIT("accept"); if (mgr_awake == 0) { wtr_raii.state_wtr(); eminfo->wait_to_run(); } SHIM_RETURN("accept"); return ret; }
extern "C" unsigned int sleep(unsigned int seconds) { if (!eminfo || eminfo->currently_detached()) { if (!shim_sleep) { shim_sleep = (unsigned int (*)(unsigned int)) dlsym(RTLD_NEXT, "sleep"); } return ((shim_sleep)(seconds)); } unsigned int ret; int mgr_awake = eminfo->wake_another_thread(); oflux::WaitingToRunRAII wtr_raii(eminfo->thread()); SHIM_CALL("sleep"); { oflux::UnlockRunTime urt(eminfo); ret = ((shim_sleep)(seconds)); } SHIM_WAIT("sleep"); if(mgr_awake == 0) { wtr_raii.state_wtr(); eminfo->wait_to_run(); } SHIM_RETURN("sleep"); return ret; }
static bool bind_vars(obj* vars, obj lt, obj rt){ obj utype; switch(lt->type){ default: break; case tSymbol: if(macromode){ if(obj rr = search_assoc(car(macro_env), lt)){ //macromode = false; if(vars) add_assoc(vars, rr, rt); //macromode = true; return true; } } if(vars) add_assoc(vars, lt, rt); return true; case tRef: let(&(uref(lt)), rt); return true; case INT: return equal(lt, rt); case tOp: utype = search_assoc(curr_interp->types, ult(lt)); if(utype){ if(vrInt(utype) != rt->type) return false; return bind_vars(vars, urt(lt), uref(rt)); } if(rt->type!=tOp) return false; if(! bind_vars(vars, ult(lt), ult(rt))) return false; return bind_vars(vars, urt(lt), urt(rt)); case LIST: if(rt->type!=LIST) return false; list x=ul(lt), a=ul(rt); for(; (x && a); x=rest(x),a=rest(a)){ if(!bind_vars(vars, first(x), first(a))) return false; } if(x||a) return false; return true; } print(lt); assert(0); return nil; }
static obj do_assign(obj lt, obj rt){ switch(type(lt)) { case tRef: return retain(*let(&(uref(lt)), rt)); case tSymbol: return retain(*let(lfind_var(lt),rt)); default: break; case tInd:{ obj *var; var = lfind_var(ult(lt)); if(!*var) error("the vector does not exist."); if((*var)->refcount > 1){ obj nv = copy(*var); release(*var); *var = nv; myPrintf("performance alert: copy"); } obj inds = eval(urt(lt)); doLInd(var, ul(inds), rt); release(inds); return retain(rt); } case LIST: return applyCC(do_assign, lt, rt); if(type(rt)!=LIST) error("list<-nonlist"); list s = ul(rt); for(list l = ul(lt); l; l=rest(l), s=rest(s)){ if(! s) error("number is not enough for rhs."); do_assign(first(l),first(s)); } if(s) error("too much for rhs."); return nil; } print(lt); assert(0); return nil; }
obj eval(obj exp){ ev: assert(!! exp); obj rr,lt, rt; switch (exp->type) { case tInd: return doInd(eval(ult(exp)), ul(eval(urt(exp)))); case LIST: return List2v(evalList(ul(exp))); case tArray: return map_obj(eval, exp); case tAnd: return prod_eval(ul(exp), mult); case MULT: return prod_eval(ul(exp), mult); case ARITH: return prod_eval(ul(exp), add); case POW: return prod_eval(ul(exp), power); case DIVIDE: return prod_eval(ul(exp), divide); case tRef: return retain(uref(exp)); case tSymbol: if( macromode) { if(obj rr = search_assoc(car(macro_env), exp)){ macromode = false; // macro lexical scope should be pushed to the stack here rr = exec(rr); macromode = true; return rr; } } return eval_symbol(exp); case tMinus: lt = eval(uref(exp)); rr = uMinus(lt); // releasing if(rr) {release(lt); return rr;} static obj symumn = Symbol("-"); rr = udef_op0(symumn, lt); if(rr) {release(lt); return rr;} error("uMinus: not defined to that type"); case tReturn: if(! uref(exp)) return encap(tSigRet, nil); return encap(tSigRet, eval(uref(exp))); case tBreak: return retain(exp); case CONDITION: return evalCond(exp); case tOp: if(type(ult(exp)) ==tSymbol) { lt = search_assoc(curr_interp->types, ult(exp)); if(lt) return encap((ValueType)vrInt(lt), eval(urt(exp)));} lt = eval(ult(exp)); push(lt); switch(lt->type){ case tCont: assert(0); case tSpecial: rr = ufn(lt)(urt(exp)); break; case tSyntaxLam: rr = macro_exec(lt, urt(exp)); break; case tInternalFn: case tClosure: rt = eval(urt(exp)); rr = eval_function(lt, rt); break; default: rt = eval(urt(exp)); rr = call_fn(mult, lt, rt); release(rt); } release(pop(&is)); return rr; case tClosure: assert(0); case tCurry: return eval_curry(exp, em0(exp)); /* obj vars = Assoc(); bind_vars(&vars, em0(exp), em2(exp)); rr = eval_curry(exp, vars); release(vars); return rr; */ case tArrow: // return enclose(exp); /* if(macromode){ if(obj rr = search_assoc(car(macro_env), exp)){ } } */ return render(tClosure, list3(retain(em0(exp)), retain(em1(exp)), retain(env))); case tDefine: return func_def(em0(exp), em1(exp), em2(exp)); case tSyntaxDef: let(lfind_var(em0(exp)), render(tSyntaxLam, list3(retain(em1(exp)), retain(em2(exp)), nil))); return nil; case tExec: return exec(exp); case tAssign: lt = car(exp); if(type(lt)==tOp){ return func_def(ult(lt), urt(lt), cdr(exp)); } else if(type(lt)==tMinus){ static obj symumn = Symbol("-"); return func_def(symumn, uref(lt), cdr(exp)); } else return do_assign(lt, eval(cdr(exp))); case tIf: rr = eval(em0(exp)); if (type(rr) != INT) error("if: Boolean Expected"); if (vrInt(rr)) { rr = em1(exp); } else { rr = em2(exp); } return eval(rr); case tWhile: for(;;) { rr = eval(car(exp)); if (type(rr) != INT) error("while: Boolean expected"); if(!vrInt(rr)) break; rr = exec(cdr(exp)); if(rr && type(rr)==tSigRet) return rr; if(rr && type(rr)==tBreak) {release(rr); break;} if(rr) release(rr); } return nil; default: return retain(exp); } }
extern "C" ssize_t read(int fd, void *buf, size_t count) { ssize_t ret; if (!eminfo || eminfo->currently_detached()) { if (!shim_read) { shim_read = (ssize_t (*)(int, void *, size_t))dlsym (RTLD_NEXT, "read"); } return ((shim_read)(fd, buf, count)); } if (!is_regular[fd]) { struct pollfd pfd; pfd.fd = fd; pfd.events = POLLIN; ((shim_poll)(&pfd, 1, 0)); if (pfd.revents & POLLIN) { // if it won't block return ((shim_read)(fd, buf, count)); } } else { /* Use mmap and mincore to find out if the page is in memory, if YES, then just do the read if NO, then use the thread-pool to fake asynch IO */ off_t off = lseek(fd, 0, SEEK_CUR); void *addr = mmap(0, count, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, off); int len = (count+page_size-1) / page_size; unsigned char *vec = new unsigned char[len]; //int rt = -- unused #ifdef LINUX mincore((char*)addr, count, (unsigned char*)vec); #else mincore((char*)addr, count, (char*)vec); #endif munmap(addr, count); bool in_memory = true; for (int i=0; i< len; i++) { if (vec[i] == 0) { in_memory = false; break; } } delete [] vec; if (in_memory) { return ((shim_read)(fd, buf, count)); } } int mgr_awake = eminfo->wake_another_thread(); oflux::WaitingToRunRAII wtr_raii(eminfo->thread()); SHIM_CALL("read"); { oflux::UnlockRunTime urt(eminfo); ret = ((shim_read)(fd, buf, count)); } SHIM_WAIT("read"); if (mgr_awake == 0) { wtr_raii.state_wtr(); eminfo->wait_to_run(); } SHIM_RETURN("read"); return ret; }