@@ -0,0 +1,176 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

#include "internal.h"

#include <errno.h>
#include <pthread.h>

/* TODO add condvar support to libuv */
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static pthread_once_t once = PTHREAD_ONCE_INIT;
static pthread_t threads[4];
static ngx_queue_t exit_message;
static ngx_queue_t wq = { &wq, &wq };


static void* worker(void* arg) {
struct uv__work* w;
ngx_queue_t* q;

(void) arg;

for (;;) {
if (pthread_mutex_lock(&mutex))
abort();

while (ngx_queue_empty(&wq))
if (pthread_cond_wait(&cond, &mutex))
abort();

q = ngx_queue_head(&wq);

if (q == &exit_message)
pthread_cond_signal(&cond);
else
ngx_queue_remove(q);

if (pthread_mutex_unlock(&mutex))
abort();

if (q == &exit_message)
break;

w = ngx_queue_data(q, struct uv__work, wq);
w->work(w);

uv_mutex_lock(&w->loop->wq_mutex);
ngx_queue_insert_tail(&w->loop->wq, &w->wq);
uv_mutex_unlock(&w->loop->wq_mutex);
uv_async_send(&w->loop->wq_async);
}

return NULL;
}


static void post(ngx_queue_t* q) {
pthread_mutex_lock(&mutex);
ngx_queue_insert_tail(&wq, q);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}


static void init_once(void) {
unsigned int i;

ngx_queue_init(&wq);

for (i = 0; i < ARRAY_SIZE(threads); i++)
if (pthread_create(threads + i, NULL, worker, NULL))
abort();
}


__attribute__((destructor))
static void cleanup(void) {
unsigned int i;
int err;

post(&exit_message);

for (i = 0; i < ARRAY_SIZE(threads); i++) {
err = pthread_join(threads[i], NULL);
assert(err == 0 || err == EINVAL || err == ESRCH);
(void) err; /* Silence compiler warning in release builds. */
}
}


void uv__work_submit(uv_loop_t* loop,
struct uv__work* w,
void (*work)(struct uv__work* w),
void (*done)(struct uv__work* w)) {
pthread_once(&once, init_once);
w->loop = loop;
w->work = work;
w->done = done;
post(&w->wq);
}


void uv__work_done(uv_async_t* handle, int status) {
struct uv__work* w;
uv_loop_t* loop;
ngx_queue_t* q;
ngx_queue_t wq;

loop = container_of(handle, uv_loop_t, wq_async);
ngx_queue_init(&wq);

uv_mutex_lock(&loop->wq_mutex);
if (!ngx_queue_empty(&loop->wq)) {
q = ngx_queue_head(&loop->wq);
ngx_queue_split(&loop->wq, q, &wq);
}
uv_mutex_unlock(&loop->wq_mutex);

while (!ngx_queue_empty(&wq)) {
q = ngx_queue_head(&wq);
ngx_queue_remove(q);

w = container_of(q, struct uv__work, wq);
w->done(w);
}
}


static void uv__queue_work(struct uv__work* w) {
uv_work_t* req = container_of(w, uv_work_t, work_req);

if (req->work_cb)
req->work_cb(req);
}


static void uv__queue_done(struct uv__work* w) {
uv_work_t* req = container_of(w, uv_work_t, work_req);

uv__req_unregister(req->loop, req);

if (req->after_work_cb)
req->after_work_cb(req);
}


int uv_queue_work(uv_loop_t* loop,
uv_work_t* req,
uv_work_cb work_cb,
uv_after_work_cb after_work_cb) {
uv__req_init(loop, req, UV_WORK);
req->loop = loop;
req->work_cb = work_cb;
req->after_work_cb = after_work_cb;
uv__work_submit(loop, &req->work_req, uv__queue_work, uv__queue_done);
return 0;
}

This file was deleted.

This file was deleted.

@@ -27,6 +27,7 @@


#define HAVE_SRWLOCK_API() (pTryAcquireSRWLockShared != NULL)
#define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL)

#ifdef _MSC_VER /* msvc */
# define inline __inline
@@ -56,6 +57,23 @@ inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock);
inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock);


inline static int uv_cond_fallback_init(uv_cond_t* cond);
inline static void uv_cond_fallback_destroy(uv_cond_t* cond);
inline static void uv_cond_fallback_signal(uv_cond_t* cond);
inline static void uv_cond_fallback_broadcast(uv_cond_t* cond);
inline static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex);
inline static int uv_cond_fallback_timedwait(uv_cond_t* cond,
uv_mutex_t* mutex, uint64_t timeout);

inline static int uv_cond_condvar_init(uv_cond_t* cond);
inline static void uv_cond_condvar_destroy(uv_cond_t* cond);
inline static void uv_cond_condvar_signal(uv_cond_t* cond);
inline static void uv_cond_condvar_broadcast(uv_cond_t* cond);
inline static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex);
inline static int uv_cond_condvar_timedwait(uv_cond_t* cond,
uv_mutex_t* mutex, uint64_t timeout);


