process-util: skip the atomic exchange for a cached PID

getpid_cached() runs a compare-and-exchange on every call, also when
the PID is cached already. On x86 that is a locked read-modify-write
even when the comparison fails. sd-journal calls getpid_cached() in
every public function to detect use after fork(). Reading the entries
of a journal hence calls it once per entry and field.

Load the cached value first, and only fall back to the exchange if it
is not set. Reading 1M entries of a real journal takes about 2% fewer
cycles.
This commit is contained in:
Daan De Meyer authored and Lennart Poettering committed 2026-10-08 19:52:29 +02:00
1 parent 4da00a0432
commit bde980af1e
1 file changed
+8 -1
+8 -1
View File
@@ -1315,7 +1315,7 @@ void reset_cached_pid(void) {
pid_t getpid_cached(void) {
static bool installed = false;
pid_t current_value = CACHED_PID_UNSET;
pid_t current_value;
/* getpid_cached() is much like getpid(), but caches the value in local memory, to avoid having to invoke a
* system call each time. This restores glibc behaviour from before 2.24, when getpid() was unconditionally
@@ -1326,6 +1326,13 @@ pid_t getpid_cached(void) {
* https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c579f48edba88380635ab98cb612030e3ed8691e
*/
/* The compare-and-exchange below is a locked read-modify-write even when it fails. Almost all calls
* find the PID cached, hence check for it with a plain load first. */
current_value = __atomic_load_n(&cached_pid, __ATOMIC_RELAXED);
if (current_value > 0)
return current_value;
current_value = CACHED_PID_UNSET;
(void) __atomic_compare_exchange_n(
&cached_pid,
&current_value,