This script finds and fixes many variations of the pattern: while (!atomic(&flag));
to add a rte_pause() to the loop. This type of loop was causing failures in the standalone atomic tests on high core system. The script generalizes that to find other places with the same problem. Script was autogenerated by AI and works but may cover more cases than really necessary. Signed-off-by: Stephen Hemminger <[email protected]> --- devtools/cocci/fix_empty_spinloops.cocci | 165 +++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 devtools/cocci/fix_empty_spinloops.cocci diff --git a/devtools/cocci/fix_empty_spinloops.cocci b/devtools/cocci/fix_empty_spinloops.cocci new file mode 100644 index 0000000000..ff64b30eac --- /dev/null +++ b/devtools/cocci/fix_empty_spinloops.cocci @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Find and fix empty spin loops that should call rte_pause() +// +// Empty spin loops waste CPU cycles and can cause performance issues. +// This script finds various forms of busy-wait loops and adds rte_pause() +// to give hints to the CPU and reduce power consumption. + +// Rule 1: Handle rte_atomic*_read() variants +@fix_atomic_read@ +expression ptr, val; +@@ + +( +- while (rte_atomic16_read(ptr) == val); ++ while (rte_atomic16_read(ptr) == val) ++ rte_pause(); +| +- while (rte_atomic16_read(ptr) != val); ++ while (rte_atomic16_read(ptr) != val) ++ rte_pause(); +| +- while (rte_atomic32_read(ptr) == val); ++ while (rte_atomic32_read(ptr) == val) ++ rte_pause(); +| +- while (rte_atomic32_read(ptr) != val); ++ while (rte_atomic32_read(ptr) != val) ++ rte_pause(); +| +- while (rte_atomic64_read(ptr) == val); ++ while (rte_atomic64_read(ptr) == val) ++ rte_pause(); +| +- while (rte_atomic64_read(ptr) != val); ++ while (rte_atomic64_read(ptr) != val) ++ rte_pause(); +) + +// Rule 2: Handle rte_atomic*_read() with comparison operators +@fix_atomic_cmp@ +expression ptr, val; +@@ + +( +- while (rte_atomic16_read(ptr) < val); ++ while (rte_atomic16_read(ptr) < val) ++ rte_pause(); +| +- while (rte_atomic16_read(ptr) > val); ++ while (rte_atomic16_read(ptr) > val) ++ rte_pause(); +| +- while (rte_atomic32_read(ptr) < val); ++ while (rte_atomic32_read(ptr) < val) ++ rte_pause(); +| +- while (rte_atomic32_read(ptr) > val); ++ while (rte_atomic32_read(ptr) > val) ++ rte_pause(); +| +- while (rte_atomic64_read(ptr) < val); ++ while (rte_atomic64_read(ptr) < val) ++ rte_pause(); +| +- while (rte_atomic64_read(ptr) > val); ++ while (rte_atomic64_read(ptr) > val) ++ rte_pause(); +) + +// Rule 3: Handle C11 atomics with rte_atomic_load_explicit() +@fix_c11_atomic@ +expression ptr, order, val; +@@ + +( +- while (rte_atomic_load_explicit(ptr, order) == val); ++ while (rte_atomic_load_explicit(ptr, order) == val) ++ rte_pause(); +| +- while (rte_atomic_load_explicit(ptr, order) != val); ++ while (rte_atomic_load_explicit(ptr, order) != val) ++ rte_pause(); +| +- while (rte_atomic_load_explicit(ptr, order) < val); ++ while (rte_atomic_load_explicit(ptr, order) < val) ++ rte_pause(); +| +- while (rte_atomic_load_explicit(ptr, order) > val); ++ while (rte_atomic_load_explicit(ptr, order) > val) ++ rte_pause(); +) + +// Rule 4: Handle __atomic_load_n() directly +@fix_gcc_atomic@ +expression ptr, order, val; +@@ + +( +- while (__atomic_load_n(ptr, order) == val); ++ while (__atomic_load_n(ptr, order) == val) ++ rte_pause(); +| +- while (__atomic_load_n(ptr, order) != val); ++ while (__atomic_load_n(ptr, order) != val) ++ rte_pause(); +| +- while (__atomic_load_n(ptr, order) < val); ++ while (__atomic_load_n(ptr, order) < val) ++ rte_pause(); +| +- while (__atomic_load_n(ptr, order) > val); ++ while (__atomic_load_n(ptr, order) > val) ++ rte_pause(); +) + +// Rule 5: Handle volatile variable reads (simple dereference) +@fix_volatile@ +expression E; +identifier v; +@@ + +( +- while (*v == E); ++ while (*v == E) ++ rte_pause(); +| +- while (*v != E); ++ while (*v != E) ++ rte_pause(); +| +- while (*v < E); ++ while (*v < E) ++ rte_pause(); +| +- while (*v > E); ++ while (*v > E) ++ rte_pause(); +| +- while (v == E); ++ while (v == E) ++ rte_pause(); +| +- while (v != E); ++ while (v != E) ++ rte_pause(); +) + +// Rule 6: Handle negated conditions +@fix_negated@ +expression ptr, val; +@@ + +( +- while (!rte_atomic32_read(ptr)); ++ while (!rte_atomic32_read(ptr)) ++ rte_pause(); +| +- while (!rte_atomic64_read(ptr)); ++ while (!rte_atomic64_read(ptr)) ++ rte_pause(); +| +- while (!rte_atomic_load_explicit(ptr, val)); ++ while (!rte_atomic_load_explicit(ptr, val)) ++ rte_pause(); +) -- 2.51.0

