コード例 #1
0
ファイル: sys_thread.c プロジェクト: tnodir/luasys
/*
 * Arguments: thread_udata
 */
static int
thread_done (lua_State *L)
{
  struct sys_thread *td = checkudata(L, 1, THREAD_TYPENAME);

  if (td->L) {
    if (thread_isvm(td)) {
      thread_critsect_leave(td->vmcsp);
      thread_critsect_del(td->vmcsp);
    } else {
      sys_vm2_leave(td);
#ifndef _WIN32
      {
        THREAD_FUNC_RES v;
        pthread_join(td->tid, &v);
      }
#else
      WaitForSingleObject(td->tid, INFINITE);
      CloseHandle(td->tid);
#endif
      sys_vm2_enter(td);
    }
    (void) thread_cond_del(&td->cond);

    lua_rawgetp(L, LUA_REGISTRYINDEX, THREAD_KEY_ADDRESS);
    lua_pushnil(L);
    lua_rawsetp(L, -2, td->L); /* coroutine */
    lua_pop(L, 1);

    td->L = NULL;
  }
  return 0;
}
コード例 #2
0
ファイル: sys_thread.c プロジェクト: LuaDist/luasys
/*
 * Arguments: function, [arguments (any) ...]
 */
static THREAD_FUNC_API
thread_start (struct sys_thread *td)
{
    lua_State *L = td->L;

    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);

    /* remove reference to self */
    td = sys_del_thread(td);

    sys_vm2_leave(td);
    return 0;
}
コード例 #3
0
ファイル: sys_thread.c プロジェクト: LuaDist/luasys
void
sys_vm_leave (void)
{
    if (g_TLSIndex == INVALID_TLS_INDEX)
	return;

    sys_vm2_leave(sys_get_thread());
}
コード例 #4
0
ファイル: thread_pipe.c プロジェクト: dilshod/luasys
static int
pipe_cond_wait (thread_cond_t *condp, thread_critsect_t *csp,
                struct sys_thread *td, const msec_t timeout)
{
    int res;

    sys_vm2_leave(td);
    res = thread_cond_wait_nolock(condp, csp, timeout);
    sys_vm2_enter(td);
    return res;
}
コード例 #5
0
ファイル: sys_thread.c プロジェクト: tnodir/luasys
void
sys_thread_switch (struct sys_thread *td)
{
  sys_vm2_leave(td);
#ifndef _WIN32
  sched_yield();
#else
  SwitchToThread();
#endif
  sys_vm2_enter(td);
}
コード例 #6
0
ファイル: sys_thread.c プロジェクト: tnodir/luasys
static int
thread_cond_wait_vm (thread_cond_t *condp, struct sys_thread *td,
                     const msec_t timeout)
{
  int res;

#if defined(USE_PTHREAD_SYNC)
  sys_vm2_preleave(td);
  res = thread_cond_wait_nolock(condp, td->vmcsp, timeout);
  sys_vm2_postenter(td);
#else
  sys_vm2_leave(td);
  res = thread_handle_wait(*condp, timeout);
  sys_vm2_enter(td);
#endif

  return res;
}
コード例 #7
0
ファイル: isapi_ecb.c プロジェクト: richardhundt/luasys
/*
 * Arguments: ecb_udata, [membuf_udata, count (number)]
 * Returns: [string | count (number)]
 */
static int
ecb_read (lua_State *L)
{
  LPEXTENSION_CONTROL_BLOCK ecb = lua_unboxpointer(L, 1, ECB_TYPENAME);
  size_t n = !lua_isnumber(L, -1) ? ~((size_t) 0)
   : (size_t) lua_tointeger(L, -1);
  const size_t len = n;  /* how much total to read */
  size_t rlen;  /* how much to read */
  int nr;  /* number of bytes actually read */
  struct sys_thread *td = sys_thread_get();
  struct sys_buffer sb;
  char buf[SYS_BUFSIZE];
  int res = 0;

  sys_buffer_write_init(L, 2, &sb, buf, sizeof(buf));
  do {
    rlen = (n <= sb.size) ? n : sb.size;
    if (td) sys_vm2_leave(td);
    {
      DWORD l;
      nr = ecb->ReadClient(ecb->ConnID, sb.ptr.w, &l) ? (int) l : -1;
    }
    if (td) sys_vm2_enter(td);
    if (nr == -1) break;
    n -= nr;  /* still have to read `n' bytes */
  } while ((n != 0L && nr == (int) rlen)  /* until end of count or eof */
   && sys_buffer_write_next(L, &sb, buf, 0));
  if (nr <= 0 && len == n) {
    res = -1;
  } else {
    if (!sys_buffer_write_done(L, &sb, buf, nr))
      lua_pushinteger(L, len - n);
  }
  if (td) sys_thread_check(td);
  if (!res) return 1;
  return sys_seterror(L, 0);
}
コード例 #8
0
ファイル: sys_thread.c プロジェクト: tnodir/luasys
/*
 * Arguments: [status (number)]
 */
static THREAD_FUNC_RES
thread_exit (struct sys_thread *td)
{
  struct sys_thread *reftd = td->reftd;
  const int is_vm = thread_isvm(td);
  lua_Integer res;

  td->sched_ctx = NULL;

  if (td->flags != SYS_THREAD_KILLED) {
    td->flags = SYS_THREAD_KILLED;
    td->exit_status = lua_tointeger(td->L, -1);
  }
  res = td->exit_status;

  if (is_vm) {
    thread_waitvm(td->vmtd, TIMEOUT_INFINITE);
    lua_close(td->L);
  } else {
    struct sys_thread *vmtd = thread_getvm(td);

#ifndef _WIN32
    pthread_cond_broadcast(&td->cond);
#endif
    /* stop collector to prevent self-deadlock on GC */
    lua_gc(vmtd->L, LUA_GCSTOP, 0);
    sys_thread_del(td);
    lua_gc(vmtd->L, LUA_GCRESTART, 0);
    sys_vm2_leave(vmtd);
  }

  /* decrease VM-thread's reference count */
  if (reftd) {
    struct sys_vmthread *vmref = reftd->vmtd;

    sys_vm2_enter(reftd);
    if (is_vm) {
      reftd->flags = SYS_THREAD_KILLED;
      reftd->exit_status = res;
#ifndef _WIN32
      pthread_cond_broadcast(&reftd->cond);
#endif
      sys_thread_del(reftd);
    }
    if (!--vmref->nref) {
#ifndef _WIN32
      pthread_cond_broadcast(&vmref->td.cond);
#else
      (void) thread_cond_signal(&vmref->td.cond);
#endif
    }
    sys_vm2_leave(reftd);
  }

#ifndef _WIN32
  pthread_exit((THREAD_FUNC_RES) res);
#else
  _endthreadex((THREAD_FUNC_RES) res);
#endif
  return 0;
}
コード例 #9
0
ファイル: select.c プロジェクト: ELMERzark/luasys
EVQ_API int
evq_wait (struct event_queue *evq, struct sys_thread *td, msec_t timeout)
{
  struct event *ev_ready;
  fd_set work_readset = evq->readset;
  fd_set work_writeset = evq->writeset;
  struct timeval tv, *tvp;
  struct event **events = evq->events;
  const int npolls = evq->npolls;
  int i, nready, max_fd;

  if (timeout != 0L) {
    timeout = timeout_get(evq->tq, timeout, evq->now);
    if (timeout == 0L) {
      ev_ready = timeout_process(evq->tq, NULL, evq->now);
      goto end;
    }
  }
  if (timeout == TIMEOUT_INFINITE)
    tvp = NULL;
  else {
    tv.tv_sec = timeout / 1000;
    tv.tv_usec = (timeout % 1000) * 1000;
    tvp = &tv;
  }

  max_fd = evq->max_fd;
  if (max_fd == -1) {
    for (i = 1; i < npolls; ++i) {
      struct event *ev = events[i];
      if (max_fd < ev->fd)
        max_fd = ev->fd;
    }
    evq->max_fd = max_fd;
  }

  if (td) sys_vm2_leave(td);
  nready = select(max_fd + 1, &work_readset, &work_writeset, NULL, tvp);
  if (td) sys_vm2_enter(td);

  evq->now = sys_milliseconds();

  if (nready == -1)
    return (errno == EINTR) ? 0 : -1;

  ev_ready = evq->ev_ready;
  if (tvp) {
    if (!nready) {
      if (evq->tq) {
        struct event *ev = timeout_process(evq->tq, ev_ready, evq->now);
        if (ev != ev_ready) {
          ev_ready = ev;
          goto end;
        }
      }
      return SYS_ERR_TIMEOUT;
    }

    timeout = evq->now;
  }

  if (FD_ISSET(evq->sig_fd[0], &work_readset)) {
    ev_ready = signal_process_interrupt(evq, ev_ready, timeout);
    --nready;
  }

  for (i = 1; i < npolls && nready; i++) {
    struct event *ev = events[i];
    unsigned int res = 0;

    if ((ev->flags & EVENT_READ) && FD_ISSET(ev->fd, &work_readset))
      res |= EVENT_READ_RES;
    else if ((ev->flags & EVENT_WRITE) && FD_ISSET(ev->fd, &work_writeset))
      res |= EVENT_WRITE_RES;

    if (!res) continue;

    ev->flags |= res;
    if (!(ev->flags & EVENT_ACTIVE)) {
      ev->flags |= EVENT_ACTIVE;
      if (ev->flags & EVENT_ONESHOT)
        evq_del(ev, 1);
      else if (ev->tq && !(ev->flags & EVENT_TIMEOUT_MANUAL))
        timeout_reset(ev, timeout);

      ev->next_ready = ev_ready;
      ev_ready = ev;
    }
    --nready;
  }
  if (!ev_ready) return 0;
 end:
  evq->ev_ready = ev_ready;
  return 0;
}