/* * Arguments: dpool_udata, data_items (any) ... */ static int dpool_put (lua_State *L) { struct sys_thread *td = sys_thread_get(); struct data_pool *dp = checkudata(L, 1, DPOOL_TYPENAME); int nput = lua_gettop(L) - 1; if (!td) luaL_argerror(L, 0, "Threading not initialized"); if (!nput) luaL_argerror(L, 2, "data expected"); lua_getfenv(L, 1); /* storage */ lua_insert(L, 1); if (dp->n >= dp->max) { if (dp->flags & DPOOL_PUTONFULL) { lua_rawgetp(L, 1, (void *) DPOOL_PUTONFULL); lua_insert(L, 2); lua_call(L, 1 + nput, LUA_MULTRET); nput = lua_gettop(L) - 1; if (!nput) return 0; } else { do { const int res = thread_event_wait(&dp->tev, td, TIMEOUT_INFINITE); sys_thread_check(td); if (res) return sys_seterror(L, 0); } while (dp->n >= dp->max); } } /* Try directly move data between threads */ if (dp->nwaits && !dp->td) { dp->td = td; dp->nput = nput; thread_event_signal(&dp->tev); sys_thread_switch(0); dp->td = NULL; if (!dp->nput) return 0; /* moved to thread */ dp->nput = 0; } /* Keep data in the storage */ { int top = dp->top; lua_pushinteger(L, nput); do { lua_rawseti(L, 1, ++top); } while (nput--); dp->top = top; if (!dp->n++) { thread_event_signal(&dp->tev); } } return 0; }
PUBLIC void Thread_object::invoke(L4_obj_ref /*self*/, L4_fpage::Rights rights, Syscall_frame *f, Utcb *utcb) { register L4_obj_ref::Operation op = f->ref().op(); if (((op != 0) && !(op & L4_obj_ref::Ipc_send)) || (op & L4_obj_ref::Ipc_reply) || f->tag().proto() != L4_msg_tag::Label_thread) { /* we do IPC */ Thread *ct = current_thread(); Thread *sender = 0; Thread *partner = 0; bool have_rcv = false; if (EXPECT_FALSE(!check_sys_ipc(op, &partner, &sender, &have_rcv))) { utcb->error = L4_error::Not_existent; return; } ct->do_ipc(f->tag(), partner, partner, have_rcv, sender, f->timeout(), f, rights); return; } switch (utcb->values[0] & Opcode_mask) { case Op_control: f->tag(sys_control(rights, f->tag(), utcb)); return; case Op_ex_regs: f->tag(sys_ex_regs(f->tag(), utcb)); return; case Op_switch: f->tag(sys_thread_switch(f->tag(), utcb)); return; case Op_stats: f->tag(sys_thread_stats(f->tag(), utcb)); return; case Op_vcpu_resume: f->tag(sys_vcpu_resume(f->tag(), utcb)); return; case Op_register_del_irq: f->tag(sys_register_delete_irq(f->tag(), utcb, utcb)); return; case Op_modify_senders: f->tag(sys_modify_senders(f->tag(), utcb, utcb)); return; case Op_vcpu_control: f->tag(sys_vcpu_control(rights, f->tag(), utcb)); return; default: f->tag(invoke_arch(f->tag(), utcb)); return; } }
static int thread_switch_wrap (lua_State *L) { struct sys_thread *td = sys_thread_get(); (void) L; if (td) { sys_thread_switch(td); sys_thread_check(td, L); } return 0; }