Skip to content

Commit

Permalink
win: fix uv_thread_self()
Browse files Browse the repository at this point in the history
59658a8 changed uv_thread_self()
to return uv_thread_t, but uv_thread_t is a thread's HANDLE while
uv_thread_self() returns the current thread's id.
This means that uv_thread_equal() is also broken, as we are
potentially comparing HANDLES to ids.

Changed uv_thread_self() to return the current thread's creation handle.
Fixed small doc issue.
  • Loading branch information
orangemocha authored and saghul committed Nov 10, 2014
1 parent 0f25560 commit 6591d00
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 59 deletions.
2 changes: 1 addition & 1 deletion docs/src/threading.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Threads
^^^^^^^

.. c:function:: int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg)
.. c:function:: unsigned long uv_thread_self(void)
.. c:function:: uv_thread_t uv_thread_self(void)
.. c:function:: int uv_thread_join(uv_thread_t *tid)
.. c:function:: int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2)
Expand Down
45 changes: 45 additions & 0 deletions src/unix/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,51 @@
#undef NANOSEC
#define NANOSEC ((uint64_t) 1e9)


struct thread_ctx {
void (*entry)(void* arg);
void* arg;
};


static void* uv__thread_start(void *arg)
{
struct thread_ctx *ctx_p;
struct thread_ctx ctx;

ctx_p = arg;
ctx = *ctx_p;
free(ctx_p);
ctx.entry(ctx.arg);

return 0;
}


int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
struct thread_ctx* ctx;
int err;

ctx = malloc(sizeof(*ctx));
if (ctx == NULL)
return UV_ENOMEM;

ctx->entry = entry;
ctx->arg = arg;

err = pthread_create(tid, NULL, uv__thread_start, ctx);

if (err)
free(ctx);

return err ? -1 : 0;
}


uv_thread_t uv_thread_self(void) {
return pthread_self();
}

int uv_thread_join(uv_thread_t *tid) {
return -pthread_join(*tid, NULL);
}
Expand Down
58 changes: 0 additions & 58 deletions src/uv-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,64 +257,6 @@ int uv_udp_recv_stop(uv_udp_t* handle) {
}


struct thread_ctx {
void (*entry)(void* arg);
void* arg;
};


#ifdef _WIN32
static UINT __stdcall uv__thread_start(void* arg)
#else
static void* uv__thread_start(void *arg)
#endif
{
struct thread_ctx *ctx_p;
struct thread_ctx ctx;

ctx_p = arg;
ctx = *ctx_p;
free(ctx_p);
ctx.entry(ctx.arg);

return 0;
}


int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
struct thread_ctx* ctx;
int err;

ctx = malloc(sizeof(*ctx));
if (ctx == NULL)
return UV_ENOMEM;

ctx->entry = entry;
ctx->arg = arg;

#ifdef _WIN32
*tid = (HANDLE) _beginthreadex(NULL, 0, uv__thread_start, ctx, 0, NULL);
err = *tid ? 0 : errno;
#else
err = pthread_create(tid, NULL, uv__thread_start, ctx);
#endif

if (err)
free(ctx);

return err ? -1 : 0;
}


uv_thread_t uv_thread_self(void) {
#ifdef _WIN32
return GetCurrentThreadId();
#else
return pthread_self();
#endif
}


void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
QUEUE* q;
uv_handle_t* h;
Expand Down
62 changes: 62 additions & 0 deletions src/win/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,68 @@ void uv_once(uv_once_t* guard, void (*callback)(void)) {
uv__once_inner(guard, callback);
}

static UV_THREAD_LOCAL uv_thread_t uv__current_thread = NULL;

struct thread_ctx {
void (*entry)(void* arg);
void* arg;
uv_thread_t self;
};


static UINT __stdcall uv__thread_start(void* arg)
{
struct thread_ctx *ctx_p;
struct thread_ctx ctx;

ctx_p = arg;
ctx = *ctx_p;
free(ctx_p);

uv__current_thread = ctx.self;
ctx.entry(ctx.arg);

return 0;
}


int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
struct thread_ctx* ctx;
int err;
HANDLE thread;

ctx = malloc(sizeof(*ctx));
if (ctx == NULL)
return UV_ENOMEM;

ctx->entry = entry;
ctx->arg = arg;

/* Create the thread in suspended state so we have a chance to pass
* its own creation handle to it */
thread = (HANDLE) _beginthreadex(NULL,
0,
uv__thread_start,
ctx,
CREATE_SUSPENDED,
NULL);
if (thread == NULL) {
err = errno;
free(ctx);
} else {
err = 0;
*tid = thread;
ctx->self = thread;
ResumeThread(thread);
}

return err;
}


uv_thread_t uv_thread_self(void) {
return uv__current_thread;
}

int uv_thread_join(uv_thread_t *tid) {
if (WaitForSingleObject(*tid, INFINITE))
Expand Down

0 comments on commit 6591d00

Please sign in to comment.