static NOINLINE void uv__once_inner(uv_once_t* guard,
void (*callback)(void)) {
DWORD result;
@@ -81,7 +99,7 @@ static NOINLINE void uv__once_inner(uv_once_t* guard,

} else {
/* We lost the race. Destroy the event we created and wait for the */
/* existing one to become signaled. */
/* existing one todv become signaled. */
CloseHandle(created_event);
result = WaitForSingleObject(existing_event, INFINITE);
assert(result == WAIT_OBJECT_0);
@@ -140,6 +158,8 @@ void uv_mutex_unlock(uv_mutex_t* mutex) {


int uv_rwlock_init(uv_rwlock_t* rwlock) {
uv__once_init();

if (HAVE_SRWLOCK_API())
return uv__rwlock_srwlock_init(rwlock);
else
@@ -365,3 +385,228 @@ inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock) {
inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock) {
uv_mutex_unlock(&rwlock->fallback_.write_mutex_);
}



/* This condition variable implementation is based on the SetEvent solution
* (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
* We could not use the SignalObjectAndWait solution (section 3.4) because
* it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and
* uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs.
*/

inline static int uv_cond_fallback_init(uv_cond_t* cond) {
/* Initialize the count to 0. */
cond->fallback.waiters_count = 0;

InitializeCriticalSection(&cond->fallback.waiters_count_lock);

/* Create an auto-reset event. */
cond->fallback.signal_event = CreateEvent(NULL, /* no security */
FALSE, /* auto-reset event */
FALSE, /* non-signaled initially */
NULL); /* unnamed */
if (!cond->fallback.signal_event)
goto error2;

/* Create a manual-reset event. */
cond->fallback.broadcast_event = CreateEvent(NULL, /* no security */
TRUE, /* manual-reset */
FALSE, /* non-signaled */
NULL); /* unnamed */
if (!cond->fallback.broadcast_event)
goto error;

return 0;

error:
CloseHandle(cond->fallback.signal_event);
error2:
DeleteCriticalSection(&cond->fallback.waiters_count_lock);
return -1;
}


inline static int uv_cond_condvar_init(uv_cond_t* cond) {
pInitializeConditionVariable(&cond->cond_var);
return 0;
}


int uv_cond_init(uv_cond_t* cond) {
uv__once_init();

if (HAVE_CONDVAR_API())
return uv_cond_condvar_init(cond);
else
return uv_cond_fallback_init(cond);
}


inline static void uv_cond_fallback_destroy(uv_cond_t* cond) {
if (!CloseHandle(cond->fallback.broadcast_event))
abort();
if (!CloseHandle(cond->fallback.signal_event))
abort();
DeleteCriticalSection(&cond->fallback.waiters_count_lock);
}


inline static void uv_cond_condvar_destroy(uv_cond_t* cond) {
/* nothing to do */
}


void uv_cond_destroy(uv_cond_t* cond) {
if (HAVE_CONDVAR_API())
uv_cond_condvar_destroy(cond);
else
uv_cond_fallback_destroy(cond);
}


inline static void uv_cond_fallback_signal(uv_cond_t* cond) {
int have_waiters;

/* Avoid race conditions. */
EnterCriticalSection(&cond->fallback.waiters_count_lock);
have_waiters = cond->fallback.waiters_count > 0;
LeaveCriticalSection(&cond->fallback.waiters_count_lock);

if (have_waiters)
SetEvent(cond->fallback.signal_event);
}


inline static void uv_cond_condvar_signal(uv_cond_t* cond) {
pWakeConditionVariable(&cond->cond_var);
}


void uv_cond_signal(uv_cond_t* cond) {
if (HAVE_CONDVAR_API())
uv_cond_condvar_signal(cond);
else
uv_cond_fallback_signal(cond);
}


inline static void uv_cond_fallback_broadcast(uv_cond_t* cond) {
int have_waiters;

/* Avoid race conditions. */
EnterCriticalSection(&cond->fallback.waiters_count_lock);
have_waiters = cond->fallback.waiters_count > 0;
LeaveCriticalSection(&cond->fallback.waiters_count_lock);

if (have_waiters)
SetEvent(cond->fallback.broadcast_event);
}


inline static void uv_cond_condvar_broadcast(uv_cond_t* cond) {
pWakeAllConditionVariable(&cond->cond_var);
}


void uv_cond_broadcast(uv_cond_t* cond) {
if (HAVE_CONDVAR_API())
uv_cond_condvar_broadcast(cond);
else
uv_cond_fallback_broadcast(cond);
}


inline int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex,
DWORD dwMilliseconds) {
DWORD result;
int last_waiter;
HANDLE handles[2] = {
cond->fallback.signal_event,
cond->fallback.broadcast_event
};

/* Avoid race conditions. */
EnterCriticalSection(&cond->fallback.waiters_count_lock);
cond->fallback.waiters_count++;
LeaveCriticalSection(&cond->fallback.waiters_count_lock);

/* It's ok to release the <mutex> here since Win32 manual-reset events */
/* maintain state when used with <SetEvent>. This avoids the "lost wakeup" */
/* bug. */
uv_mutex_unlock(mutex);

/* Wait for either event to become signaled due to <uv_cond_signal> being */
/* called or <uv_cond_broadcast> being called. */
result = WaitForMultipleObjects(2, handles, FALSE, dwMilliseconds);

EnterCriticalSection(&cond->fallback.waiters_count_lock);
cond->fallback.waiters_count--;
last_waiter = result == WAIT_OBJECT_0 + 1
&& cond->fallback.waiters_count == 0;
LeaveCriticalSection(&cond->fallback.waiters_count_lock);

/* Some thread called <pthread_cond_broadcast>. */
if (last_waiter) {
/* We're the last waiter to be notified or to stop waiting, so reset the */
/* the manual-reset event. */
ResetEvent(cond->fallback.broadcast_event);
}

/* Reacquire the <mutex>. */
uv_mutex_lock(mutex);

if (result == WAIT_OBJECT_0 || result == WAIT_OBJECT_0 + 1)
return 0;

if (result == WAIT_TIMEOUT)
return -1;

abort();
return -1; /* Satisfy the compiler. */
}


inline static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
if (uv_cond_wait_helper(cond, mutex, INFINITE))
abort();
}


inline static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
if (!pSleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
abort();
}


void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
if (HAVE_CONDVAR_API())
uv_cond_condvar_wait(cond, mutex);
else
uv_cond_fallback_wait(cond, mutex);
}


inline static int uv_cond_fallback_timedwait(uv_cond_t* cond,
uv_mutex_t* mutex, uint64_t timeout) {
return uv_cond_wait_helper(cond, mutex, (DWORD)(timeout / 1e6));
}


inline static int uv_cond_condvar_timedwait(uv_cond_t* cond,
uv_mutex_t* mutex, uint64_t timeout) {
if (pSleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
return 0;
if (GetLastError() != ERROR_TIMEOUT)
abort();
return -1;
}


int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex,
uint64_t timeout) {
if (HAVE_CONDVAR_API())
return uv_cond_condvar_timedwait(cond, mutex, timeout);
else
return uv_cond_fallback_timedwait(cond, mutex, timeout);
}
@@ -45,6 +45,11 @@ sTryAcquireSRWLockShared pTryAcquireSRWLockShared;
sTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive;
sReleaseSRWLockShared pReleaseSRWLockShared;
sReleaseSRWLockExclusive pReleaseSRWLockExclusive;
sInitializeConditionVariable pInitializeConditionVariable;
sSleepConditionVariableCS pSleepConditionVariableCS;
sSleepConditionVariableSRW pSleepConditionVariableSRW;
sWakeAllConditionVariable pWakeAllConditionVariable;
sWakeConditionVariable pWakeConditionVariable;


