2222#include " threadFilter.h"
2323#include " arch.h"
2424#include " os.h"
25+ #include " profiler.h"
26+ #include " wallclock/wallClock.h"
2527#include < cassert>
2628#include < cstdlib>
2729#include < cstdio>
@@ -77,7 +79,7 @@ void ThreadFilter::initializeChunk(int chunk_idx) {
7779 // Allocate and initialize new chunk completely before swapping
7880 ChunkStorage* new_chunk = new ChunkStorage ();
7981 for (auto & slot : new_chunk->slots ) {
80- slot.value .store (-1 , std::memory_order_relaxed);
82+ slot.value . java_tid .store (-1 , std::memory_order_relaxed);
8183 }
8284
8385 // Try to install it atomically
@@ -145,6 +147,11 @@ void ThreadFilter::initFreeList() {
145147 }
146148}
147149
150+ bool ThreadFilter::filter_by_os_tid () {
151+ BaseWallClock* wall_clock = Profiler::instance ()->wallEngine ();
152+ return wall_clock == nullptr || wall_clock->mode () == BaseWallClock::Mode::ASGCT ;
153+ }
154+
148155bool ThreadFilter::accept (SlotID slot_id) const {
149156 // Fast path: if disabled, accept everything (relaxed to avoid fences on hot path)
150157 if (unlikely (!_enabled.load (std::memory_order_relaxed))) {
@@ -158,12 +165,16 @@ bool ThreadFilter::accept(SlotID slot_id) const {
158165 // This is not a fast path like the add operation.
159166 ChunkStorage* chunk = _chunks[chunk_idx].load (std::memory_order_acquire);
160167 if (likely (chunk != nullptr )) {
161- return chunk->slots [slot_idx].value .load (std::memory_order_relaxed) != -1 ;
168+ if (filter_by_os_tid ()) {
169+ return chunk->slots [slot_idx].value .os_tid .load (std::memory_order_relaxed) != -1 ;
170+ } else {
171+ return chunk->slots [slot_idx].value .java_tid .load (std::memory_order_relaxed) != -1 ;
172+ }
162173 }
163174 return false ;
164175}
165176
166- void ThreadFilter::add (long tid , SlotID slot_id) {
177+ void ThreadFilter::add (long java_tid, int os_tid , SlotID slot_id) {
167178 // PRECONDITION: slot_id must be from registerThread() or negative
168179 // Undefined behavior for invalid positive slot_ids (performance optimization)
169180 if (slot_id < 0 ) return ;
@@ -174,7 +185,11 @@ void ThreadFilter::add(long tid, SlotID slot_id) {
174185 // Fast path: assume valid slot_id from registerThread()
175186 ChunkStorage* chunk = _chunks[chunk_idx].load (std::memory_order_acquire);
176187 if (likely (chunk != nullptr )) {
177- chunk->slots [slot_idx].value .store (tid, std::memory_order_release);
188+ if (filter_by_os_tid ()) {
189+ chunk->slots [slot_idx].value .os_tid .store (os_tid, std::memory_order_release);
190+ } else {
191+ chunk->slots [slot_idx].value .java_tid .store (java_tid, std::memory_order_release);
192+ }
178193 }
179194}
180195
@@ -195,8 +210,11 @@ void ThreadFilter::remove(SlotID slot_id) {
195210 if (unlikely (chunk == nullptr )) {
196211 return ;
197212 }
198-
199- chunk->slots [slot_idx].value .store (-1 , std::memory_order_release);
213+ if (filter_by_os_tid ()) {
214+ chunk->slots [slot_idx].value .java_tid .store (-1 , std::memory_order_release);
215+ } else {
216+ chunk->slots [slot_idx].value .os_tid .store (-1 , std::memory_order_release);
217+ }
200218}
201219
202220void ThreadFilter::unregisterThread (SlotID slot_id) {
@@ -255,12 +273,13 @@ ThreadFilter::SlotID ThreadFilter::popFromFreeList() {
255273 return -1 ; // Empty list
256274}
257275
258- void ThreadFilter::collect (std::vector<int >& tids) const {
259- tids.clear ();
276+ void ThreadFilter::collect_java_tids (std::vector<long >& java_tids) const {
277+ assert (!filter_by_os_tid ());
278+ java_tids.clear ();
260279
261280 // Reserve space for efficiency
262281 // The eventual resize is not the bottleneck, so we reserve a reasonable size
263- tids .reserve (512 );
282+ java_tids .reserve (512 );
264283
265284 // Scan only initialized chunks
266285 int num_chunks = _num_chunks.load (std::memory_order_relaxed);
@@ -271,16 +290,36 @@ void ThreadFilter::collect(std::vector<int>& tids) const {
271290 }
272291
273292 for (const auto & slot : chunk->slots ) {
274- int slot_tid = slot.value .load (std::memory_order_relaxed);
275- if (slot_tid != -1 ) {
276- tids .push_back (slot_tid );
293+ long java_tid = slot.value . java_tid .load (std::memory_order_relaxed);
294+ if (java_tid != -1 ) {
295+ java_tids .push_back (java_tid );
277296 }
278297 }
279298 }
299+ }
300+
301+ void ThreadFilter::collect_os_tids (std::vector<int >& os_tids) const {
302+ assert (!filter_by_os_tid ());
303+ os_tids.clear ();
304+
305+ // Reserve space for efficiency
306+ // The eventual resize is not the bottleneck, so we reserve a reasonable size
307+ os_tids.reserve (512 );
280308
281- // Optional: shrink if we over-reserved significantly
282- if (tids.capacity () > tids.size () * 2 ) {
283- tids.shrink_to_fit ();
309+ // Scan only initialized chunks
310+ int num_chunks = _num_chunks.load (std::memory_order_relaxed);
311+ for (int chunk_idx = 0 ; chunk_idx < num_chunks; ++chunk_idx) {
312+ ChunkStorage* chunk = _chunks[chunk_idx].load (std::memory_order_acquire);
313+ if (chunk == nullptr ) {
314+ continue ; // Skip unallocated chunks
315+ }
316+
317+ for (const auto & slot : chunk->slots ) {
318+ int os_tid = slot.value .os_tid .load (std::memory_order_relaxed);
319+ if (os_tid != -1 ) {
320+ os_tids.push_back (os_tid);
321+ }
322+ }
284323 }
285324}
286325
0 commit comments