Join the discussion

Write your take first — we'll ask for email only when you're ready to publish.

  • Hacker News
  • Claude, deal with this
  • I can't help myself digging into the referenced source code. The membarrier syscall can fail to allocate, returning ENOMEM. The way Folly calls it, the program would abort. Which I guess is a fair strategy but it's good to know when your synchronization primitive is actually SynchronizeOrCrash.
  • In Linux everything is XOrCrash, since allocations never fail but the OOM killer can get you later.
    by ot
  • > The membarrier syscall can fail to allocate, returning ENOMEM.

    This is mentioned in the source comment, but not documented in the membarrier(2) manual page.

    https://elixir.bootlin.com/linux/v7.1.2/source/kernel/sched/...

    In reality... what is it allocating?

    https://elixir.bootlin.com/linux/v7.1.2/source/kernel/sched/...

    Ok, so it needs to allocate a cpumask (tiny) under some usages.

    Similar requirement in other sites, e.g.: https://elixir.bootlin.com/linux/v7.1.2/source/kernel/sched/...

    Depending on kernel config (e.g., !CONFIG_CPUMAKS_OFFSTACK), this allocation literally cannot fail:

    https://elixir.bootlin.com/linux/v7.1.2/source/include/linux...

    On OFFSTACK configs, it's merely a tiny heap allocation:

    https://elixir.bootlin.com/linux/v7.1.2/source/lib/cpumask.c...

    If this fails, your system is already hosed; program abort vs kernel lock up a few seconds later is probably immaterial. I think folly's choice to abort is a reasonable one.

    by loeg
  • I also just added these to Julia for 1.14 (https://github.com/JuliaLang/julia/pull/60311).
  • Thanks for the link, I didn't know it was implemented in Julia (or any other language for that matter).

    I took a brief look at the PR, and there was one comment that caught my attention:

    > Note that unlike the C++ spec, I have specified that atomic_fence_heavy does synchronize with atomic_fence.

    I don't think C++ can specify that guarantee for the following reason:

    The agreement is that if, for some reason, the OS does not provide the required abstraction, falling back to `std::atomic_thread_fence(std::memory_order_seq_cst)` should still be a conforming implementation. However, `std::atomic_thread_fence(std::memory_order_seq_cst)` does not establish any new synchronizes-with relationships (at least, not beyond those already provided by the existing release/acquire fence rules). We can see why this wording fails in Approach 2 of P1202R0.

    With `membarrier` specifically, I still have not figured out a case that would break this specifically, but theoretically it feels possible since there are cases where happens-before are not enforced.

    That said, heavyweight fences do provide everything that ordinary fences provide. As Concurrency TS2 states: > A heavyweight-fence has all the synchronization effects of a fence (C++20 §33.5.11 [atomics.fences]).

  • This is a great article but it goes into a lot of detail that can be intimidating at first.

    For me, the reading that made asymmetric fences "click" is this: https://pvk.ca/Blog/2019/01/09/preemption-is-gc-for-memory-r...

    It might be easier to read that first, as it also goes into practical applications, and then this one.

    by ot
  • Thanks, this is very useful. Reading it I was wondering how applications typically exploit the asymmetric fence, I hope the article you linked help in that regard.