MCPcopy Create free account
hub / github.com/Serial-Studio/Serial-Studio / _adjacent_atomic_findings

Function _adjacent_atomic_findings

scripts/code_verify_rules.py:941–989  ·  view source on GitHub ↗

Two `std::atomic<>` (or QAtomic*) members within a few lines of each other almost certainly share a 64-byte cache line. When two cores write to atomics that share a line, MESI/MOESI invalidations bounce the line across cores -- a 50-200x slowdown vs the uncontended case (false sharin

(class_node, src: bytes, fenced)

Source from the content-addressed store, hash-verified

939
940
941def _adjacent_atomic_findings(class_node, src: bytes, fenced) -> list:
942 """Two `std::atomic<>` (or QAtomic*) members within a few lines of
943 each other almost certainly share a 64-byte cache line. When two
944 cores write to atomics that share a line, MESI/MOESI invalidations
945 bounce the line across cores -- a 50-200x slowdown vs the uncontended
946 case (false sharing). The fix is `alignas(64)` (or
947 `std::hardware_destructive_interference_size`) on each, or explicit
948 `char _pad[64];` padding.
949
950 Pointer-to-atomic fields are skipped: the pointer itself is set once
951 at construction, and the actual atomics live behind the indirection
952 in some other object whose layout we can&#x27;t reason about from here."""
953 findings: list = []
954 body = class_node.child_by_field_name("body")
955 if body is None:
956 return findings
957 prev_line = -100
958 for child in body.children:
959 if child.type != "field_declaration":
960 continue
961 text = _node_text(child, src)
962 if not _ATOMIC_DECL_RE.search(text):
963 prev_line = -100
964 continue
965 # Skip pointer-to-atomic and reference-to-atomic fields: the
966 # atomic that would suffer false sharing lives elsewhere.
967 if re.search(r"atomic\w*\s*(?:<[^>]*>)?\s*[*&]", text):
968 prev_line = -100
969 continue
970 if "alignas" in text:
971 prev_line = _line_of(child)
972 continue
973 line = _line_of(child)
974 if not fenced(line) and 0 < line - prev_line <= 4:
975 findings.append(
976 Finding(
977 line,
978 "perf-false-sharing-risk",
979 "adjacent atomic members will share a cache line "
980 "(64 B Intel/AArch64, up to 128 B on Apple Silicon "
981 "M-series via the 128 B speculative line). Cross-core "
982 "writes thrash MESI/MOESI invalidations (50-200x slowdown "
983 "vs uncontended). Add `alignas(64)` / "
984 "`alignas(std::hardware_destructive_interference_size)` "
985 "or insert `char _pad[64 - sizeof(prev)];` between them.",
986 )
987 )
988 prev_line = line
989 return findings
990
991
992def _virtual_hotpath_findings(src_text: str, path: Path, fenced) -> list:

Callers 1

_cpp_rulesFunction · 0.85

Calls 6

_node_textFunction · 0.85
_line_ofFunction · 0.85
fencedFunction · 0.85
FindingClass · 0.70
searchMethod · 0.45
appendMethod · 0.45

Tested by

no test coverage detected