diff --git a/src/unix/core.c b/src/unix/core.c index 9343ee72..3dd7a94c 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -233,10 +233,10 @@ int uv__getiovmax(void) { #if defined(IOV_MAX) return IOV_MAX; #elif defined(_SC_IOV_MAX) - static int iovmax_cached = -1; + static _Atomic int iovmax_cached = -1; int iovmax; - iovmax = uv__load_relaxed(&iovmax_cached); + iovmax = atomic_load_explicit(&iovmax_cached, memory_order_relaxed); if (iovmax != -1) return iovmax; @@ -248,7 +248,7 @@ int uv__getiovmax(void) { if (iovmax == -1) iovmax = 1; - uv__store_relaxed(&iovmax_cached, iovmax); + atomic_store_explicit(&iovmax_cached, iovmax, memory_order_relaxed); return iovmax; #else diff --git a/src/unix/fs.c b/src/unix/fs.c index 9c8ef6cc..a54038c9 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -309,7 +309,7 @@ static int uv__fs_mkstemp(uv_fs_t* req) { static uv_once_t once = UV_ONCE_INIT; int r; #ifdef O_CLOEXEC - static int no_cloexec_support; + static _Atomic int no_cloexec_support; #endif static const char pattern[] = "XXXXXX"; static const size_t pattern_size = sizeof(pattern) - 1; @@ -334,7 +334,8 @@ static int uv__fs_mkstemp(uv_fs_t* req) { uv_once(&once, uv__mkostemp_initonce); #ifdef O_CLOEXEC - if (uv__load_relaxed(&no_cloexec_support) == 0 && uv__mkostemp != NULL) { + if (atomic_load_explicit(&no_cloexec_support, memory_order_relaxed) == 0 && + uv__mkostemp != NULL) { r = uv__mkostemp(path, O_CLOEXEC); if (r >= 0) @@ -347,7 +348,7 @@ static int uv__fs_mkstemp(uv_fs_t* req) { /* We set the static variable so that next calls don't even try to use mkostemp. */ - uv__store_relaxed(&no_cloexec_support, 1); + atomic_store_explicit(&no_cloexec_support, 1, memory_order_relaxed); } #endif /* O_CLOEXEC */ @@ -457,7 +458,7 @@ static ssize_t uv__fs_preadv(uv_file fd, static ssize_t uv__fs_read(uv_fs_t* req) { #if defined(__linux__) - static int no_preadv; + static _Atomic int no_preadv; #endif unsigned int iovmax; ssize_t result; @@ -481,7 +482,7 @@ static ssize_t uv__fs_read(uv_fs_t* req) { result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off); #else # if defined(__linux__) - if (uv__load_relaxed(&no_preadv)) retry: + if (atomic_load_explicit(&no_preadv, memory_order_relaxed)) retry: # endif { result = uv__fs_preadv(req->file, req->bufs, req->nbufs, req->off); @@ -493,7 +494,7 @@ static ssize_t uv__fs_read(uv_fs_t* req) { req->nbufs, req->off); if (result == -1 && errno == ENOSYS) { - uv__store_relaxed(&no_preadv, 1); + atomic_store_explicit(&no_preadv, 1, memory_order_relaxed); goto retry; } } @@ -899,14 +900,14 @@ out: #ifdef __linux__ static unsigned uv__kernel_version(void) { - static unsigned cached_version; + static _Atomic unsigned cached_version; struct utsname u; unsigned version; unsigned major; unsigned minor; unsigned patch; - version = uv__load_relaxed(&cached_version); + version = atomic_load_explicit(&cached_version, memory_order_relaxed); if (version != 0) return version; @@ -917,7 +918,7 @@ static unsigned uv__kernel_version(void) { return 0; version = major * 65536 + minor * 256 + patch; - uv__store_relaxed(&cached_version, version); + atomic_store_explicit(&cached_version, version, memory_order_relaxed); return version; } @@ -959,10 +960,10 @@ static int uv__is_cifs_or_smb(int fd) { static ssize_t uv__fs_try_copy_file_range(int in_fd, off_t* off, int out_fd, size_t len) { - static int no_copy_file_range_support; + static _Atomic int no_copy_file_range_support; ssize_t r; - if (uv__load_relaxed(&no_copy_file_range_support)) { + if (atomic_load_explicit(&no_copy_file_range_support, memory_order_relaxed)) { errno = ENOSYS; return -1; } @@ -981,7 +982,7 @@ static ssize_t uv__fs_try_copy_file_range(int in_fd, off_t* off, errno = ENOSYS; /* Use fallback. */ break; case ENOSYS: - uv__store_relaxed(&no_copy_file_range_support, 1); + atomic_store_explicit(&no_copy_file_range_support, 1, memory_order_relaxed); break; case EPERM: /* It's been reported that CIFS spuriously fails. @@ -1530,14 +1531,14 @@ static int uv__fs_statx(int fd, uv_stat_t* buf) { STATIC_ASSERT(UV_ENOSYS != -1); #ifdef __linux__ - static int no_statx; + static _Atomic int no_statx; struct uv__statx statxbuf; int dirfd; int flags; int mode; int rc; - if (uv__load_relaxed(&no_statx)) + if (atomic_load_explicit(&no_statx, memory_order_relaxed)) return UV_ENOSYS; dirfd = AT_FDCWD; @@ -1571,7 +1572,7 @@ static int uv__fs_statx(int fd, * implemented, rc might return 1 with 0 set as the error code in which * case we return ENOSYS. */ - uv__store_relaxed(&no_statx, 1); + atomic_store_explicit(&no_statx, 1, memory_order_relaxed); return UV_ENOSYS; } diff --git a/src/unix/kqueue.c b/src/unix/kqueue.c index c68cd451..deb486ba 100644 --- a/src/unix/kqueue.c +++ b/src/unix/kqueue.c @@ -60,7 +60,7 @@ int uv__kqueue_init(uv_loop_t* loop) { #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 -static int uv__has_forked_with_cfrunloop; +static _Atomic int uv__has_forked_with_cfrunloop; #endif int uv__io_fork(uv_loop_t* loop) { @@ -82,7 +82,9 @@ int uv__io_fork(uv_loop_t* loop) { process. So we sidestep the issue by pretending like we never started it in the first place. */ - uv__store_relaxed(&uv__has_forked_with_cfrunloop, 1); + atomic_store_explicit(&uv__has_forked_with_cfrunloop, + 1, + memory_order_relaxed); uv__free(loop->cf_state); loop->cf_state = NULL; } @@ -530,7 +532,8 @@ int uv_fs_event_start(uv_fs_event_t* handle, if (!(statbuf.st_mode & S_IFDIR)) goto fallback; - if (0 == uv__load_relaxed(&uv__has_forked_with_cfrunloop)) { + if (0 == atomic_load_explicit(&uv__has_forked_with_cfrunloop, + memory_order_relaxed)) { int r; /* The fallback fd is no longer needed */ uv__close_nocheckstdio(fd); @@ -565,7 +568,8 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { uv__handle_stop(handle); #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - if (0 == uv__load_relaxed(&uv__has_forked_with_cfrunloop)) + if (0 == atomic_load_explicit(&uv__has_forked_with_cfrunloop, + memory_order_relaxed)) if (handle->cf_cb != NULL) r = uv__fsevents_close(handle); #endif diff --git a/src/unix/linux.c b/src/unix/linux.c index 0512417a..a30f1bfb 100644 --- a/src/unix/linux.c +++ b/src/unix/linux.c @@ -579,7 +579,7 @@ update_timeout: } uint64_t uv__hrtime(uv_clocktype_t type) { - static clock_t fast_clock_id = -1; + static _Atomic clock_t fast_clock_id = -1; struct timespec t; clock_t clock_id; @@ -595,7 +595,7 @@ uint64_t uv__hrtime(uv_clocktype_t type) { if (type != UV_CLOCK_FAST) goto done; - clock_id = uv__load_relaxed(&fast_clock_id); + clock_id = atomic_load_explicit(&fast_clock_id, memory_order_relaxed); if (clock_id != -1) goto done; @@ -604,7 +604,7 @@ uint64_t uv__hrtime(uv_clocktype_t type) { if (t.tv_nsec <= 1 * 1000 * 1000) clock_id = CLOCK_MONOTONIC_COARSE; - uv__store_relaxed(&fast_clock_id, clock_id); + atomic_store_explicit(&fast_clock_id, clock_id, memory_order_relaxed); done: diff --git a/src/uv-common.c b/src/uv-common.c index 1031be4a..cec771fa 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -944,7 +944,7 @@ __attribute__((destructor)) void uv_library_shutdown(void) { static int was_shutdown; - if (uv__load_relaxed(&was_shutdown)) + if (uv__exchange_int_relaxed(&was_shutdown, 1)) return; uv__process_title_cleanup(); @@ -955,7 +955,6 @@ void uv_library_shutdown(void) { #else uv__threadpool_cleanup(); #endif - uv__store_relaxed(&was_shutdown, 1); } diff --git a/src/uv-common.h b/src/uv-common.h index 26d0e49b..2720121a 100644 --- a/src/uv-common.h +++ b/src/uv-common.h @@ -37,6 +37,10 @@ #include "queue.h" #include "strscpy.h" +#ifndef _MSC_VER +# include +#endif + #if EDOM > 0 # define UV__ERR(x) (-(x)) #else @@ -61,12 +65,12 @@ extern int snprintf(char*, size_t, const char*, ...); void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)]) #endif -#if defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 7) -#define uv__load_relaxed(p) __atomic_load_n(p, __ATOMIC_RELAXED) -#define uv__store_relaxed(p, v) __atomic_store_n(p, v, __ATOMIC_RELAXED) +#ifdef _MSC_VER +#define uv__exchange_int_relaxed(p, v) \ + InterlockedExchangeNoFence((LONG volatile*)(p), v) #else -#define uv__load_relaxed(p) (*p) -#define uv__store_relaxed(p, v) do *p = v; while (0) +#define uv__exchange_int_relaxed(p, v) \ + atomic_exchange_explicit((_Atomic int*)(p), v, memory_order_relaxed) #endif #define UV__UDP_DGRAM_MAXSIZE (64 * 1024)