Repository: JuliaLang/julia
File: src/signals-unix.c (C)

Code before:
static _Atomic(enum membarrier_implementation) membarrier_impl = MEMBARRIER_IMPLEMENTATION_UNKNOWN;

static enum membarrier_implementation jl_init_membarrier(void) {
    int ret = membarrier(MEMBARRIER_CMD_QUERY, 0);
    int needed = MEMBARRIER_CMD_PRIVATE_EXPEDITED | MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED;
    if (ret > 0 && ((ret & needed) == needed)) {
        // supported
        if (membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0) == 0) {
            // working
            jl_atomic_store_relaxed(&membarrier_impl, MEMBARRIER_IMPLEMENTATION_SYS_MEMBARRIER);
            return MEMBARRIER_IMPLEMENTATION_SYS_MEMBARRIER;
        }
    }
    jl_init_mprotect_membarrier();
    jl_atomic_store_relaxed(&membarrier_impl, MEMBARRIER_IMPLEMENTATION_MPROTECT);
    return MEMBARRIER_IMPLEMENTATION_MPROTECT;
}

JL_DLLEXPORT void jl_membarrier(void) {
    enum membarrier_implementation impl = jl_atomic_load_relaxed(&membarrier_impl);
    if (impl == MEMBARRIER_IMPLEMENTATION_UNKNOWN) {
        impl = jl_init_membarrier();
    }
    if (impl == MEMBARRIER_IMPLEMENTATION_SYS_MEMBARRIER) {
        int ret = membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED, 0);
        assert(ret);
        (void)ret;
    } else {
        assert(impl == MEMBARRIER_IMPLEMENTATION_MPROTECT);
        jl_mprotect_membarrier();
    }
}
#endif


Review comment (bug):
Claude:
   1. Bug in jl_membarrier assertion (signals-unix.c:1394)
```assert(ret); // BUG: This asserts that ret is non-zero (failure)```
The assertion is inverted. It should be assert(ret == 0) to verify success, not assert(ret) which asserts the syscall failed.


Code after:
    MEMBARRIER_IMPLEMENTATION_UNKNOWN        = 0,
    MEMBARRIER_IMPLEMENTATION_SYS_MEMBARRIER = 1,
    MEMBARRIER_IMPLEMENTATION_MPROTECT       = 2,
    MEMBARRIER_IMPLEMENTATION_THREAD_SUSPEND = 3
};

static _Atomic(enum membarrier_implementation) membarrier_impl = MEMBARRIER_IMPLEMENTATION_UNKNOWN;

// Linux and FreeBSD have compatible membarrier syscall support
#if defined(_OS_LINUX_)
#   include <sys/syscall.h>
#   if defined(__NR_membarrier)
enum membarrier_cmd {
    MEMBARRIER_CMD_QUERY                        = 0,
    MEMBARRIER_CMD_PRIVATE_EXPEDITED            = (1 << 3),
    MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED   = (1 << 4),
};
#    define membarrier(...) syscall(__NR_membarrier, __VA_ARGS__)
#    define HAVE_MEMBARRIER_SYSCALL
#  else
#    warning "Missing linux kernel headers for membarrier syscall, support disabled"
#  endif
#elif defined(_OS_FREEBSD_)
#  include <sys/param.h>
#  if __FreeBSD_version >= 1401500
#    include <sys/membarrier.h>
#    define HAVE_MEMBARRIER_SYSCALL
#  endif
#endif

static enum membarrier_implementation jl_init_membarrier(void) {
#ifdef HAVE_MEMBARRIER_SYSCALL
    int ret = membarrier(MEMBARRIER_CMD_QUERY, 0);
    int needed = MEMBARRIER_CMD_PRIVATE_EXPEDITED | MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED;
    if (ret > 0 && ((ret & needed) == needed)) {
        // supported
        if (membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0) == 0) {
            // working
            jl_atomic_store_relaxed(&membarrier_impl, MEMBARRIER_IMPLEMENTATION_SYS_MEMBARRIER);
            return MEMBARRIER_IMPLEMENTATION_SYS_MEMBARRIER;
        }
    }
#endif
    // The mprotect fallback is known not to work on AArch64, so skip it there
#if !defined(_CPU_AARCH64_) && !defined(_CPU_ARM_)
    if (jl_init_mprotect_membarrier()) {
        jl_atomic_store_relaxed(&membarrier_impl, MEMBARRIER_IMPLEMENTATION_MPROTECT);
        return MEMBARRIER_IMPLEMENTATION_MPROTECT;
    }
#endif
    // Fall back to thread suspension (sound but slow)