* librseq memory allocator portability @ 2025-02-02 15:48 Ondřej Surý via lttng-dev 2025-02-03 14:52 ` Mathieu Desnoyers via lttng-dev 0 siblings, 1 reply; 3+ messages in thread From: Ondřej Surý via lttng-dev @ 2025-02-02 15:48 UTC (permalink / raw) To: lttng-dev Hey Mathieu, I’m actually thinking about using librseq for some more lightweight stuff first - like statistic counters (especially those related to memory allocations), and my first obvious question would be - how portable is the librseq memory allocator? I am not keen on having a code with ifdef spaghetti to support BSDs, so I think that it probably should provide some per-thread memory pools at the expense of just consuming more memory on platforms without rseq system call. Ondrej -- Ondřej Surý (He/Him) ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: librseq memory allocator portability 2025-02-02 15:48 librseq memory allocator portability Ondřej Surý via lttng-dev @ 2025-02-03 14:52 ` Mathieu Desnoyers via lttng-dev 2025-02-03 14:55 ` Mathieu Desnoyers via lttng-dev 0 siblings, 1 reply; 3+ messages in thread From: Mathieu Desnoyers via lttng-dev @ 2025-02-03 14:52 UTC (permalink / raw) To: Ondřej Surý, lttng-dev On 2025-02-02 16:48, Ondřej Surý via lttng-dev wrote: > Hey Mathieu, > > I’m actually thinking about using librseq for some more lightweight stuff first - like statistic counters (especially those related to memory allocations), and my first obvious question would be - how portable is the librseq memory allocator? > > I am not keen on having a code with ifdef spaghetti to support BSDs, so I think that it probably should provide some per-thread memory pools at the expense of just consuming more memory on platforms without rseq system call. Hi Ondrej, I have good news: the librseq mempool allocator is completely independent of the rseq system call. It's just a memory allocator. AFAIR, the only optional dependency which is Linux-specific is on memfd_create for the RSEQ_MEMPOOL_POPULATE_COW_INIT populate policy. The RSEQ_MEMPOOL_POPULATE_COW_ZERO policy can be used as fallback on other architectures. It uses more memory on systems where only few of the possible cores are used and allocated memory is initialized to non-zero values. Indexing per-cpu can fallback to sched_getcpu(3) if rseq is not available, which should be common enough. This is actually what the librseq rseq_current_cpu() does as fallback. So you could just use that static inline helper. Now in terms of strategy for using rseq critical sections for a split-counter use-case, let's see our options: - You'll want to use rseq_load_add_store__ptr() on your fast path. It will return a negative error in case of abort, or if the environment does not support rseq: A) either your Linux kernel does not have CONFIG_RSEQ or is too old, B) or your GNU libc does not have rseq support, and you did not explicitly call the librseq thread registration. C) or your environment does not support rseq at all (e.g. BSD). In the caller code, when handing rseq_load_add_store__ptr() errors, I would recommend a fallback to an atomic counter increment of a _second_ counter, so if the fallback is used in a situation caused by an rseq abort (e.g. a debugger single stepping within the rseq critical section) it works flawlessly. Then you'll want to sum up the per-cpu counters for the rseq fast-path and for the atomic counter slow-path whenever you read the counter value. We may need to tweak the librseq code a little bit to handle case (C) for BSDs, as this has not been a target so far, so we may need to add a few #ifdefs to cover that case seamlessly. We have an internal project progressing at EfficiOS which aims to implement the equivalent of the Linux kernel static keys for userspace on various architectures. The goal is to dynamically change the code behavior between a no-op and a jump, thus selecting between rseq or atomics from a library or program constructor based on rseq availability. Please let me know if anything is unclear. Thanks! Mathieu -- Mathieu Desnoyers EfficiOS Inc. https://www.efficios.com ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: librseq memory allocator portability 2025-02-03 14:52 ` Mathieu Desnoyers via lttng-dev @ 2025-02-03 14:55 ` Mathieu Desnoyers via lttng-dev 0 siblings, 0 replies; 3+ messages in thread From: Mathieu Desnoyers via lttng-dev @ 2025-02-03 14:55 UTC (permalink / raw) To: Ondřej Surý, lttng-dev On 2025-02-03 15:52, Mathieu Desnoyers via lttng-dev wrote: > On 2025-02-02 16:48, Ondřej Surý via lttng-dev wrote: >> Hey Mathieu, >> >> I’m actually thinking about using librseq for some more lightweight >> stuff first - like statistic counters (especially those related to >> memory allocations), and my first obvious question would be - how >> portable is the librseq memory allocator? >> >> I am not keen on having a code with ifdef spaghetti to support BSDs, >> so I think that it probably should provide some per-thread memory >> pools at the expense of just consuming more memory on platforms >> without rseq system call. > > Hi Ondrej, > > I have good news: the librseq mempool allocator is completely > independent of the rseq system call. It's just a memory > allocator. > > AFAIR, the only optional dependency which is Linux-specific > is on memfd_create for the RSEQ_MEMPOOL_POPULATE_COW_INIT > populate policy. The RSEQ_MEMPOOL_POPULATE_COW_ZERO policy > can be used as fallback on other architectures. It uses > more memory on systems where only few of the possible > cores are used and allocated memory is initialized to > non-zero values. > > Indexing per-cpu can fallback to sched_getcpu(3) if > rseq is not available, which should be common enough. > This is actually what the librseq rseq_current_cpu() > does as fallback. So you could just use that static > inline helper. > > Now in terms of strategy for using rseq critical sections > for a split-counter use-case, let's see our options: > > - You'll want to use rseq_load_add_store__ptr() on your > fast path. It will return a negative error in case of > abort, or if the environment does not support rseq: > > A) either your Linux kernel does not have CONFIG_RSEQ or > is too old, > B) or your GNU libc does not have rseq support, and you > did not explicitly call the librseq thread registration. > C) or your environment does not support rseq at all > (e.g. BSD). > > In the caller code, when handing rseq_load_add_store__ptr() > errors, I would recommend a fallback to an atomic counter > increment of a _second_ counter, so if the fallback is used > in a situation caused by an rseq abort (e.g. a debugger single > stepping within the rseq critical section) it works flawlessly. > > Then you'll want to sum up the per-cpu counters for the rseq > fast-path and for the atomic counter slow-path whenever you > read the counter value. > > We may need to tweak the librseq code a little bit to handle > case (C) for BSDs, as this has not been a target so far, so > we may need to add a few #ifdefs to cover that case seamlessly. > > We have an internal project progressing at EfficiOS which aims > to implement the equivalent of the Linux kernel static keys for > userspace on various architectures. The goal is to dynamically > change the code behavior between a no-op and a jump, thus selecting > between rseq or atomics from a library or program constructor > based on rseq availability. > > Please let me know if anything is unclear. One more thing: we may want to go ahead with the implementation of fork handling with pthread_atfork which is still on the librseq TODO list so we can eliminate our dependency on madvise MADV_DONTFORK and MADV_WIPEONFORK which are Linux-specific. Thanks, Mathieu > > Thanks! > > Mathieu > -- Mathieu Desnoyers EfficiOS Inc. https://www.efficios.com ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-02-03 14:56 UTC | newest] Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2025-02-02 15:48 librseq memory allocator portability Ondřej Surý via lttng-dev 2025-02-03 14:52 ` Mathieu Desnoyers via lttng-dev 2025-02-03 14:55 ` Mathieu Desnoyers via lttng-dev
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox