Live data from Hacker News

Restartable Sequences in Glibc 2.35

lwn.net

1–10 of 18 posts

Re: Restartable Sequences in Glibc 2.35

#5
So for a single critical section per thread, there's a small fixed overhead for every scheduling event in the system (the changes to the scheduler to check for whether the IP is in the critical section), and there's a restart cost if rescheduling actually happens during the critical section, but there's no additional code size or instructions on the critical path itself. But once managing multiple critical sections per thread this is no longer true...

Seems like interesting tradeoffs with an approach where the kernel manages a scheduling generation number in shared memory with each thread that gets incremented each scheduling, and having the user code responsible for checking at the end of the critical section whether it matches the value at the beginning. Probably an instruction or three less (and less pointer chasing) per scheduling event, but it eats a register during the critical section and grows the critical section by a few instructions, which also (for very tight critical sections) increases the chances they need a restart...

Re: Restartable Sequences in Glibc 2.35

#6
This seems really clever, but then I started thinking about the actual use cases. It does not offer protection against multiple threads modifying the same data. It is only useful where the "I was preempted in the middle" allows some deterministic recovery pathway to be taken. These are not unheard of, but they are rare compared to the cases where two (or more) threads may write the same non-atomic data (the ones where you'd really like cost-free RCU).

From the LWN article:

> The first rule is that the critical section cannot make any changes to the protected data structure that are visible to other threads until the final instruction in that section.

This makes me fairly certain that you cannot use this approach to deal with multi-core systems with data shared between threads, since the data could be modified without any preemption taking place.

Re: Restartable Sequences in Glibc 2.35

#7
post #5

So for a single critical section per thread, there's a small fixed overhead for every scheduling event in the system (the changes to the scheduler to check for whether the IP is in the critical section), and there's a restart cost if rescheduling actually happens during the critical section, but there's no additional code size or instructions on the critical path itself. But once managing multiple critical sections p…

The LWN article mentions that compare-and-exchange is considered "slow", and the design you're mentioning here, you'd need that.

This is an alternative to cmpxchg-style solutions, which you can implement entirely in user space with no kernel collarboration. As I mentioned in another thread, the restartable sequence approach seems very limited in applicability, since it only offers you something in cases where it is specifically preemption, not multithreaded access to the data, that you need to protect against.

Re: Restartable Sequences in Glibc 2.35

#9

This seems really clever, but then I started thinking about the actual use cases. It does not offer protection against multiple threads modifying the same data. It is only useful where the "I was preempted in the middle" allows some deterministic recovery pathway to be taken. These are not unheard of, but they are rare compared to the cases where two (or more) threads may write the same non-atomic data (the ones wher…

As the article says at the beginning, this is intended for per-CPU data structures, not shared ones. For example, buffer pools where you don't care exactly which pool a given thread takes its buffers from, but you do care about maximizing performance and minimizing contention.

Re: Restartable Sequences in Glibc 2.35

#10
post #9

This seems really clever, but then I started thinking about the actual use cases. It does not offer protection against multiple threads modifying the same data. It is only useful where the "I was preempted in the middle" allows some deterministic recovery pathway to be taken. These are not unheard of, but they are rare compared to the cases where two (or more) threads may write the same non-atomic data (the ones wher…

As the article says at the beginning, this is intended for per-CPU data structures, not shared ones. For example, buffer pools where you don't care exactly which pool a given thread takes its buffers from, but you do care about maximizing performance and minimizing contention.

That also requires pinning the thread to the cpu, or it can find itself "on the wrong core" when it wants to release the buffer.

This narrows the use case even further. To be clear I write software that could nominally benefit from stuff like this, but the tradeoffs (requiring pinning, in particular, which may not be available on all platforms) mean that it seems better to use approaches (e.g. RCU) that will work without restartable sequences.

Post reply on HN