@@ -275,27 +275,38 @@ class runtime_signature : public std::enable_shared_from_this<runtime_signature>
275275 std::optional<uintptr_t > scan_multithreaded (std::span<const std::byte> memory_range, scanner_func_t core_scanner) const {
276276 const unsigned int num_threads = std::thread::hardware_concurrency ();
277277 const size_t chunk_size = 65536 * 4 ;
278- const size_t min_range_for_multithread = chunk_size * num_threads;
278+ const size_t min_range_for_multithread = chunk_size;
279+
279280 if (num_threads <= 1 || memory_range.size () < min_range_for_multithread) {
280281 return (this ->*core_scanner)(memory_range, nullptr );
281282 }
283+
282284 auto & pool = get_pool ();
283285 std::vector<std::future<std::optional<uintptr_t >>> futures;
284286 auto found_flag = std::make_shared<std::atomic<bool >>(false );
285287 const size_t overlap = pattern_.size () > 1 ? pattern_.size () - 1 : 0 ;
288+
286289 for (size_t start = 0 ; start < memory_range.size (); start += chunk_size) {
290+ if (found_flag->load (std::memory_order_acquire)) {
291+ break ;
292+ }
287293 size_t end = std::min (start + chunk_size + overlap, memory_range.size ());
288294 if (start >= end || (end - start) < pattern_.size ()) continue ;
295+
289296 std::span<const std::byte> chunk = memory_range.subspan (start, end - start);
290297 futures.push_back (pool.enqueue (core_scanner, shared_from_this (), chunk, found_flag));
291298 }
299+
300+ std::optional<uintptr_t > first_result;
292301 for (auto & fut : futures) {
293302 if (auto result = fut.get (); result.has_value ()) {
294- found_flag->store (true , std::memory_order_relaxed);
295- return result;
303+ if (!first_result.has_value () || result.value () < first_result.value ()) {
304+ first_result = result;
305+ }
296306 }
297307 }
298- return std::nullopt ;
308+
309+ return first_result;
299310 }
300311#endif
301312
@@ -416,55 +427,76 @@ namespace detail {
416427
417428inline std::optional<uintptr_t > runtime_signature::scan_dynamic_anchor (std::span<const std::byte> memory_range, std::shared_ptr<std::atomic<bool >> found_flag) const {
418429 if (memory_range.size () < pattern_.size ()) return std::nullopt ;
430+
419431 auto frequencies = detail::calculate_dynamic_rarity (memory_range);
420432 auto props = detail::find_best_anchor_and_build_props (pattern_, frequencies);
421433 if (!props.has_anchor ) {
422434 return scan_forward_anchor (memory_range, found_flag);
423435 }
436+
424437 const uint8x16_t v_anchor = vdupq_n_u8 (static_cast <uint8_t >(props.anchor_byte ));
425438 const uint8x16_t v_pattern16 = vld1q_u8 (reinterpret_cast <const uint8_t *>(props.pattern16 .data ()));
426439 const uint8x16_t v_mask16 = vld1q_u8 (reinterpret_cast <const uint8_t *>(props.mask16 .data ()));
440+
427441 const std::byte* current_pos = memory_range.data ();
428- const std::byte* const end_pos = memory_range.data () + memory_range.size () - pattern_.size ();
429- const std::byte* const fast_scan_end_pos = memory_range.data () + memory_range.size () - 16 ;
442+ const std::byte* const range_end = memory_range.data () + memory_range.size ();
443+ const std::byte* const end_pos = range_end - pattern_.size ();
444+ const std::byte* const fast_scan_end_pos = (range_end >= memory_range.data () + 16 ) ? range_end - 16 : memory_range.data ();
445+
430446 while (current_pos <= fast_scan_end_pos) {
431- if (found_flag && found_flag->load (std::memory_order_relaxed)) return std::nullopt ;
447+ if (found_flag && found_flag->load (std::memory_order_acquire)) return std::nullopt ;
448+
432449#ifdef UR_ENABLE_HARDWARE_PREFETCH
433450 __builtin_prefetch (current_pos + 64 , 0 , 0 );
434451#endif
435452 const uint8x16_t v_mem = vld1q_u8 (reinterpret_cast <const uint8_t *>(current_pos));
436453 const uint8x16_t v_cmp_result = vceqq_u8 (v_mem, v_anchor);
454+
437455 if (vmaxvq_u8 (v_cmp_result) == 0 ) {
438456 current_pos += 16 ;
439457 continue ;
440458 }
459+
441460 uint8_t result_bytes[16 ];
442461 vst1q_u8 (result_bytes, v_cmp_result);
443462 for (int i = 0 ; i < 16 ; ++i) {
444463 if (result_bytes[i] == 0xFF ) {
445464 const std::byte* potential_start = current_pos + i - props.anchor_offset ;
446465 if (potential_start < memory_range.data () || potential_start > end_pos) continue ;
447- const uint8x16_t v_mem16 = vld1q_u8 (reinterpret_cast <const uint8_t *>(potential_start));
448- const uint8x16_t v_masked_mem = vandq_u8 (v_mem16, v_mask16);
449- const uint8x16_t v_verify_result = vceqq_u8 (v_masked_mem, v_pattern16);
450- if (vminvq_u8 (v_verify_result) == 0xFF ) {
451- if (pattern_.size () <= 16 || full_match_at (potential_start)) {
452- if (found_flag) found_flag->store (true , std::memory_order_relaxed);
466+ if (potential_start + pattern_.size () > range_end) continue ;
467+
468+ if (potential_start + 16 <= range_end) {
469+ const uint8x16_t v_mem16 = vld1q_u8 (reinterpret_cast <const uint8_t *>(potential_start));
470+ const uint8x16_t v_masked_mem = vandq_u8 (v_mem16, v_mask16);
471+ const uint8x16_t v_verify_result = vceqq_u8 (v_masked_mem, v_pattern16);
472+
473+ if (vminvq_u8 (v_verify_result) == 0xFF ) {
474+ if (pattern_.size () <= 16 || full_match_at (potential_start)) {
475+ if (found_flag) found_flag->store (true , std::memory_order_release);
476+ return reinterpret_cast <uintptr_t >(potential_start);
477+ }
478+ }
479+ } else {
480+ if (full_match_at (potential_start)) {
481+ if (found_flag) found_flag->store (true , std::memory_order_release);
453482 return reinterpret_cast <uintptr_t >(potential_start);
454483 }
455484 }
456485 }
457486 }
458487 current_pos += 16 ;
459488 }
460- std::span<const std::byte> tail_span{current_pos, static_cast <size_t >(memory_range.data () + memory_range.size () - current_pos)};
461- const auto scan_end_tail = tail_span.data () + tail_span.size () - pattern_.size ();
462- for (const std::byte* p = tail_span.data (); p <= scan_end_tail; ++p) {
463- if (full_match_at (p)) {
464- if (found_flag) found_flag->store (true , std::memory_order_relaxed);
465- return reinterpret_cast <uintptr_t >(p);
489+
490+ const auto scan_end_tail = range_end - pattern_.size ();
491+ while (current_pos <= scan_end_tail) {
492+ if (found_flag && found_flag->load (std::memory_order_acquire)) return std::nullopt ;
493+ if (full_match_at (current_pos)) {
494+ if (found_flag) found_flag->store (true , std::memory_order_release);
495+ return reinterpret_cast <uintptr_t >(current_pos);
466496 }
497+ current_pos++;
467498 }
499+
468500 return std::nullopt ;
469501}
470502#endif
0 commit comments