Ejemplo n.º 1
0
/*
 * Returns: [thread_ludata]
 */
static int
thread_init (lua_State *L)
{
    struct sys_thread *td;

    /* TLS Index */
    if (g_TLSIndex == INVALID_TLS_INDEX) {
#ifndef _WIN32
	const int res = pthread_key_create(&g_TLSIndex, NULL);
	if (res) {
	    errno = res;
	    goto err;
	}
#else
	if ((g_TLSIndex = TlsAlloc()) == INVALID_TLS_INDEX)
	    goto err;
#endif
    }
    /* VM Mutex */
    td = sys_get_thread();
    if (!td) {
	if (vmthread_new(L, (void *) &td))
	    goto err;

	thread_settable(L, L, td->tid);
	sys_set_thread(td);
	sys_vm2_enter(td);
    }
    lua_pushlightuserdata(L, td->vmtd);
    return 1;
 err:
    return sys_seterror(L, 0);
}
Ejemplo n.º 2
0
struct sys_thread *
sys_del_thread (struct sys_thread *td)
{
    lua_State *L = td->L;
    const thread_id_t tid = td->tid;

    td = (struct sys_thread *) td->vmtd;

    /* remove reference to self */
    lua_pushnil(L);
    lua_pushnil(L);
    thread_settable(L, L, tid);

    return td;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
struct sys_thread *
sys_new_thread (struct sys_thread *td)
{
    lua_State *L = td->L;
    lua_State *NL;
    struct sys_thread *ntd;

    NL = lua_newthread(L);
    if (!NL) return NULL;

    ntd = lua_newuserdata(L, sizeof(struct sys_thread));
    memset(ntd, 0, sizeof(struct sys_thread));
    ntd->mutex = td->mutex;
    ntd->L = NL;
    ntd->vmtd = td->vmtd;
    ntd->tid = thread_getid();

    thread_settable(L, NL, ntd->tid);  /* save thread to avoid GC */
    return ntd;
}
Ejemplo n.º 5
0
/*
 * 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;
}
Ejemplo n.º 6
0
/*
 * Arguments: function, [arguments (any) ...]
 * Returns: [thread_ludata]
 */
static int
thread_run (lua_State *L)
{
    struct sys_thread *vmtd = sys_get_thread();
    lua_State *NL;
    struct sys_thread *td;
#ifndef _WIN32
    pthread_attr_t attr;
    int res = 0;
#else
    HANDLE hThr;
    const int res = 0;
#endif

    if (!vmtd) luaL_argerror(L, 0, "Threading not initialized");
    luaL_checktype(L, 1, LUA_TFUNCTION);

    NL = lua_newthread(L);
    if (!NL) goto err;

    td = lua_newuserdata(L, sizeof(struct sys_thread));
    memset(td, 0, sizeof(struct sys_thread));
    td->mutex = vmtd->mutex;
    td->L = NL;
    td->vmtd = vmtd->vmtd;

#ifndef _WIN32
    if ((res = pthread_attr_init(&attr))
     || (res = pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE)))
	goto err;
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    res = pthread_create(&td->tid, &attr,
     (thread_func_t) thread_start, td);
    pthread_attr_destroy(&attr);
    if (!res) {
#else
    hThr = (HANDLE) _beginthreadex(NULL, THREAD_STACK_SIZE,
     (thread_func_t) thread_start, td, 0, &td->tid);
    if (hThr) {
	CloseHandle(hThr);
#endif
	thread_settable(L, NL, td->tid);  /* save thread to avoid GC */
	lua_xmove(L, NL, lua_gettop(L));  /* move function and args to NL */

	lua_pushlightuserdata(L, td);
	return 1;
    }
 err:
    return sys_seterror(L, res);
}


/*
 * Arguments: function, master (thread_ludata),
 *	[arguments (string | number | boolean | lightuserdata) ...],
 *	thread, thread_udata
 */
static THREAD_FUNC_API
thread_startvm (struct sys_thread *td)
{
    lua_State *L = td->L;

    thread_settable(L, L, td->tid);

    sys_set_thread(td);
    sys_vm2_enter(td);

    if (lua_pcall(L, lua_gettop(L) - 1, 0, 0)) {
	if (td->interrupted && lua_touserdata(L, -1) == &g_TLSIndex)
	    lua_pop(L, 1);
	else
	    lua_error(L);
    }

    /* notify event_queue */
    if (td->trigger)
	sys_trigger_notify(&td->trigger, SYS_EVEOF | SYS_EVDEL);

    lua_close(L);
    return 0;
}