Esempio n. 1
0
/*
 * Arguments: function, [arguments (any) ...]
 * Returns: [thread_udata]
 */
static int
thread_run (lua_State *L)
{
  struct sys_thread *td, *vmtd = sys_thread_get();

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

  td = sys_thread_new(L, vmtd, NULL, 1);
  if (!td) goto err;

  lua_insert(L, 1);  /* thread_udata */

  /* function and arguments */
  {
    const int n = lua_gettop(L) - 1;
    luaL_checkstack(td->L, n, NULL);
    lua_xmove(L, td->L, n);
  }

  if (!sys_thread_create(td, 0)) {
    return 1;
  }
  sys_thread_del(td);
 err:
  return sys_seterror(L, 0);
}
Esempio n. 2
0
sys_threadpool *
sys_threadpool_create(uint32_t num_workers)
{
	sys_threadpool *pool = (sys_threadpool *)calloc(1, sizeof(*pool));
	sys_worker *worker = NULL;
	size_t i;

	if (!pool)
		return NULL;

	pool->task_mutex = sys_mutex_create();
	pool->task_notify = sys_cond_var_create();
	
	pool->num_workers = num_workers;
	pool->shutdown = false;

	if (pool->num_workers <= 0) {
		if ((pool->num_workers = sys_cpu_count()) <= 0) {
			log_entry(THREADPOOL_MODULE, LOG_WARNING, "Failed to determine processor count. Limiting server to one thread. To avoid this, specify the number of threads");
			pool->num_workers = 1;
		}
	}

	if (rt_array_init(&pool->workers, pool->num_workers, sizeof(sys_worker)) != SYS_OK)
		goto free_task;

	if (rt_array_init(&pool->active_tasks, pool->num_workers, sizeof(sys_task *)) != SYS_OK)
		goto free_workers;	

	if (rt_queue_init(&pool->task_queue, (size_t)pool->num_workers * 2, sizeof(sys_task)) != SYS_OK)
		goto free_active_tasks;

	pool->worker_key = sys_tls_alloc_key();

	rt_array_fill(&pool->workers);
	for (i = 0; i < pool->num_workers; ++i) {
		worker = rt_array_get(&pool->workers, i);

		worker->id = i;
		worker->idle = true;
		worker->pool = pool;
		
		worker->thread = sys_thread_create(_threadpool_worker_proc);

		sys_thread_start(worker->thread, worker);
		sys_thread_detach(worker->thread);
	}

	return pool;

free_active_tasks:
	rt_array_release(&pool->active_tasks);

free_workers:
	rt_array_release(&pool->workers);

free_task:
	sys_mutex_destroy(pool->task_mutex);
	sys_cond_var_destroy(pool->task_notify);

	free(pool);

	return NULL;
}
Esempio n. 3
0
/*
 * Arguments: options (table: {1..n: library names, "cpu": number}),
 *	filename (string) | function_dump (string),
 *	[arguments (string | number | boolean | ludata | share_object) ...]
 * Returns: [thread_udata]
 */
static int
thread_runvm (lua_State *L)
{
  const char *path = luaL_checkstring(L, 2);
  struct sys_thread *vmtd = sys_thread_get();
  struct sys_thread *td, *faketd;
  lua_State *NL;
  unsigned int loadlibs = ~0U;  /* load all standard libraries */
  int is_affin = 0, cpu = 0;

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

  /* options */
  if (lua_istable(L, 1)) {
    unsigned int libs = 0;
    int i;

    for (i = 1; ; ++i) {
      const char *s;
      lua_rawgeti(L, 1, i);
      s = lua_tostring(L, -1);
      if (!s || !*s) {
        if (s) loadlibs = 0;  /* don't load any libraries */
        lua_pop(L, 1);
        break;
      }
      libs |= 1 << luaL_checkoption(L, -1, NULL, stdlib_names);
      lua_pop(L, 1);
    }
    if (libs) loadlibs = libs;

    /* CPU affinity */
    lua_getfield(L, 1, "cpu");
    if (lua_type(L, -1) == LUA_TNUMBER) {
      cpu = (int) lua_tointeger(L, -1);
      is_affin = 1;
    }
    lua_pop(L, 1);
  }

  td = thread_newvm(NULL, vmtd, loadlibs);
  if (!td) goto err;

  faketd = sys_thread_new(L, vmtd, td, 1);
  if (!faketd) goto err;

  lua_replace(L, 1);  /* fake thread_udata */

  if (is_affin)
    td->vmtd->cpu = cpu;

  NL = td->L;

  /* function */
  if (path[0] == LUA_SIGNATURE[0]
   ? luaL_loadbuffer(NL, path, lua_rawlen(L, ARG_LAST), "thread")
   : luaL_loadfile(NL, path)) {
    lua_pushstring(L, lua_tostring(NL, -1));  /* error message */
    lua_close(NL);
    lua_error(L);
  }

  /* arguments */
  {
    int i, top = lua_gettop(L);

    luaL_checkstack(NL, top + LUA_MINSTACK, "too many arguments");

    for (i = ARG_LAST + 1; i <= top; ++i) {
      switch (lua_type(L, i)) {
      case LUA_TSTRING:
        {
          size_t len;
          const char *s = lua_tolstring(L, i, &len);
          lua_pushlstring(NL, s, len);
        }
        break;
      case LUA_TNUMBER:
        lua_pushnumber(NL, lua_tonumber(L, i));
        break;
      case LUA_TBOOLEAN:
        lua_pushboolean(NL, lua_toboolean(L, i));
        break;
      case LUA_TLIGHTUSERDATA:
        lua_pushlightuserdata(NL, lua_touserdata(L, i));
        break;
      case LUA_TUSERDATA:
        if (!luaL_getmetafield(L, i, THREAD_XDUP_TAG))
          luaL_argerror(L, i, "shareable object expected");
        lua_pushvalue(L, i);
        lua_pushlightuserdata(L, NL);
        lua_call(L, 2, 0);
        break;
      case LUA_TNIL:
        lua_pushnil(NL);
        break;
      default:
        luaL_argerror(L, i, "primitive type expected");
      }
    }
  }

  if (!sys_thread_create(td, is_affin)) {
    faketd->tid = td->tid;
    lua_settop(L, 1);
    return 1;
  }
  lua_close(NL);
 err:
  return sys_seterror(L, 0);
}