OverviewFilesCommitsIssuesDocsReleasesPeers

mirall-cli / node_modules / bare-thread / binding.c

206 lines · c ref:
#if defined(__linux__)
#define _GNU_SOURCE
#endif

#include <assert.h>
#include <bare.h>
#include <js.h>
#include <uv.h>

#if defined(__linux__)
#include <unistd.h>
#endif

static js_value_t *
bare_thread_get_cpu(js_env_t *env, js_callback_info_t *info) {
  int err;

  int cpu = uv_thread_getcpu();

  if (cpu == UV_ENOTSUP) return NULL;

  if (cpu < 0) {
    err = js_throw_error(env, uv_err_name(cpu), uv_strerror(cpu));
    assert(err == 0);

    return NULL;
  }

  js_value_t *result;
  err = js_create_int32(env, cpu, &result);
  assert(err == 0);

  return result;
}

static js_value_t *
bare_thread_get_id(js_env_t *env, js_callback_info_t *info) {
  int err;

  uint64_t id;

#if defined(__APPLE__)
  pthread_threadid_np(pthread_self(), &id);
#elif defined(__linux__)
  id = (uint64_t) gettid();
#elif defined(_WIN32)
  id = (uint64_t) GetCurrentThreadId();
#else
  id = (uint64_t) (uintptr_t) uv_thread_self() & 0x1fffffffffffffull;
#endif

  js_value_t *result;
  err = js_create_int64(env, id, &result);
  assert(err == 0);

  return result;
}

static js_value_t *
bare_thread_get_name(js_env_t *env, js_callback_info_t *info) {
  int err;

  uv_thread_t thread = uv_thread_self();

  char name[256];
  err = uv_thread_getname(&thread, name, 256);
  if (err < 0) {
    err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
    assert(err == 0);

    return NULL;
  }

  js_value_t *result;
  err = js_create_string_utf8(env, (utf8_t *) name, -1, &result);
  assert(err == 0);

  return result;
}

static js_value_t *
bare_thread_set_name(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 1;
  js_value_t *argv[1];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 1);

  utf8_t data[256];
  err = js_get_value_string_utf8(env, argv[0], data, 256, NULL);
  assert(err == 0);

  err = uv_thread_setname((char *) data);
  if (err < 0) {
    err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
    assert(err == 0);

    return NULL;
  }

  return NULL;
}

static js_value_t *
bare_thread_get_priority(js_env_t *env, js_callback_info_t *info) {
  int err;

  uv_thread_t thread = uv_thread_self();

  int priority;
  err = uv_thread_getpriority(thread, &priority);
  if (err < 0) {
    err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
    assert(err == 0);

    return NULL;
  }

  js_value_t *result;
  err = js_create_int32(env, priority, &result);
  assert(err == 0);

  return result;
}

static js_value_t *
bare_thread_set_priority(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 1;
  js_value_t *argv[1];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 1);

  int priority;
  err = js_get_value_int32(env, argv[0], &priority);
  assert(err == 0);

  uv_thread_t thread = uv_thread_self();

  err = uv_thread_setpriority(thread, priority);
  if (err < 0) {
    err = js_throw_error(env, uv_err_name(err), uv_strerror(err));
    assert(err == 0);

    return NULL;
  }

  return NULL;
}

static js_value_t *
bare_thread_exports(js_env_t *env, js_value_t *exports) {
  int err;

#define V(name, fn) \
  { \
    js_value_t *val; \
    err = js_create_function(env, name, -1, fn, NULL, &val); \
    assert(err == 0); \
    err = js_set_named_property(env, exports, name, val); \
    assert(err == 0); \
  }

  V("getCPU", bare_thread_get_cpu)
  V("getID", bare_thread_get_id)
  V("getName", bare_thread_get_name)
  V("setName", bare_thread_set_name)
  V("getPriority", bare_thread_get_priority)
  V("setPriority", bare_thread_set_priority)
#undef V

  js_value_t *priority;
  err = js_create_object(env, &priority);
  assert(err == 0);

  err = js_set_named_property(env, exports, "priority", priority);
  assert(err == 0);

#define V(name) \
  { \
    js_value_t *val; \
    err = js_create_int32(env, UV_THREAD_##name, &val); \
    assert(err == 0); \
    err = js_set_named_property(env, priority, #name, val); \
    assert(err == 0); \
  }

  V(PRIORITY_LOWEST);
  V(PRIORITY_BELOW_NORMAL);
  V(PRIORITY_NORMAL);
  V(PRIORITY_ABOVE_NORMAL);
  V(PRIORITY_HIGHEST);

  return exports;
}

BARE_MODULE(bare_thread, bare_thread_exports)