src: switch to use C11 atomics where available (#3950)
Switch all code in unix/ to use C11 atomics directly. Change uv_library_shutdown() to use an exchange instead of load/store. Unfortunately MSVC only started supporting C11 atomics in VS2022 version 17.5 Preview 2 as experimental. So resort to using the Interlocked API. Ref: https://devblogs.microsoft.com/cppblog/c11-atomics-in-visual-studio-2022-version-17-5-preview-2/ Fixes: https://github.com/libuv/libuv/issues/3948
This commit is contained in:
parent
e189c31375
commit
2f33980a91
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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:
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -37,6 +37,10 @@
|
||||
#include "queue.h"
|
||||
#include "strscpy.h"
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# include <stdatomic.h>
|
||||
#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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user