void uv_winapi_init() {
@@ -129,4 +134,19 @@ void uv_winapi_init() {

pReleaseSRWLockExclusive = (sReleaseSRWLockExclusive)
GetProcAddress(kernel32_module, "ReleaseSRWLockExclusive");

pInitializeConditionVariable = (sInitializeConditionVariable)
GetProcAddress(kernel32_module, "InitializeConditionVariable");

pSleepConditionVariableCS = (sSleepConditionVariableCS)
GetProcAddress(kernel32_module, "SleepConditionVariableCS");

pSleepConditionVariableSRW = (sSleepConditionVariableSRW)
GetProcAddress(kernel32_module, "SleepConditionVariableSRW");

pWakeAllConditionVariable = (sWakeAllConditionVariable)
GetProcAddress(kernel32_module, "WakeAllConditionVariable");

pWakeConditionVariable = (sWakeConditionVariable)
GetProcAddress(kernel32_module, "WakeConditionVariable");
}
@@ -4426,6 +4426,25 @@ typedef VOID (WINAPI* sReleaseSRWLockShared)
typedef VOID (WINAPI* sReleaseSRWLockExclusive)
(PSRWLOCK SRWLock);

typedef VOID (WINAPI* sInitializeConditionVariable)
(PCONDITION_VARIABLE ConditionVariable);

typedef BOOL (WINAPI* sSleepConditionVariableCS)
(PCONDITION_VARIABLE ConditionVariable,
PCRITICAL_SECTION CriticalSection,
DWORD dwMilliseconds);

typedef BOOL (WINAPI* sSleepConditionVariableSRW)
(PCONDITION_VARIABLE ConditionVariable,
PSRWLOCK SRWLock,
DWORD dwMilliseconds,
ULONG Flags);

typedef VOID (WINAPI* sWakeAllConditionVariable)
(PCONDITION_VARIABLE ConditionVariable);

typedef VOID (WINAPI* sWakeConditionVariable)
(PCONDITION_VARIABLE ConditionVariable);


/* Ntdll function pointers */
@@ -4448,5 +4467,10 @@ extern sTryAcquireSRWLockShared pTryAcquireSRWLockShared;
extern sTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive;
extern sReleaseSRWLockShared pReleaseSRWLockShared;
extern sReleaseSRWLockExclusive pReleaseSRWLockExclusive;
extern sInitializeConditionVariable pInitializeConditionVariable;
extern sSleepConditionVariableCS pSleepConditionVariableCS;
extern sSleepConditionVariableSRW pSleepConditionVariableSRW;
extern sWakeAllConditionVariable pWakeAllConditionVariable;
extern sWakeConditionVariable pWakeConditionVariable;

#endif /* UV_WIN_WINAPI_H_ */
@@ -415,7 +415,6 @@ static int test_tcp(unsigned int num_servers, unsigned int num_clients) {

free(clients);
free(servers);
uv_loop_delete(uv_default_loop()); /* Silence valgrind. */

return 0;
}
@@ -55,8 +55,13 @@ void platform_init(int argc, char **argv) {

/* Invoke "argv[0] test-name [test-part]". Store process info in *p. */
/* Make sure that all stdio output of the processes is buffered up. */
int process_start(char* name, char* part, process_info_t* p) {
FILE* stdout_file = tmpfile();
int process_start(char* name, char* part, process_info_t* p, int is_helper) {
FILE* stdout_file;
const char* arg;
char* args[16];
int n;

stdout_file = tmpfile();
if (!stdout_file) {
perror("tmpfile");
return -1;
@@ -68,17 +73,34 @@ int process_start(char* name, char* part, process_info_t* p) {
pid_t pid = fork();

if (pid < 0) {
perror("vfork");
perror("fork");
return -1;
}

if (pid == 0) {
/* child */
arg = getenv("UV_USE_VALGRIND");
n = 0;

/* Disable valgrind for helpers, it complains about helpers leaking memory.
* They're killed after the test and as such never get a chance to clean up.
*/
if (is_helper == 0 && arg != NULL && atoi(arg) != 0) {
args[n++] = "valgrind";
args[n++] = "--quiet";
args[n++] = "--leak-check=full";
args[n++] = "--show-reachable=yes";
args[n++] = "--error-exitcode=125";
}

args[n++] = executable_path;
args[n++] = name;
args[n++] = part;
args[n++] = NULL;

dup2(fileno(stdout_file), STDOUT_FILENO);
dup2(fileno(stdout_file), STDERR_FILENO);

char* args[] = { executable_path, name, part, NULL };
execvp(executable_path, args);
execvp(args[0], args);
perror("execvp()");
_exit(127);
}
@@ -24,7 +24,6 @@
#include <malloc.h>
#include <stdio.h>
#include <process.h>
#include <windows.h>

#include "task.h"
#include "runner.h"
@@ -57,7 +56,7 @@ void platform_init(int argc, char **argv) {
}


int process_start(char *name, char *part, process_info_t *p) {
int process_start(char *name, char *part, process_info_t *p, int is_helper) {
HANDLE file = INVALID_HANDLE_VALUE;
HANDLE nul = INVALID_HANDLE_VALUE;
WCHAR path[MAX_PATH], filename[MAX_PATH];
@@ -26,6 +26,7 @@
#pragma warning(disable : 4996)


#include <winsock2.h>
#include <windows.h>
#include <stdio.h>

@@ -24,6 +24,7 @@

#include "runner.h"
#include "task.h"
#include "uv.h"

char executable_path[PATHMAX] = { '\0' };

@@ -147,7 +148,8 @@ int run_test(const char* test, int timeout, int benchmark_output) {

if (process_start(task->task_name,
task->process_name,
&processes[process_count]) == -1) {
&processes[process_count],
1 /* is_helper */) == -1) {
snprintf(errmsg,
sizeof errmsg,
"Process `%s` failed to start.",
@@ -173,7 +175,8 @@ int run_test(const char* test, int timeout, int benchmark_output) {

if (process_start(task->task_name,
task->process_name,
&processes[process_count]) == -1) {
&processes[process_count],
0 /* !is_helper */) == -1) {
snprintf(errmsg,
sizeof errmsg,
"Process `%s` failed to start.",
@@ -291,11 +294,14 @@ int run_test(const char* test, int timeout, int benchmark_output) {
*/
int run_test_part(const char* test, const char* part) {
task_entry_t* task;
int r;

for (task = TASKS; task->main; task++) {
if (strcmp(test, task->task_name) == 0
&& strcmp(part, task->process_name) == 0) {
return task->main();
if (strcmp(test, task->task_name) == 0 &&
strcmp(part, task->process_name) == 0) {
r = task->main();
uv_loop_delete(uv_default_loop());
return r;
}
}

@@ -127,7 +127,7 @@ void platform_init();

/* Invoke "argv[0] test-name [test-part]". Store process info in *p. */
/* Make sure that all stdio output of the processes is buffered up. */
int process_start(char *name, char* part, process_info_t *p);
int process_start(char *name, char* part, process_info_t *p, int is_helper);

/* Wait for all `n` processes in `vec` to terminate. */
/* Time out after `timeout` msec, or never if timeout == -1 */
@@ -114,5 +114,7 @@ TEST_IMPL(async) {
ASSERT(async_cb_called == 3);
ASSERT(close_cb_called == 2);

ASSERT(0 == uv_thread_join(&thread));

return 0;
}
@@ -0,0 +1,173 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

#include "uv.h"
#include "task.h"

#include <string.h>
#include <errno.h>

typedef struct {
uv_mutex_t mutex;
uv_cond_t cond;
int delay;
int use_broadcast;
volatile int posted;
} worker_config;


static void worker(void* arg) {
worker_config* c = arg;

if (c->delay)
uv_sleep(c->delay);

uv_mutex_lock(&c->mutex);
ASSERT(c->posted == 0);
c->posted = 1;
if (c->use_broadcast)
uv_cond_broadcast(&c->cond);
else
uv_cond_signal(&c->cond);
uv_mutex_unlock(&c->mutex);
}


TEST_IMPL(condvar_1) {
uv_thread_t thread;
worker_config wc;

memset(&wc, 0, sizeof(wc));

ASSERT(0 == uv_cond_init(&wc.cond));
ASSERT(0 == uv_mutex_init(&wc.mutex));
ASSERT(0 == uv_thread_create(&thread, worker, &wc));

uv_mutex_lock(&wc.mutex);
uv_sleep(100);
uv_cond_wait(&wc.cond, &wc.mutex);
ASSERT(wc.posted == 1);
uv_mutex_unlock(&wc.mutex);

ASSERT(0 == uv_thread_join(&thread));
uv_mutex_destroy(&wc.mutex);
uv_cond_destroy(&wc.cond);

return 0;
}


TEST_IMPL(condvar_2) {
uv_thread_t thread;
worker_config wc;

memset(&wc, 0, sizeof(wc));
wc.delay = 100;

ASSERT(0 == uv_cond_init(&wc.cond));
ASSERT(0 == uv_mutex_init(&wc.mutex));
ASSERT(0 == uv_thread_create(&thread, worker, &wc));

uv_mutex_lock(&wc.mutex);
uv_cond_wait(&wc.cond, &wc.mutex);
uv_mutex_unlock(&wc.mutex);

ASSERT(0 == uv_thread_join(&thread));
uv_mutex_destroy(&wc.mutex);
uv_cond_destroy(&wc.cond);

return 0;
}


TEST_IMPL(condvar_3) {
uv_thread_t thread;
worker_config wc;
int r;

memset(&wc, 0, sizeof(wc));
wc.delay = 100;

ASSERT(0 == uv_cond_init(&wc.cond));
ASSERT(0 == uv_mutex_init(&wc.mutex));
ASSERT(0 == uv_thread_create(&thread, worker, &wc));

uv_mutex_lock(&wc.mutex);
r = uv_cond_timedwait(&wc.cond, &wc.mutex, (uint64_t)(50 * 1e6));
ASSERT(r == -1);
uv_mutex_unlock(&wc.mutex);

ASSERT(0 == uv_thread_join(&thread));
uv_mutex_destroy(&wc.mutex);
uv_cond_destroy(&wc.cond);

return 0;
}


TEST_IMPL(condvar_4) {
uv_thread_t thread;
worker_config wc;
int r;

memset(&wc, 0, sizeof(wc));
wc.delay = 100;

ASSERT(0 == uv_cond_init(&wc.cond));
ASSERT(0 == uv_mutex_init(&wc.mutex));
ASSERT(0 == uv_thread_create(&thread, worker, &wc));

uv_mutex_lock(&wc.mutex);
r = uv_cond_timedwait(&wc.cond, &wc.mutex, (uint64_t)(150 * 1e6));
ASSERT(r == 0);
uv_mutex_unlock(&wc.mutex);

ASSERT(0 == uv_thread_join(&thread));
uv_mutex_destroy(&wc.mutex);
uv_cond_destroy(&wc.cond);

return 0;
}


TEST_IMPL(condvar_5) {
uv_thread_t thread;
worker_config wc;

memset(&wc, 0, sizeof(wc));
wc.use_broadcast = 1;

ASSERT(0 == uv_cond_init(&wc.cond));
ASSERT(0 == uv_mutex_init(&wc.mutex));
ASSERT(0 == uv_thread_create(&thread, worker, &wc));

uv_mutex_lock(&wc.mutex);
uv_sleep(100);
uv_cond_wait(&wc.cond, &wc.mutex);
ASSERT(wc.posted == 1);
uv_mutex_unlock(&wc.mutex);

ASSERT(0 == uv_thread_join(&thread));
uv_mutex_destroy(&wc.mutex);
uv_cond_destroy(&wc.cond);

return 0;
}
@@ -174,14 +174,13 @@ static void timer_cb_watch_twice(uv_timer_t* handle, int status) {
}

TEST_IMPL(fs_event_watch_dir) {
uv_fs_t fs_req;
uv_loop_t* loop = uv_default_loop();
int r;

/* Setup */
uv_fs_unlink(loop, &fs_req, "watch_dir/file1", NULL);
uv_fs_unlink(loop, &fs_req, "watch_dir/file2", NULL);
uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL);
remove("watch_dir/file2");
remove("watch_dir/file1");
remove("watch_dir/");
create_dir(loop, "watch_dir");

r = uv_fs_event_init(loop, &fs_event, "watch_dir", fs_event_cb_dir, 0);
@@ -198,22 +197,21 @@ TEST_IMPL(fs_event_watch_dir) {
ASSERT(close_cb_called == 2);

/* Cleanup */
r = uv_fs_unlink(loop, &fs_req, "watch_dir/file1", NULL);
r = uv_fs_unlink(loop, &fs_req, "watch_dir/file2", NULL);
r = uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL);
remove("watch_dir/file2");
remove("watch_dir/file1");
remove("watch_dir/");

return 0;
}

TEST_IMPL(fs_event_watch_file) {
uv_fs_t fs_req;
uv_loop_t* loop = uv_default_loop();
int r;

/* Setup */
uv_fs_unlink(loop, &fs_req, "watch_dir/file1", NULL);
uv_fs_unlink(loop, &fs_req, "watch_dir/file2", NULL);
uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL);
remove("watch_dir/file2");
remove("watch_dir/file1");
remove("watch_dir/");
create_dir(loop, "watch_dir");
create_file(loop, "watch_dir/file1");
create_file(loop, "watch_dir/file2");
@@ -232,9 +230,9 @@ TEST_IMPL(fs_event_watch_file) {
ASSERT(close_cb_called == 2);

/* Cleanup */
r = uv_fs_unlink(loop, &fs_req, "watch_dir/file1", NULL);
r = uv_fs_unlink(loop, &fs_req, "watch_dir/file2", NULL);
r = uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL);
remove("watch_dir/file2");
remove("watch_dir/file1");
remove("watch_dir/");

return 0;
}
@@ -260,13 +258,12 @@ TEST_IMPL(fs_event_watch_file_twice) {
TEST_IMPL(fs_event_watch_file_current_dir) {
uv_timer_t timer;
uv_loop_t* loop;
uv_fs_t fs_req;
int r;

loop = uv_default_loop();

/* Setup */
uv_fs_unlink(loop, &fs_req, "watch_file", NULL);
remove("watch_file");
create_file(loop, "watch_file");

r = uv_fs_event_init(loop, &fs_event, "watch_file",
@@ -290,19 +287,19 @@ TEST_IMPL(fs_event_watch_file_current_dir) {
ASSERT(close_cb_called == 1);

/* Cleanup */
r = uv_fs_unlink(loop, &fs_req, "watch_file", NULL);
remove("watch_file");

return 0;
}


TEST_IMPL(fs_event_no_callback_on_close) {
uv_fs_t fs_req;
uv_loop_t* loop = uv_default_loop();
int r;

/* Setup */
uv_fs_unlink(loop, &fs_req, "watch_dir/file1", NULL);
uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL);
remove("watch_dir/file1");
remove("watch_dir/");
create_dir(loop, "watch_dir");
create_file(loop, "watch_dir/file1");

@@ -321,8 +318,8 @@ TEST_IMPL(fs_event_no_callback_on_close) {
ASSERT(close_cb_called == 1);

/* Cleanup */
r = uv_fs_unlink(loop, &fs_req, "watch_dir/file1", NULL);
r = uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL);
remove("watch_dir/file1");
remove("watch_dir/");

return 0;
}
@@ -370,7 +367,6 @@ TEST_IMPL(fs_event_immediate_close) {

TEST_IMPL(fs_event_close_with_pending_event) {
uv_loop_t* loop;
uv_fs_t fs_req;
int r;

loop = uv_default_loop();
@@ -391,10 +387,8 @@ TEST_IMPL(fs_event_close_with_pending_event) {
ASSERT(close_cb_called == 1);

/* Clean up */
r = uv_fs_unlink(loop, &fs_req, "watch_dir/file", NULL);
ASSERT(r == 0);
r = uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL);
ASSERT(r == 0);
remove("watch_dir/file");
remove("watch_dir/");

return 0;
}
@@ -427,7 +421,6 @@ static void fs_event_cb_close(uv_fs_event_t* handle, const char* filename,

TEST_IMPL(fs_event_close_in_callback) {
uv_loop_t* loop;
uv_fs_t fs_req;
int r;

loop = uv_default_loop();
@@ -455,18 +448,12 @@ TEST_IMPL(fs_event_close_in_callback) {
ASSERT(fs_event_cb_called == 3);

/* Clean up */
r = uv_fs_unlink(loop, &fs_req, "watch_dir/file1", NULL);
ASSERT(r == 0);
r = uv_fs_unlink(loop, &fs_req, "watch_dir/file2", NULL);
ASSERT(r == 0);
r = uv_fs_unlink(loop, &fs_req, "watch_dir/file3", NULL);
ASSERT(r == 0);
r = uv_fs_unlink(loop, &fs_req, "watch_dir/file4", NULL);
ASSERT(r == 0);
r = uv_fs_unlink(loop, &fs_req, "watch_dir/file5", NULL);
ASSERT(r == 0);
r = uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL);
ASSERT(r == 0);
remove("watch_dir/file1");
remove("watch_dir/file2");
remove("watch_dir/file3");
remove("watch_dir/file4");
remove("watch_dir/file5");
remove("watch_dir/");

return 0;
}
@@ -140,7 +140,6 @@ TEST_IMPL(fs_poll) {
ASSERT(poll_cb_called == 5);
ASSERT(timer_cb_called == 2);
ASSERT(close_cb_called == 1);
uv_loop_delete(loop);

return 0;
}
@@ -53,6 +53,7 @@ typedef struct {
} utime_check_t;


static int dummy_cb_count;
static int close_cb_count;
static int create_cb_count;
static int open_cb_count;
@@ -127,6 +128,12 @@ void check_permission(const char* filename, int mode) {
}


static void dummy_cb(uv_fs_t* req) {
(void) req;
dummy_cb_count++;
}


static void link_cb(uv_fs_t* req) {
ASSERT(req->fs_type == UV_FS_LINK);
ASSERT(req->result == 0);
@@ -787,15 +794,15 @@ TEST_IMPL(fs_async_dir) {
ASSERT(r == 0);
uv_run(loop);

r = uv_fs_stat(loop, &stat_req, "test_dir\\", stat_cb);
r = uv_fs_stat(loop, &stat_req, "test_dir/", stat_cb);
ASSERT(r == 0);
uv_run(loop);

r = uv_fs_lstat(loop, &stat_req, "test_dir", stat_cb);
ASSERT(r == 0);
uv_run(loop);

r = uv_fs_lstat(loop, &stat_req, "test_dir\\", stat_cb);
r = uv_fs_lstat(loop, &stat_req, "test_dir/", stat_cb);
ASSERT(r == 0);
uv_run(loop);

@@ -1183,6 +1190,28 @@ TEST_IMPL(fs_link) {
}


TEST_IMPL(fs_readlink) {
uv_fs_t req;

loop = uv_default_loop();
ASSERT(0 == uv_fs_readlink(loop, &req, "no_such_file", dummy_cb));
ASSERT(0 == uv_run(loop));
ASSERT(dummy_cb_count == 1);
ASSERT(req.ptr == NULL);
ASSERT(req.result == -1);
ASSERT(req.errorno == UV_ENOENT);
uv_fs_req_cleanup(&req);

ASSERT(-1 == uv_fs_readlink(loop, &req, "no_such_file", NULL));
ASSERT(req.ptr == NULL);
ASSERT(req.result == -1);
ASSERT(req.errorno == UV_ENOENT);
uv_fs_req_cleanup(&req);

return 0;
}


TEST_IMPL(fs_symlink) {
int r;
uv_fs_t req;
@@ -1251,6 +1280,8 @@ TEST_IMPL(fs_symlink) {

r = uv_fs_symlink(loop, &req, "test_file_symlink", "test_file_symlink_symlink", 0, NULL);
ASSERT(r != -1);
uv_fs_req_cleanup(&req);

r = uv_fs_readlink(loop, &req, "test_file_symlink_symlink", NULL);
ASSERT(r != -1);
ASSERT(strcmp(req.ptr, "test_file_symlink") == 0);
@@ -1278,6 +1309,8 @@ TEST_IMPL(fs_symlink) {

r = uv_fs_symlink(loop, &req, "test_file_symlink2", "test_file_symlink2_symlink", 0, NULL);
ASSERT(r != -1);
uv_fs_req_cleanup(&req);

r = uv_fs_readlink(loop, &req, "test_file_symlink2_symlink", readlink_cb);
ASSERT(r != -1);
uv_run(loop);
@@ -1608,6 +1641,7 @@ TEST_IMPL(fs_readdir_file) {
r = uv_fs_readdir(loop, &readdir_req, path, 0, NULL);
ASSERT(r == -1);
ASSERT(uv_last_error(loop).code == UV_ENOTDIR);
uv_fs_req_cleanup(&readdir_req);

r = uv_fs_readdir(loop, &readdir_req, path, 0, file_readdir_cb);
ASSERT(r == 0);
@@ -238,9 +238,9 @@ static void udp_recv(uv_udp_t* handle,
int r;

ASSERT(nread >= 0);
free(buf.base);

if (nread == 0) {
free(buf.base);
return;
}

@@ -22,6 +22,11 @@
TEST_DECLARE (platform_output)
TEST_DECLARE (callback_order)
TEST_DECLARE (run_once)
TEST_DECLARE (condvar_1)
TEST_DECLARE (condvar_2)
TEST_DECLARE (condvar_3)
TEST_DECLARE (condvar_4)
TEST_DECLARE (condvar_5)
TEST_DECLARE (semaphore_1)
TEST_DECLARE (semaphore_2)
TEST_DECLARE (semaphore_3)
@@ -152,6 +157,7 @@ TEST_DECLARE (fs_fstat)
TEST_DECLARE (fs_chmod)
TEST_DECLARE (fs_chown)
TEST_DECLARE (fs_link)
TEST_DECLARE (fs_readlink)
TEST_DECLARE (fs_symlink)
TEST_DECLARE (fs_symlink_dir)
TEST_DECLARE (fs_utime)
@@ -207,6 +213,11 @@ TASK_LIST_START
TEST_ENTRY (callback_order)
#endif
TEST_ENTRY (run_once)
TEST_ENTRY (condvar_1)
TEST_ENTRY (condvar_2)
TEST_ENTRY (condvar_3)
TEST_ENTRY (condvar_4)
TEST_ENTRY (condvar_5)
TEST_ENTRY (semaphore_1)
TEST_ENTRY (semaphore_2)
TEST_ENTRY (semaphore_3)
@@ -405,6 +416,7 @@ TASK_LIST_START
TEST_ENTRY (fs_chown)
TEST_ENTRY (fs_utime)
TEST_ENTRY (fs_futime)
TEST_ENTRY (fs_readlink)
TEST_ENTRY (fs_symlink)
TEST_ENTRY (fs_symlink_dir)
TEST_ENTRY (fs_stat_missing_path)
@@ -52,10 +52,7 @@ void pinger_try_read(pinger_t* pinger);


static uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
uv_buf_t buf;
buf.base = (char*)malloc(size);
buf.len = size;
return buf;
return uv_buf_init(malloc(size), size);
}


@@ -103,10 +100,7 @@ static void pinger_read_cb(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) {
ASSERT(uv_last_error(uv_default_loop()).code == UV_EOF);

puts("got EOF");

if (buf.base) {
free(buf.base);
}
free(buf.base);

uv_close((uv_handle_t*)(&pinger->stream.tcp), pinger_on_close);

@@ -117,17 +111,22 @@ static void pinger_read_cb(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) {
for (i = 0; i < nread; i++) {
ASSERT(buf.base[i] == PING[pinger->state]);
pinger->state = (pinger->state + 1) % (sizeof(PING) - 1);
if (pinger->state == 0) {
printf("PONG %d\n", pinger->pongs);
pinger->pongs++;
if (pinger->pongs < NUM_PINGS) {
pinger_write_ping(pinger);
} else {
uv_close((uv_handle_t*)(&pinger->stream.tcp), pinger_on_close);
return;
}

if (pinger->state != 0)
continue;

printf("PONG %d\n", pinger->pongs);
pinger->pongs++;

if (pinger->pongs < NUM_PINGS) {
pinger_write_ping(pinger);
} else {
uv_close((uv_handle_t*)(&pinger->stream.tcp), pinger_on_close);
break;
}
}

free(buf.base);
}


@@ -36,6 +36,21 @@ static int req_cb_called;
static int connect_cb_called;
static int write_cb_called;
static int shutdown_cb_called;
static int close_cb_called;


static void close_cb(uv_handle_t* handle) {
close_cb_called++;
}


static void do_close(void* handle) {
close_cb_called = 0;
uv_close((uv_handle_t*)handle, close_cb);
ASSERT(close_cb_called == 0);
uv_run(uv_default_loop());
ASSERT(close_cb_called == 1);
}


static void fail_cb(void) {
@@ -91,6 +106,7 @@ TEST_IMPL(idle_ref) {
uv_idle_start(&h, NULL);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -100,6 +116,7 @@ TEST_IMPL(async_ref) {
uv_async_init(uv_default_loop(), &h, NULL);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -110,6 +127,7 @@ TEST_IMPL(prepare_ref) {
uv_prepare_start(&h, NULL);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -120,6 +138,7 @@ TEST_IMPL(check_ref) {
uv_check_start(&h, NULL);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -136,6 +155,7 @@ TEST_IMPL(unref_in_prepare_cb) {
uv_prepare_init(uv_default_loop(), &h);
uv_prepare_start(&h, prepare_cb);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -145,6 +165,7 @@ TEST_IMPL(timer_ref) {
uv_timer_init(uv_default_loop(), &h);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -155,6 +176,7 @@ TEST_IMPL(timer_ref2) {
uv_timer_start(&h, (uv_timer_cb)fail_cb, 42, 42);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -164,6 +186,7 @@ TEST_IMPL(fs_event_ref) {
uv_fs_event_init(uv_default_loop(), &h, ".", (uv_fs_event_cb)fail_cb, 0);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -174,6 +197,7 @@ TEST_IMPL(fs_poll_ref) {
uv_fs_poll_start(&h, NULL, ".", 999);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -183,6 +207,7 @@ TEST_IMPL(tcp_ref) {
uv_tcp_init(uv_default_loop(), &h);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -193,6 +218,7 @@ TEST_IMPL(tcp_ref2) {
uv_listen((uv_stream_t*)&h, 128, (uv_connection_cb)fail_cb);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -206,6 +232,7 @@ TEST_IMPL(tcp_ref3) {
uv_run(uv_default_loop());
ASSERT(connect_cb_called == 1);
ASSERT(shutdown_cb_called == 1);
do_close(&h);
return 0;
}

@@ -220,6 +247,7 @@ TEST_IMPL(tcp_ref4) {
ASSERT(connect_cb_called == 1);
ASSERT(write_cb_called == 1);
ASSERT(shutdown_cb_called == 1);
do_close(&h);
return 0;
}

@@ -229,6 +257,7 @@ TEST_IMPL(udp_ref) {
uv_udp_init(uv_default_loop(), &h);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -241,6 +270,7 @@ TEST_IMPL(udp_ref2) {
uv_udp_recv_start(&h, (uv_alloc_cb)fail_cb, (uv_udp_recv_cb)fail_cb);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -256,6 +286,7 @@ TEST_IMPL(udp_ref3) {
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
ASSERT(req_cb_called == 1);
do_close(&h);

return 0;
}
@@ -266,6 +297,7 @@ TEST_IMPL(pipe_ref) {
uv_pipe_init(uv_default_loop(), &h, 0);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -276,6 +308,7 @@ TEST_IMPL(pipe_ref2) {
uv_listen((uv_stream_t*)&h, 128, (uv_connection_cb)fail_cb);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
do_close(&h);
return 0;
}

@@ -288,6 +321,7 @@ TEST_IMPL(pipe_ref3) {
uv_run(uv_default_loop());
ASSERT(connect_cb_called == 1);
ASSERT(shutdown_cb_called == 1);
do_close(&h);
return 0;
}

@@ -301,6 +335,7 @@ TEST_IMPL(pipe_ref4) {
ASSERT(connect_cb_called == 1);
ASSERT(write_cb_called == 1);
ASSERT(shutdown_cb_called == 1);
do_close(&h);
return 0;
}

@@ -334,5 +369,7 @@ TEST_IMPL(process_ref) {
r = uv_process_kill(&h, /* SIGTERM */ 15);
ASSERT(r == 0);

do_close(&h);

return 0;
}
@@ -145,7 +145,7 @@ TEST_IMPL(tcp_writealot) {
uv_tcp_t client;
int r;

send_buffer = malloc(TOTAL_BYTES);
send_buffer = calloc(1, TOTAL_BYTES);
ASSERT(send_buffer != NULL);

r = uv_tcp_init(uv_default_loop(), &client);
@@ -6,7 +6,6 @@
'_LARGEFILE_SOURCE',
'_FILE_OFFSET_BITS=64',
'_GNU_SOURCE',
'EIO_STACKSIZE=262144'
],
'conditions': [
['OS=="solaris"', {
@@ -53,7 +52,6 @@
[ 'OS=="win"', {
'defines': [
'_WIN32_WINNT=0x0600',
'EIO_STACKSIZE=262144',
'_GNU_SOURCE',
],
'sources': [
@@ -108,7 +106,6 @@
'-Wno-unused-parameter'
],
'sources': [
'include/uv-private/eio.h',
'include/uv-private/ev.h',
'include/uv-private/uv-unix.h',
'include/uv-private/uv-linux.h',
@@ -118,15 +115,13 @@
'src/unix/async.c',
'src/unix/core.c',
'src/unix/dl.c',
'src/unix/eio/ecb.h',
'src/unix/eio/eio.c',
'src/unix/eio/xthread.h',
'src/unix/error.c',
'src/unix/ev/ev.c',
'src/unix/ev/ev_vars.h',
'src/unix/ev/ev_wrap.h',
'src/unix/ev/event.h',
'src/unix/fs.c',
'src/unix/getaddrinfo.c',
'src/unix/internal.h',
'src/unix/loop.c',
'src/unix/loop-watcher.c',
@@ -137,11 +132,10 @@
'src/unix/stream.c',
'src/unix/tcp.c',
'src/unix/thread.c',
'src/unix/threadpool.c',
'src/unix/timer.c',
'src/unix/tty.c',
'src/unix/udp.c',
'src/unix/uv-eio.c',
'src/unix/uv-eio.h',
],
'include_dirs': [ 'src/unix/ev', ],
'libraries': [ '-lm' ]
@@ -156,7 +150,6 @@
'defines': [
'_DARWIN_USE_64_BIT_INODE=1',
'EV_CONFIG_H="config_darwin.h"',
'EIO_CONFIG_H="config_darwin.h"',
]
}],
[ 'OS=="linux"', {
@@ -168,7 +161,6 @@
],
'defines': [
'EV_CONFIG_H="config_linux.h"',
'EIO_CONFIG_H="config_linux.h"',
],
'direct_dependent_settings': {
'libraries': [ '-lrt' ],
@@ -180,13 +172,13 @@
'__EXTENSIONS__',
'_XOPEN_SOURCE=500',
'EV_CONFIG_H="config_sunos.h"',
'EIO_CONFIG_H="config_sunos.h"',
],
'direct_dependent_settings': {
'libraries': [
'-lkstat',
'-lsocket',
'-lnsl',
'-lsendfile',
'-lsocket',
],
},
}],
@@ -197,7 +189,6 @@
'_ALL_SOURCE',
'_XOPEN_SOURCE=500',
'EV_CONFIG_H="config_aix.h"',
'EIO_CONFIG_H="config_aix.h"',
],
'direct_dependent_settings': {
'libraries': [
@@ -209,7 +200,6 @@
'sources': [ 'src/unix/freebsd.c' ],
'defines': [
'EV_CONFIG_H="config_freebsd.h"',
'EIO_CONFIG_H="config_freebsd.h"',
],
'direct_dependent_settings': {
'libraries': [
@@ -221,14 +211,12 @@
'sources': [ 'src/unix/openbsd.c' ],
'defines': [
'EV_CONFIG_H="config_openbsd.h"',
'EIO_CONFIG_H="config_openbsd.h"',
],
}],
[ 'OS=="netbsd"', {
'sources': [ 'src/unix/netbsd.c' ],
'defines': [
'EV_CONFIG_H="config_netbsd.h"',
'EIO_CONFIG_H="config_netbsd.h"',
],
'direct_dependent_settings': {
'libraries': [
@@ -239,6 +227,9 @@
[ 'OS=="mac" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd"', {
'sources': [ 'src/unix/kqueue.c' ],
}],
['library=="shared_library"', {
'defines': [ 'BUILDING_UV_SHARED=1' ]
}]
]
},

@@ -314,6 +305,7 @@
'test/test-mutexes.c',
'test/test-signal.c',
'test/test-thread.c',
'test/test-condvar.c',
'test/test-timer-again.c',
'test/test-timer.c',
'test/test-tty.c',
@@ -17,6 +17,10 @@ set target=Build
set noprojgen=
set nobuild=
set run=
set target_arch=ia32
set vs_toolset=x86
set platform=WIN32
set library=static_library

:next-arg
if "%1"=="" goto args-done
@@ -27,11 +31,36 @@ if /i "%1"=="bench" set run=run-benchmarks.exe&goto arg-ok
if /i "%1"=="clean" set target=Clean&goto arg-ok
if /i "%1"=="noprojgen" set noprojgen=1&goto arg-ok
if /i "%1"=="nobuild" set nobuild=1&goto arg-ok
if /i "%1"=="x86" set target_arch=ia32&set platform=WIN32&set vs_toolset=x86&goto arg-ok
if /i "%1"=="ia32" set target_arch=ia32&set platform=WIN32&set vs_toolset=x86&goto arg-ok
if /i "%1"=="x64" set target_arch=x64&set platform=amd64&set vs_toolset=x64&goto arg-ok
if /i "%1"=="shared" set library=shared_library&goto arg-ok
if /i "%1"=="static" set library=static_library&goto arg-ok
:arg-ok
shift
goto next-arg
:args-done

@rem Look for Visual Studio 2010
if not defined VS100COMNTOOLS goto vc-set-2008
if not exist "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2008
call "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset%
set GYP_MSVS_VERSION=2010
goto select-target

:vc-set-2008
@rem Look for Visual Studio 2008
if not defined VS90COMNTOOLS goto vc-set-notfound
if not exist "%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-notfound
call "%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset%
echo Warning: building with Visual Studio 2008 is currently not supported.
set GYP_MSVS_VERSION=2008
goto select-target

:vc-set-notfound
echo Warning: Visual Studio not found

:select-target
if not "%config%"=="" goto project-gen
if "%run%"=="run-tests.exe" set config=Debug& goto project-gen
if "%run%"=="run-benchmarks.exe" set config=Release& goto project-gen
@@ -42,20 +71,19 @@ set config=Debug
if defined noprojgen goto msbuild

@rem Generate the VS project.

if exist build\gyp goto have_gyp
echo svn co http://gyp.googlecode.com/svn/trunk@983 build/gyp
svn co http://gyp.googlecode.com/svn/trunk@983 build/gyp
if errorlevel 1 goto gyp_install_failed
goto have_gyp

:gyp_install_failed
echo Failed to download gyp. Make sure you have subversion installed, or
echo Failed to download gyp. Make sure you have subversion installed, or
echo manually install gyp into %~dp0build\gyp.
goto exit

:have_gyp
python gyp_uv
python gyp_uv -Dtarget_arch=%target_arch% -Dlibrary=%library%
if errorlevel 1 goto create-msvs-files-failed
if not exist uv.sln goto create-msvs-files-failed
echo Project files generated.
@@ -64,12 +92,7 @@ echo Project files generated.
@rem Skip project generation if requested.
if defined nobuild goto run

@rem If not running in the VS build env, try to start it. If that fails, bail
@rem out.
if defined VCINSTALLDIR goto msbuild-found
if not defined VS100COMNTOOLS goto msbuild-not-found
if not exist "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" goto msbuild-not-found
call "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat"
@rem Check if VS build env is available
if not defined VCINSTALLDIR goto msbuild-not-found
goto msbuild-found

@@ -79,7 +102,7 @@ goto run

@rem Build the sln with msbuild.
:msbuild-found
msbuild uv.sln /t:%target% /p:Configuration=%config% /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo
msbuild uv.sln /t:%target% /p:Configuration=%config% /p:Platform="%platform%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo
if errorlevel 1 goto exit

:run
@@ -91,11 +114,11 @@ echo running '%config%\%run%'
goto exit

:create-msvs-files-failed
echo Failed to create vc project files.
echo Failed to create vc project files.
goto exit

:help
echo vcbuild.bat [debug/release] [test/bench] [clean] [noprojgen] [nobuild]
echo vcbuild.bat [debug/release] [test/bench] [clean] [noprojgen] [nobuild] [x86/x64] [static/shared]
echo Examples:
echo vcbuild.bat : builds debug build
echo vcbuild.bat test : builds debug build and runs tests