/* * Arguments: [buffer_max_size (number), buffer_min_size (number)] * Returns: [pipe_udata] */ static int pipe_new (lua_State *L) { const unsigned int max_size = (unsigned int) luaL_optinteger(L, 1, PIPE_BUF_MAXSIZE); const unsigned int min_size = (unsigned int) luaL_optinteger(L, 2, PIPE_BUF_MINSIZE); struct pipe_ref *pr; struct pipe *pp; if (min_size > max_size || min_size < PIPE_BUF_MINSIZE || max_size > PIPE_BUF_MAXSIZE /* (max_size / min_size) should be power of 2 */ || ((max_size / min_size) & (max_size / min_size - 1)) != 0) luaL_argerror(L, 1, "invalid size"); pr = lua_newuserdata(L, sizeof(struct pipe_ref)); pp = calloc(sizeof(struct pipe), 1); if (!pp) goto err; pr->pipe = pp; pr->put_timeout = TIMEOUT_INFINITE; luaL_getmetatable(L, PIPE_TYPENAME); lua_setmetatable(L, -2); if (thread_critsect_new(&pp->cs) || thread_cond_new(&pp->put_cond) || thread_cond_new(&pp->get_cond)) goto err; /* allocate initial buffer */ { struct pipe_buf *pb = malloc(min_size); if (!pb) goto err; memset(pb, 0, sizeof(struct pipe_buf)); pb->len = min_size - PIPE_BUF_EXTRASIZE; pb->next_buf = pb; pp->rbuf = pp->wbuf = pb; pp->buf_size = min_size; } pp->buf_max_size = max_size; return 1; err: return sys_seterror(L, 0); }
static int thread_channel (lua_State *L) { struct channel *chan = lua_newuserdata(L, sizeof(struct channel)); memset(chan, 0, sizeof(struct channel)); chan->max = (unsigned int) -1; if (!thread_cond_new(&chan->put) && !thread_cond_new(&chan->get)) { thread_critsect_new(&chan->mutex); luaL_getmetatable(L, CHANNEL_TYPENAME); lua_setmetatable(L, -2); lua_newtable(L); /* data storage */ lua_setfenv(L, -2); return 1; } return sys_seterror(L, 0); }
static struct sys_thread * thread_newvm (lua_State *L, struct sys_thread *reftd, unsigned int loadlibs) { struct sys_vmthread *vmtd; lua_State *NL; if (L) { NL = lua_newthread(L); if (!NL) return NULL; } else { NL = luaL_newstate(); if (!NL) return NULL; L = NL; thread_openlibs(L, loadlibs); thread_createmeta(L); lua_pushthread(L); } vmtd = lua_newuserdata(L, sizeof(struct sys_vmthread)); memset(vmtd, 0, sizeof(struct sys_vmthread)); vmtd->td.L = NL; vmtd->td.vmtd = vmtd; luaL_getmetatable(L, THREAD_TYPENAME); lua_setmetatable(L, -2); if (reftd) { struct sys_vmthread *vmref = reftd->vmtd; vmtd->td.reftd = reftd; vmtd->cpu = vmref->cpu; vmtd->stack_size = vmref->stack_size; } if (thread_critsect_new(&vmtd->vmcs)) return NULL; vmtd->td.vmcsp = &vmtd->vmcs; if (thread_cond_new(&vmtd->td.cond)) return NULL; thread_settable(L, &vmtd->td); /* save thread to avoid GC */ return &vmtd->td; }
/* * Returns: [thread_udata] */ struct sys_thread * sys_thread_new (lua_State *L, struct sys_thread *vmtd, struct sys_thread *vmtd2, const int push_udata) { struct sys_vmthread *vmref = vmtd->vmtd; struct sys_thread *td; lua_State *NL; if (vmtd2) { NL = vmref->td.L; lua_pushnil(L); } else { NL = lua_newthread(L); if (!NL) return NULL; } td = lua_newuserdata(L, sizeof(struct sys_thread)); memset(td, 0, sizeof(struct sys_thread)); td->vmcsp = vmtd->vmcsp; td->L = NL; td->vmtd = vmref; luaL_getmetatable(L, THREAD_TYPENAME); lua_setmetatable(L, -2); td->reftd = vmtd2 ? vmtd2 : &vmref->td; vmref->nref++; if (thread_cond_new(&td->cond)) return NULL; if (push_udata) { lua_pushvalue(L, -1); lua_insert(L, -3); /* thread_udata */ } thread_settable(L, td); /* save thread to avoid GC */ return td; }