OBJS += src/unix/cares.o
OBJS += src/unix/udp.o
OBJS += src/unix/error.o
+OBJS += src/unix/thread.o
OBJS += src/unix/process.o
OBJS += src/unix/tcp.o
OBJS += src/unix/pipe.o
#include <arpa/inet.h>
#include <netdb.h>
#include <termios.h>
+#include <pthread.h>
/* Note: May be cast to struct iovec. See writev(2). */
typedef struct {
typedef int uv_file;
+typedef pthread_mutex_t uv_mutex_t;
+typedef pthread_rwlock_t uv_rwlock_t;
+
/* Platform-specific definitions for uv_dlopen support. */
typedef void* uv_lib_t;
#define UV_DYNAMIC /* empty */
typedef int uv_file;
+typedef CRITICAL_SECTION uv_mutex_t;
+
+typedef union {
+ SRWLOCK srwlock_;
+ struct {
+ uv_mutex_t read_mutex_;
+ uv_mutex_t write_mutex_;
+ unsigned int num_readers_;
+ } fallback_;
+} uv_rwlock_t;
+
/* Platform-specific definitions for uv_dlopen support. */
typedef HMODULE uv_lib_t;
#define UV_DYNAMIC FAR WINAPI
*/
UV_EXTERN uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr);
+UV_EXTERN int uv_mutex_init(uv_mutex_t* handle);
+UV_EXTERN void uv_mutex_destroy(uv_mutex_t* handle);
+UV_EXTERN void uv_mutex_lock(uv_mutex_t* handle);
+UV_EXTERN int uv_mutex_trylock(uv_mutex_t* handle);
+UV_EXTERN void uv_mutex_unlock(uv_mutex_t* handle);
+
+UV_EXTERN int uv_rwlock_init(uv_rwlock_t* rwlock);
+UV_EXTERN void uv_rwlock_destroy(uv_rwlock_t* rwlock);
+UV_EXTERN void uv_rwlock_rdlock(uv_rwlock_t* rwlock);
+UV_EXTERN int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock);
+UV_EXTERN void uv_rwlock_rdunlock(uv_rwlock_t* rwlock);
+UV_EXTERN void uv_rwlock_wrlock(uv_rwlock_t* rwlock);
+UV_EXTERN int uv_rwlock_trywrlock(uv_rwlock_t* rwlock);
+UV_EXTERN void uv_rwlock_wrunlock(uv_rwlock_t* rwlock);
/* the presence of these unions force similar struct layout */
union uv_any_handle {
assert(sockfd >= 0);
while (1) {
-#if HAVE_ACCEPT4
- peerfd = accept4(sockfd, saddr, &slen, SOCK_NONBLOCK | SOCK_CLOEXEC);
+#if HAVE_SYS_ACCEPT4
+ peerfd = sys_accept4(sockfd, saddr, &slen, SOCK_NONBLOCK | SOCK_CLOEXEC);
if (peerfd != -1)
break;
#include <stddef.h> /* offsetof */
#undef HAVE_FUTIMES
-#undef HAVE_PIPE2
-#undef HAVE_ACCEPT4
#undef HAVE_KQUEUE
#undef HAVE_PORTS_FS
#if defined(__linux__)
-#include <linux/version.h>
-#include <features.h>
+# undef HAVE_SYS_UTIMESAT
+# undef HAVE_SYS_PIPE2
+# undef HAVE_SYS_ACCEPT4
-/* futimes() requires linux >= 2.6.22 and glib >= 2.6 */
-#if LINUX_VERSION_CODE >= 0x20616 && __GLIBC_PREREQ(2, 6)
-#define HAVE_FUTIMES 1
-#endif
+# undef _GNU_SOURCE
+# define _GNU_SOURCE
-/* pipe2() requires linux >= 2.6.27 and glibc >= 2.9 */
-#if LINUX_VERSION_CODE >= 0x2061B && __GLIBC_PREREQ(2, 9)
-#define HAVE_PIPE2 1
-#endif
+# include <linux/version.h>
+# include <sys/syscall.h>
+# include <features.h>
+# include <unistd.h>
-/* accept4() requires linux >= 2.6.28 and glib >= 2.10 */
-#if LINUX_VERSION_CODE >= 0x2061C && __GLIBC_PREREQ(2, 10)
-#define HAVE_ACCEPT4 1
-#endif
+# if __NR_utimensat
+# define HAVE_SYS_UTIMESAT 1
+# endif
+# if __NR_pipe2
+# define HAVE_SYS_PIPE2 1
+# endif
+# if __NR_accept4
+# define HAVE_SYS_ACCEPT4 1
+# endif
+
+# if HAVE_SYS_UTIMESAT
+inline static int sys_utimesat(int dirfd,
+ const char* path,
+ const struct timespec times[2],
+ int flags)
+{
+ return syscall(__NR_utimensat, dirfd, path, times, flags);
+}
+inline static int sys_futimes(int fd, const struct timeval times[2])
+{
+ struct timespec ts[2];
+ ts[0].tv_sec = times[0].tv_sec, ts[0].tv_nsec = times[0].tv_usec * 1000;
+ ts[1].tv_sec = times[1].tv_sec, ts[1].tv_nsec = times[1].tv_usec * 1000;
+ return sys_utimesat(fd, NULL, ts, 0);
+}
+# undef HAVE_FUTIMES
+# define HAVE_FUTIMES 1
+# define futimes(fd, times) sys_futimes(fd, times)
+# endif /* HAVE_SYS_FUTIMESAT */
+
+# if HAVE_SYS_PIPE2
+inline static int sys_pipe2(int pipefd[2], int flags)
+{
+ return syscall(__NR_pipe2, pipefd, flags);
+}
+# endif /* HAVE_SYS_PIPE2 */
+
+# if HAVE_SYS_ACCEPT4
+inline static int sys_accept4(int fd,
+ struct sockaddr* addr,
+ socklen_t* addrlen,
+ int flags)
+{
+ return syscall(__NR_accept4, fd, addr, addrlen, flags);
+}
+# endif /* HAVE_SYS_ACCEPT4 */
#endif /* __linux__ */
void uv__fs_event_destroy(uv_fs_event_t* handle) {
+ uv__fs_event_stop(handle);
free(handle->filename);
uv__close(handle->fd);
handle->fd = -1;
static int uv__make_pipe(int fds[2], int flags) {
-#if HAVE_PIPE2
+#if HAVE_SYS_PIPE2
int fl;
fl = O_CLOEXEC;
if (flags & UV__F_NONBLOCK)
fl |= O_NONBLOCK;
- if (pipe2(fds, fl) == 0)
+ if (sys_pipe2(fds, fl) == 0)
return 0;
if (errno != ENOSYS)
req = ngx_queue_data(q, uv_write_t, queue);
if (req->cb) {
- uv__set_sys_error(stream->loop, req->error);
+ uv__set_artificial_error(stream->loop, req->error);
req->cb(req, req->error ? -1 : 0);
}
}
/* NOTE: call callback AFTER freeing the request data. */
if (req->cb) {
- uv__set_sys_error(stream->loop, req->error);
+ uv__set_artificial_error(stream->loop, req->error);
req->cb(req, req->error ? -1 : 0);
}
--- /dev/null
+/* 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 "internal.h"
+
+#include <pthread.h>
+#include <errno.h>
+
+
+#ifdef NDEBUG
+# define CHECK(r) ((void) (r))
+#else
+# include <stdio.h>
+# include <stdlib.h>
+# define CHECK(r) \
+ do { \
+ int __r = (r); \
+ if (__r) errno = __r, perror(#r), abort(); \
+ } \
+ while (0)
+#endif
+
+
+int uv_mutex_init(uv_mutex_t* mutex) {
+ if (pthread_mutex_init(mutex, NULL))
+ return -1;
+ else
+ return 0;
+}
+
+
+void uv_mutex_destroy(uv_mutex_t* mutex) {
+ CHECK(pthread_mutex_destroy(mutex));
+}
+
+
+void uv_mutex_lock(uv_mutex_t* mutex) {
+ CHECK(pthread_mutex_lock(mutex));
+}
+
+
+int uv_mutex_trylock(uv_mutex_t* mutex) {
+ int r;
+
+ r = pthread_mutex_trylock(mutex);
+
+ if (r && r != EAGAIN)
+ CHECK(r);
+
+ if (r)
+ return -1;
+ else
+ return 0;
+}
+
+
+void uv_mutex_unlock(uv_mutex_t* mutex) {
+ CHECK(pthread_mutex_unlock(mutex));
+}
+
+
+int uv_rwlock_init(uv_rwlock_t* rwlock) {
+ if (pthread_rwlock_init(rwlock, NULL))
+ return -1;
+ else
+ return 0;
+}
+
+
+void uv_rwlock_destroy(uv_rwlock_t* rwlock) {
+ CHECK(pthread_rwlock_destroy(rwlock));
+}
+
+
+void uv_rwlock_rdlock(uv_rwlock_t* rwlock) {
+ CHECK(pthread_rwlock_rdlock(rwlock));
+}
+
+
+int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
+ int r;
+
+ r = pthread_rwlock_tryrdlock(rwlock);
+
+ if (r && r != EAGAIN)
+ CHECK(r);
+
+ if (r)
+ return -1;
+ else
+ return 0;
+}
+
+
+void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {
+ CHECK(pthread_rwlock_unlock(rwlock));
+}
+
+
+void uv_rwlock_wrlock(uv_rwlock_t* rwlock) {
+ CHECK(pthread_rwlock_wrlock(rwlock));
+}
+
+
+int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
+ int r;
+
+ r = pthread_rwlock_trywrlock(rwlock);
+
+ if (r && r != EAGAIN)
+ CHECK(r);
+
+ if (r)
+ return -1;
+ else
+ return 0;
+}
+
+
+void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {
+ CHECK(pthread_rwlock_unlock(rwlock));
+}
if (GetConsoleMode(handle, &mode)) {
return UV_TTY;
} else {
- return UV_UNKNOWN_HANDLE;
+ return UV_FILE;
}
case FILE_TYPE_PIPE:
--- /dev/null
+/* 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 "../uv-common.h"
+#include "internal.h"
+#include <assert.h>
+
+#define HAVE_SRWLOCK_API() (pTryAcquireSRWLockShared != NULL)
+
+#ifdef _MSC_VER /* msvc */
+# define inline __inline
+# define NOINLINE __declspec (noinline)
+#else /* gcc */
+# define inline inline
+# define NOINLINE __attribute__ ((noinline))
+#endif
+
+
+inline static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock);
+inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock);
+inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock);
+
+inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock);
+inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock);
+inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock);
+
+
+static NOINLINE void uv__once_inner(uv_once_t* guard,
+ void (*callback)(void)) {
+ DWORD result;
+ HANDLE existing_event, created_event;
+ HANDLE* event_ptr;
+
+ /* Fetch and align event_ptr */
+ event_ptr = (HANDLE*) (((uintptr_t) &guard->event + (sizeof(HANDLE) - 1)) &
+ ~(sizeof(HANDLE) - 1));
+
+ created_event = CreateEvent(NULL, 1, 0, NULL);
+ if (created_event == 0) {
+ /* Could fail in a low-memory situation? */
+ uv_fatal_error(GetLastError(), "CreateEvent");
+ }
+
+ existing_event = InterlockedCompareExchangePointer(event_ptr,
+ created_event,
+ NULL);
+
+ if (existing_event == NULL) {
+ /* We won the race */
+ callback();
+
+ result = SetEvent(created_event);
+ assert(result);
+ guard->ran = 1;
+
+ } else {
+ /* We lost the race. Destroy the event we created and wait for the */
+ /* existing one to become signaled. */
+ CloseHandle(created_event);
+ result = WaitForSingleObject(existing_event, INFINITE);
+ assert(result == WAIT_OBJECT_0);
+ }
+}
+
+
+void uv_once(uv_once_t* guard, void (*callback)(void)) {
+ /* Fast case - avoid WaitForSingleObject. */
+ if (guard->ran) {
+ return;
+ }
+
+ uv__once_inner(guard, callback);
+}
+
+int uv_mutex_init(uv_mutex_t* mutex) {
+ InitializeCriticalSection(mutex);
+ return 0;
+}
+
+
+void uv_mutex_destroy(uv_mutex_t* mutex) {
+ DeleteCriticalSection(mutex);
+}
+
+
+void uv_mutex_lock(uv_mutex_t* mutex) {
+ EnterCriticalSection(mutex);
+}
+
+
+int uv_mutex_trylock(uv_mutex_t* mutex) {
+ if (TryEnterCriticalSection(mutex))
+ return 0;
+ else
+ return -1;
+}
+
+
+void uv_mutex_unlock(uv_mutex_t* mutex) {
+ LeaveCriticalSection(mutex);
+}
+
+
+int uv_rwlock_init(uv_rwlock_t* rwlock) {
+ if (HAVE_SRWLOCK_API())
+ return uv__rwlock_srwlock_init(rwlock);
+ else
+ return uv__rwlock_fallback_init(rwlock);
+}
+
+
+void uv_rwlock_destroy(uv_rwlock_t* rwlock) {
+ if (HAVE_SRWLOCK_API())
+ uv__rwlock_srwlock_destroy(rwlock);
+ else
+ uv__rwlock_fallback_destroy(rwlock);
+}
+
+
+void uv_rwlock_rdlock(uv_rwlock_t* rwlock) {
+ if (HAVE_SRWLOCK_API())
+ uv__rwlock_srwlock_rdlock(rwlock);
+ else
+ uv__rwlock_fallback_rdlock(rwlock);
+}
+
+
+int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
+ if (HAVE_SRWLOCK_API())
+ return uv__rwlock_srwlock_tryrdlock(rwlock);
+ else
+ return uv__rwlock_fallback_tryrdlock(rwlock);
+}
+
+
+void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {
+ if (HAVE_SRWLOCK_API())
+ uv__rwlock_srwlock_rdunlock(rwlock);
+ else
+ uv__rwlock_fallback_rdunlock(rwlock);
+}
+
+
+void uv_rwlock_wrlock(uv_rwlock_t* rwlock) {
+ if (HAVE_SRWLOCK_API())
+ uv__rwlock_srwlock_wrlock(rwlock);
+ else
+ uv__rwlock_fallback_wrlock(rwlock);
+}
+
+
+int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
+ if (HAVE_SRWLOCK_API())
+ return uv__rwlock_srwlock_trywrlock(rwlock);
+ else
+ return uv__rwlock_fallback_trywrlock(rwlock);
+}
+
+
+void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {
+ if (HAVE_SRWLOCK_API())
+ uv__rwlock_srwlock_wrunlock(rwlock);
+ else
+ uv__rwlock_fallback_wrunlock(rwlock);
+}
+
+
+inline static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock) {
+ pInitializeSRWLock(&rwlock->srwlock_);
+ return 0;
+}
+
+
+inline static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock) {
+ (void) rwlock;
+}
+
+
+inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock) {
+ pAcquireSRWLockShared(&rwlock->srwlock_);
+}
+
+
+inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock) {
+ if (pTryAcquireSRWLockShared(&rwlock->srwlock_))
+ return 0;
+ else
+ return -1;
+}
+
+
+inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock) {
+ pReleaseSRWLockShared(&rwlock->srwlock_);
+}
+
+
+inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock) {
+ pAcquireSRWLockExclusive(&rwlock->srwlock_);
+}
+
+
+inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock) {
+ if (pTryAcquireSRWLockExclusive(&rwlock->srwlock_))
+ return 0;
+ else
+ return -1;
+}
+
+
+inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock) {
+ pReleaseSRWLockExclusive(&rwlock->srwlock_);
+}
+
+
+inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock) {
+ if (uv_mutex_init(&rwlock->fallback_.read_mutex_))
+ return -1;
+
+ if (uv_mutex_init(&rwlock->fallback_.write_mutex_)) {
+ uv_mutex_destroy(&rwlock->fallback_.read_mutex_);
+ return -1;
+ }
+
+ rwlock->fallback_.num_readers_ = 0;
+
+ return 0;
+}
+
+
+inline static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock) {
+ uv_mutex_destroy(&rwlock->fallback_.read_mutex_);
+ uv_mutex_destroy(&rwlock->fallback_.write_mutex_);
+}
+
+
+inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock) {
+ uv_mutex_lock(&rwlock->fallback_.read_mutex_);
+
+ if (++rwlock->fallback_.num_readers_ == 1)
+ uv_mutex_lock(&rwlock->fallback_.write_mutex_);
+
+ uv_mutex_unlock(&rwlock->fallback_.read_mutex_);
+}
+
+
+inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock) {
+ int ret;
+
+ ret = -1;
+
+ if (uv_mutex_trylock(&rwlock->fallback_.read_mutex_))
+ goto out;
+
+ if (rwlock->fallback_.num_readers_ == 0)
+ ret = uv_mutex_trylock(&rwlock->fallback_.write_mutex_);
+ else
+ ret = 0;
+
+ if (ret == 0)
+ rwlock->fallback_.num_readers_++;
+
+ uv_mutex_unlock(&rwlock->fallback_.read_mutex_);
+
+out:
+ return ret;
+}
+
+
+inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock) {
+ uv_mutex_lock(&rwlock->fallback_.read_mutex_);
+
+ if (--rwlock->fallback_.num_readers_ == 0)
+ uv_mutex_unlock(&rwlock->fallback_.write_mutex_);
+
+ uv_mutex_unlock(&rwlock->fallback_.read_mutex_);
+}
+
+
+inline static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock) {
+ uv_mutex_lock(&rwlock->fallback_.write_mutex_);
+}
+
+
+inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock) {
+ return uv_mutex_trylock(&rwlock->fallback_.write_mutex_);
+}
+
+
+inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock) {
+ uv_mutex_unlock(&rwlock->fallback_.write_mutex_);
+}
+++ /dev/null
-/* 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 <assert.h>
-
-#include "uv.h"
-#include "../uv-common.h"
-#include "internal.h"
-
-
-#ifdef _MSC_VER /* msvc */
-# define NOINLINE __declspec (noinline)
-#else /* gcc */
-# define NOINLINE __attribute__ ((noinline))
-#endif
-
-
-static NOINLINE void uv__once_inner(uv_once_t* guard,
- void (*callback)(void)) {
- DWORD result;
- HANDLE existing_event, created_event;
- HANDLE* event_ptr;
-
- /* Fetch and align event_ptr */
- event_ptr = (HANDLE*) (((uintptr_t) &guard->event + (sizeof(HANDLE) - 1)) &
- ~(sizeof(HANDLE) - 1));
-
- created_event = CreateEvent(NULL, 1, 0, NULL);
- if (created_event == 0) {
- /* Could fail in a low-memory situation? */
- uv_fatal_error(GetLastError(), "CreateEvent");
- }
-
- existing_event = InterlockedCompareExchangePointer(event_ptr,
- created_event,
- NULL);
-
- if (existing_event == NULL) {
- /* We won the race */
- callback();
-
- result = SetEvent(created_event);
- assert(result);
- guard->ran = 1;
-
- } else {
- /* We lost the race. Destroy the event we created and wait for the */
- /* existing one to become signaled. */
- CloseHandle(created_event);
- result = WaitForSingleObject(existing_event, INFINITE);
- assert(result == WAIT_OBJECT_0);
- }
-}
-
-
-void uv_once(uv_once_t* guard, void (*callback)(void)) {
- /* Fast case - avoid WaitForSingleObject. */
- if (guard->ran) {
- return;
- }
-
- uv__once_inner(guard, callback);
-}
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
sCreateSymbolicLinkW pCreateSymbolicLinkW;
+sInitializeSRWLock pInitializeSRWLock;
+sAcquireSRWLockShared pAcquireSRWLockShared;
+sAcquireSRWLockExclusive pAcquireSRWLockExclusive;
+sTryAcquireSRWLockShared pTryAcquireSRWLockShared;
+sTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive;
+sReleaseSRWLockShared pReleaseSRWLockShared;
+sReleaseSRWLockExclusive pReleaseSRWLockExclusive;
void uv_winapi_init() {
pCreateSymbolicLinkW = (sCreateSymbolicLinkW)
GetProcAddress(kernel32_module, "CreateSymbolicLinkW");
+
+ pInitializeSRWLock = (sInitializeSRWLock)
+ GetProcAddress(kernel32_module, "InitializeSRWLock");
+
+ pAcquireSRWLockShared = (sAcquireSRWLockShared)
+ GetProcAddress(kernel32_module, "AcquireSRWLockShared");
+
+ pAcquireSRWLockExclusive = (sAcquireSRWLockExclusive)
+ GetProcAddress(kernel32_module, "AcquireSRWLockExclusive");
+
+ pTryAcquireSRWLockShared = (sTryAcquireSRWLockShared)
+ GetProcAddress(kernel32_module, "TryAcquireSRWLockShared");
+
+ pTryAcquireSRWLockExclusive = (sTryAcquireSRWLockExclusive)
+ GetProcAddress(kernel32_module, "TryAcquireSRWLockExclusive");
+
+ pReleaseSRWLockShared = (sReleaseSRWLockShared)
+ GetProcAddress(kernel32_module, "ReleaseSRWLockShared");
+
+ pReleaseSRWLockExclusive = (sReleaseSRWLockExclusive)
+ GetProcAddress(kernel32_module, "ReleaseSRWLockExclusive");
}
LPCWSTR lpTargetFileName,
DWORD dwFlags);
+typedef VOID (WINAPI* sInitializeSRWLock)
+ (PSRWLOCK SRWLock);
+
+typedef VOID (WINAPI* sAcquireSRWLockShared)
+ (PSRWLOCK SRWLock);
+
+typedef VOID (WINAPI* sAcquireSRWLockExclusive)
+ (PSRWLOCK SRWLock);
+
+typedef BOOL (WINAPI* sTryAcquireSRWLockShared)
+ (PSRWLOCK SRWLock);
+
+typedef BOOL (WINAPI* sTryAcquireSRWLockExclusive)
+ (PSRWLOCK SRWLock);
+
+typedef VOID (WINAPI* sReleaseSRWLockShared)
+ (PSRWLOCK SRWLock);
+
+typedef VOID (WINAPI* sReleaseSRWLockExclusive)
+ (PSRWLOCK SRWLock);
/* Ntapi function pointers */
extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
extern sCreateSymbolicLinkW pCreateSymbolicLinkW;
+extern sInitializeSRWLock pInitializeSRWLock;
+extern sAcquireSRWLockShared pAcquireSRWLockShared;
+extern sAcquireSRWLockExclusive pAcquireSRWLockExclusive;
+extern sTryAcquireSRWLockShared pTryAcquireSRWLockShared;
+extern sTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive;
+extern sReleaseSRWLockShared pReleaseSRWLockShared;
+extern sReleaseSRWLockExclusive pReleaseSRWLockExclusive;
#endif /* UV_WIN_WINAPI_H_ */
r = uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL);
return 0;
-}
\ No newline at end of file
+}
+
+
+static void fs_event_fail(uv_fs_event_t* handle, const char* filename,
+ int events, int status) {
+ ASSERT(0 && "should never be called");
+}
+
+
+static void timer_cb(uv_timer_t* handle, int status) {
+ int r;
+
+ ASSERT(status == 0);
+
+ r = uv_fs_event_init(handle->loop, &fs_event, ".", fs_event_fail, 0);
+ ASSERT(r != -1);
+
+ uv_close((uv_handle_t*)&fs_event, close_cb);
+ uv_close((uv_handle_t*)handle, close_cb);
+}
+
+
+TEST_IMPL(fs_event_immediate_close) {
+ uv_timer_t timer;
+ uv_loop_t* loop;
+ int r;
+
+ loop = uv_default_loop();
+
+ r = uv_timer_init(loop, &timer);
+ ASSERT(r == 0);
+
+ r = uv_timer_start(&timer, timer_cb, 1, 0);
+ ASSERT(r == 0);
+
+ uv_run(loop);
+
+ ASSERT(close_cb_called == 2);
+
+ return 0;
+}
TEST_DECLARE (fs_event_watch_file)
TEST_DECLARE (fs_event_watch_file_current_dir)
TEST_DECLARE (fs_event_no_callback_on_close)
+TEST_DECLARE (fs_event_immediate_close)
TEST_DECLARE (fs_readdir_empty_dir)
TEST_DECLARE (fs_readdir_file)
TEST_DECLARE (fs_open_dir)
TEST_DECLARE (threadpool_queue_work_simple)
+TEST_DECLARE (thread_mutex)
+TEST_DECLARE (thread_rwlock)
#ifdef _WIN32
TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows)
TEST_DECLARE (argument_escaping)
TEST_ENTRY (fs_event_watch_file)
TEST_ENTRY (fs_event_watch_file_current_dir)
TEST_ENTRY (fs_event_no_callback_on_close)
+ TEST_ENTRY (fs_event_immediate_close)
TEST_ENTRY (fs_readdir_empty_dir)
TEST_ENTRY (fs_readdir_file)
TEST_ENTRY (fs_open_dir)
TEST_ENTRY (threadpool_queue_work_simple)
+ TEST_ENTRY (thread_mutex)
+ TEST_ENTRY (thread_rwlock)
#if 0
/* These are for testing the test runner. */
--- /dev/null
+/* 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 <stdio.h>
+#include <stdlib.h>
+
+
+/* The mutex and rwlock tests are really poor.
+ * They're very basic sanity checks and nothing more.
+ * Apologies if that rhymes.
+ */
+
+TEST_IMPL(thread_mutex) {
+ uv_mutex_t mutex;
+ int r;
+
+ r = uv_mutex_init(&mutex);
+ ASSERT(r == 0);
+
+ uv_mutex_lock(&mutex);
+ uv_mutex_unlock(&mutex);
+ uv_mutex_destroy(&mutex);
+
+ return 0;
+}
+
+
+TEST_IMPL(thread_rwlock) {
+ uv_rwlock_t rwlock;
+ int r;
+
+ r = uv_rwlock_init(&rwlock);
+ ASSERT(r == 0);
+
+ uv_rwlock_rdlock(&rwlock);
+ uv_rwlock_rdunlock(&rwlock);
+ uv_rwlock_wrlock(&rwlock);
+ uv_rwlock_wrunlock(&rwlock);
+ uv_rwlock_destroy(&rwlock);
+
+ return 0;
+}
'src/win/internal.h',
'src/win/loop-watcher.c',
'src/win/pipe.c',
+ 'src/win/thread.c',
'src/win/process.c',
'src/win/req.c',
'src/win/stream.c',
'src/win/tcp.c',
'src/win/tty.c',
'src/win/threadpool.c',
- 'src/win/threads.c',
'src/win/timer.c',
'src/win/udp.c',
'src/win/util.c',
'src/unix/cares.c',
'src/unix/dl.c',
'src/unix/error.c',
+ 'src/unix/thread.c',
'src/unix/process.c',
'src/unix/internal.h',
'src/unix/eio/ecb.h',
'test/test-tcp-write-to-half-open-connection.c',
'test/test-tcp-writealot.c',
'test/test-threadpool.c',
+ 'test/test-mutexes.c',
'test/test-timer-again.c',
'test/test-timer.c',
'test/test-tty.c',