Skip to content

PhysicalCoreID: Use sched_getcpu on aarch64 with glibc >= 2.35#14224

Open
evanj wants to merge 1 commit into
facebook:mainfrom
evanj:evan.jones/physicalcore-aarch64
Open

PhysicalCoreID: Use sched_getcpu on aarch64 with glibc >= 2.35#14224
evanj wants to merge 1 commit into
facebook:mainfrom
evanj:evan.jones/physicalcore-aarch64

Conversation

@evanj

@evanj evanj commented Jan 6, 2026

Copy link
Copy Markdown
Contributor

The Linux sched_getcpu function was changed to use the glibc "restartable sequences" since glibc 2.35 in in 2022. At this point, most recent Linux distributions have picked this up. The preprocessor macro will conditionally enable it based on the version of glibc, so this should make this faster on newer aarch64 builds, without impacting old ones. I have tested with a microbenchmark that the performance with new glibc is the same as x86-64 (a few ns/call).

I added a test to try to check this. It was useful for me in testing this, but it is probably "wrong": without duplicating the check exactly, it is hard to test the support. It is possible we should remove the test.

Correct the macro: it should be testing __GLIBC__ and __GLIBC_MINOR__ for the glibc version, rather than __GNUC__ and __GNUC_MINOR__ for the gcc/clang version.

Linux distribution support for this feature:

RHEL 9 glibc glibc 2.34 released 2022-05-17 (TOO OLD)
RHEL 9.1 glibc 2.35 released 2022-11-15 [1]
RHEL 10 glibc 2.39 released 2025-05-20

Ubuntu LTS 20.04 glibc 2.31 released 2020-04-23 (TOO OLD)
Ubuntu LTS 22.04 glibc 2.35 released 2022-04-21
Ubuntu LTS 24.04 glibc 2.39 released 2024-04-25

Debian 11 glibc 2.31 released 2021-08-14 (TOO OLD)
Debian 12 glibc 2.36 released 2023-06-14
Debian 13 glibc 2.41 released 2025-08-09

[1] https://developers.redhat.com/articles/2022/12/22/restartable-sequences-support-glibc-rhel-9

@meta-cla meta-cla Bot added the CLA Signed label Jan 6, 2026
@evanj evanj force-pushed the evan.jones/physicalcore-aarch64 branch 2 times, most recently from e875d5d to 97ca3b1 Compare January 12, 2026 21:21
@evanj evanj force-pushed the evan.jones/physicalcore-aarch64 branch 2 times, most recently from b2cc26a to c91ef6c Compare February 11, 2026 16:10
@evanj

evanj commented Apr 18, 2026

Copy link
Copy Markdown
Contributor Author

Rebased on top of main commit 6ff9638 from 2026-04-18. This change is still relevant for arm64 Linux.

@evanj evanj force-pushed the evan.jones/physicalcore-aarch64 branch from c91ef6c to 2d2ad78 Compare April 18, 2026 13:21
@github-actions

github-actions Bot commented Apr 18, 2026

Copy link
Copy Markdown

✅ clang-tidy: No findings on changed lines

Completed in 182.9s.

@evanj evanj force-pushed the evan.jones/physicalcore-aarch64 branch from 2d2ad78 to 1b15aec Compare June 25, 2026 17:50
@github-actions

Copy link
Copy Markdown

🟡 Codex Code Review

Auto-triggered after CI passed — reviewing commit 1b15aec


Codex review failed before producing findings.

WARNING: proceeding, even though we could not create PATH aliases: Refusing to create helper binaries under temporary dir "/tmp" (codex_home: AbsolutePathBuf("/tmp/codex-home"))
error: the argument '--base <BRANCH>' cannot be used with '[PROMPT]'

Usage: codex exec review --commit <SHA> --base <BRANCH> --title <TITLE> --model <MODEL> --config <key=value> --dangerously-bypass-approvals-and-sandbox --output-last-message <FILE> [PROMPT]

For more information, try '--help'.

ℹ️ About this response

Generated by Codex CLI.
Review methodology: claude_md/code_review.md

Limitations:

  • Codex may miss context from files not in the diff
  • Large PRs may be truncated
  • Always apply human judgment to AI suggestions

Commands:

  • /codex-review [context] — Request a code review
  • /codex-query <question> — Ask about the PR or codebase
@github-actions

Copy link
Copy Markdown

✅ Claude Code Review

Auto-triggered after CI passed — reviewing commit 1b15aec


Summary

The PR extends PhysicalCoreID() to use fast sched_getcpu() on aarch64 with glibc >= 2.35 and attempts to fix a latent __GNUC____GLIBC__ macro bug. However, the fix is incomplete: one macro reference is still wrong, and the preprocessor logic has a structural redundancy issue.

High-severity findings (2):

  • [port/port_posix.cc:203] __GNUC_MINOR__ used instead of __GLIBC_MINOR__ in the x86_64 glibc version check — the stated bug fix is incomplete.
  • [port/port_posix.cc:200-204] The non-x86_64 branch (__GLIBC__ > 2 || ...) is not architecture-gated, making the x86_64-specific branch dead code on glibc >= 2.35 and masking H1.
Full review (click to expand)

Findings

🔴 HIGH

