@@ -28,29 +28,50 @@ class CallTraceHashTable;
2828// Using reference parameter avoids malloc() for vector creation and copying
2929typedef std::function<void (std::unordered_set<u64 >&)> LivenessChecker;
3030
31+ /* *
32+ * Cache-aligned hazard pointer slot to eliminate false sharing.
33+ * Each slot occupies a full cache line (64 bytes) to ensure that
34+ * updates by one thread do not invalidate cache lines for other threads.
35+ */
36+ struct alignas (DEFAULT_CACHE_LINE_SIZE) HazardSlot {
37+ volatile CallTraceHashTable* pointer;
38+ char padding[DEFAULT_CACHE_LINE_SIZE - sizeof (pointer)];
39+
40+ HazardSlot () : pointer (nullptr ), padding{} {
41+ static_assert (sizeof (HazardSlot) == DEFAULT_CACHE_LINE_SIZE,
42+ " HazardSlot must be exactly one cache line" );
43+ }
44+ };
45+
3146/* *
3247 * RAII guard for hazard pointer management.
33- *
48+ *
3449 * This class encapsulates the hazard pointer mechanism used to protect CallTraceHashTable
3550 * instances from being deleted while they are being accessed by concurrent threads.
3651 *
3752 * Usage:
38- * HazardPointer guard(active_table );
39- * // active_table is now protected from deletion
53+ * HazardPointer guard(_active_table );
54+ * // _active_table is now protected from deletion
4055 * // Automatic cleanup when guard goes out of scope
4156 */
4257class HazardPointer {
4358public:
4459 static constexpr int MAX_THREADS = 8192 ;
4560 static constexpr int MAX_PROBE_DISTANCE = 32 ; // Maximum probing attempts
46-
47- static std::atomic<CallTraceHashTable*> global_hazard_list[MAX_THREADS];
48- static std::atomic<int > slot_owners[MAX_THREADS]; // Thread ID ownership verification
61+ static constexpr int BITMAP_WORDS = MAX_THREADS / 64 ; // 8192 / 64 = 128 words
62+
63+ static HazardSlot global_hazard_list[MAX_THREADS];
64+ static int slot_owners[MAX_THREADS]; // Thread ID ownership verification
65+
66+ // Occupied slot bitmap for efficient scanning (avoids iterating 8192 empty slots)
67+ // Uses raw uint64_t with GCC atomic builtins to avoid any potential malloc on musl
68+ // Each bit represents whether the corresponding slot is occupied
69+ static uint64_t occupied_bitmap[BITMAP_WORDS];
4970
5071private:
51- bool active_ ;
52- int my_slot_ ; // This instance's assigned slot
53-
72+ bool _active ;
73+ int _my_slot ; // This instance's assigned slot
74+
5475 // Signal-safe slot assignment using thread ID hash
5576 static int getThreadHazardSlot ();
5677
@@ -66,7 +87,7 @@ class HazardPointer {
6687 HazardPointer& operator =(HazardPointer&& other) noexcept ;
6788
6889 // Check if hazard pointer is active (slot allocation succeeded)
69- bool isActive () const { return active_ ; }
90+ bool isActive () const { return _active ; }
7091
7192 // Wait for hazard pointers pointing to specific table to clear (used during shutdown)
7293 static void waitForHazardPointersToClear (CallTraceHashTable* table_to_delete);
@@ -89,20 +110,21 @@ class CallTraceStorage {
89110 // Triple-buffered storage with atomic pointers
90111 // Rotation: tmp=scratch, scratch=active, active=standby, standby=tmp
91112 // New active inherits preserved traces for continuity
92- std::atomic< CallTraceHashTable*> _active_storage;
93- std::atomic< CallTraceHashTable*> _standby_storage;
94- std::atomic< CallTraceHashTable*> _scratch_storage;
113+ volatile CallTraceHashTable* _active_storage;
114+ volatile CallTraceHashTable* _standby_storage;
115+ volatile CallTraceHashTable* _scratch_storage;
95116
96117 // Generation counter for ABA protection during table swaps
97- std::atomic< u32 > _generation_counter;
118+ u32 _generation_counter;
98119
99120 // Liveness checkers - protected by simple spinlock during registration/clear
100121 // Using vector instead of unordered_set since std::function cannot be hashed
101122 std::vector<LivenessChecker> _liveness_checkers;
102123 SpinLock _liveness_lock; // Simple atomic lock for rare liveness operations
103124
104125 // Static atomic for instance ID generation - avoids function-local static initialization issues
105- static std::atomic<u64 > _next_instance_id;
126+
127+ static u64 _next_instance_id;
106128
107129 // Lazy initialization helper to avoid global constructor
108130 static u64 getNextInstanceId ();
0 commit comments