H1. Incomplete macro fix: __GNUC_MINOR__ instead of __GLIBC_MINOR__port/port_posix.cc:203
  • Issue: The PR description states "Correct the macro: it should be testing __GLIBC__ and __GLIBC_MINOR__." However, the x86_64 branch on line 203 still uses __GNUC_MINOR__:
    (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GNUC_MINOR__ >= 22))
    //                                    ^^^^^^^^^^^^^ should be __GLIBC_MINOR__
    This mixes glibc major version (__GLIBC__) with GCC minor version (__GNUC_MINOR__), which is nonsensical. It accidentally works on modern compilers where __GNUC_MINOR__ >= 22, but is semantically wrong.
  • Root cause: Incomplete find-replace — __GNUC__ was fixed to __GLIBC__ but __GNUC_MINOR__ was missed on this line.
  • Suggested fix: Change __GNUC_MINOR__ to __GLIBC_MINOR__ on line 203.
H2. Non-x86_64 branch subsumes x86_64 branch — port/port_posix.cc:200-204
  • Issue: The condition structure is:
    (x86_64 && glibc >= 2.22) || (glibc >= 2.35)
    
    The second disjunct is architecture-independent. On x86_64 with glibc >= 2.35, both match. The x86_64 branch only matters for glibc 2.22–2.34, a narrow window. This masks H1 on modern systems.
  • Suggested fix: Fix H1, and consider simplifying the logic for clarity.

🟡 MEDIUM

M1. Test flakiness: ASSERT_EQ(core1, core2)env/env_test.cc:5048
  • Issue: Thread could be rescheduled between two PhysicalCoreID() calls. The author acknowledges this risk.
  • Suggested fix: Remove this assertion or pin the thread with sched_setaffinity.
M2. OS_WIN in POSIX-only test — env/env_test.cc:5053
  • Issue: OS_WIN is dead code in EnvPosixTest. Misleading to readers.
  • Suggested fix: Remove || defined(OS_WIN).
M3. Non-glibc Linux (musl) — port/port_posix.cc:200-204
  • Issue: On musl, __GLIBC__ is undefined. ROCKSDB_SCHED_GETCPU_PRESENT may be set (musl provides sched_getcpu()), but the glibc version check blocks it. Consider whether ROCKSDB_SCHED_GETCPU_PRESENT alone should suffice.

🟢 LOW / NIT

L1. Redundant ASSERT_NE(core2, -1)env/env_test.cc:5055
  • Issue: Already implied by core1 == core2 and core1 != -1.
L2. ASSERT_GE(core1, -1) is trivially true — env/env_test.cc:5044
  • Issue: Only fails if return < -1, which is impossible per implementation.

Cross-Component Analysis

The sole consumer CoreLocalArray::AccessElementAndIndex() (util/core_local.h:68) handles -1 gracefully via random fallback, so even incorrect condition evaluation causes only a performance regression, not a correctness bug.

Context Behavior Issue?
x86_64 glibc >= 2.35 Works (via non-x86 branch, H2 masks H1) No
x86_64 glibc 2.22-2.34 Fragile (H1 bug, accidentally works) Yes
aarch64 glibc >= 2.35 Works (new, correct) No
musl Linux Falls back to -1 despite having sched_getcpu M3

Positive Observations

  • Correctly targets a real perf win: rseq-based sched_getcpu() on aarch64 is fast.
  • Build detection (ROCKSDB_SCHED_GETCPU_PRESENT) is already architecture-independent.
  • Error handling (sched_getcpu() < 0 → return -1) is preserved correctly.

ℹ️ About this response

Generated by Claude Code.
Review methodology: claude_md/code_review.md

Limitations:

  • Claude may miss context from files not in the diff
  • Large PRs may be truncated
  • Always apply human judgment to AI suggestions

Commands:

  • /claude-review [context] — Request a code review
  • /claude-query <question> — Ask about the PR or codebase
The Linux sched_getcpu function was changed to use glibc
"restartable sequences" since glibc 2.35 in in 2022. As of 2026,
all Linux distributions have picked this up. The preprocessor
macro will conditionally enable it based on the version of glibc, so
this should make this faster on newer aarch64 builds, without
impacting old ones. I have tested with a microbenchmark that the
performance with new glibc is the same as x86-64 (a few ns/call).

I added a test to try to check this. It was useful for me in testing
this, but it is probably "wrong": without duplicating the check
exactly, it is hard to test the support. It is possible we should
remove the test.

Correct the macro: it should be testing __GLIBC__ and __GLIBC_MINOR__
for the glibc version, rather than __GNUC__ and __GNUC_MINOR__ for
the gcc/clang version. Simplify the macro to just check for >= 2.35,
since it is many years old and the major LTS distributions have
picked this up a long time ago.

Linux distribution support for this feature:

RHEL 9 glibc glibc 2.34 released 2022-05-17 (TOO OLD)
RHEL 9.1 glibc 2.35 released 2022-11-15 [1]
RHEL 10 glibc 2.39 released 2025-05-20

Ubuntu LTS 20.04 glibc 2.31 released 2020-04-23 (TOO OLD)
Ubuntu LTS 22.04 glibc 2.35 released 2022-04-21
Ubuntu LTS 24.04 glibc 2.39 released 2024-04-25

Debian 11 glibc 2.31 released 2021-08-14 (TOO OLD)
Debian 12 glibc 2.36 released 2023-06-14
Debian 13 glibc 2.41 released 2025-08-09

[1] https://developers.redhat.com/articles/2022/12/22/restartable-sequences-support-glibc-rhel-9
@evanj evanj force-pushed the evan.jones/physicalcore-aarch64 branch from 1b15aec to b0bb9fb Compare June 26, 2026 20:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

2 participants