@@ -77,6 +77,15 @@ struct callback_status {
7777static callback_status notifiers[2 ];
7878static hsa_amd_memory_pool_t pool;
7979
80+ #ifdef ROCRTST_ASAN
81+ // ASAN defers the real free (and thus the notifier) via its quarantine; drain
82+ // it so callbacks have run before we check them.
83+ extern " C" void __sanitizer_purge_allocator (void );
84+ static inline void DrainAsanQuarantine () { __sanitizer_purge_allocator (); }
85+ #else
86+ static inline void DrainAsanQuarantine () {}
87+ #endif
88+
8089#define REGISTER (ptr, callback, i ) \
8190 do { \
8291 notifiers[i].callback_status = 0 ; \
@@ -94,8 +103,12 @@ static void call(void* ptr, void* user) {
94103static void doublefree (void * ptr, void * user) {
95104 call (ptr, user);
96105
106+ #ifndef ROCRTST_ASAN
107+ // Skip under ASAN: this runs during a quarantine drain, where a second free
108+ // trips the sanitizer's own double-free report before ROCr can return.
97109 hsa_status_t status = hsa_amd_memory_pool_free (ptr);
98110 ASSERT_EQ (HSA_STATUS_ERROR_INVALID_ALLOCATION , status) << " Double free did not return an error." ;
111+ #endif
99112}
100113
101114static void recursive (void * ptr, void * user) {
@@ -106,7 +119,11 @@ static void recursive(void* ptr, void* user) {
106119 ASSERT_EQ (HSA_STATUS_SUCCESS , status) << " Memory allocation failure." ;
107120 REGISTER (ptr, call, 1 );
108121 hsa_amd_memory_pool_free (ptr);
122+ #ifndef ROCRTST_ASAN
123+ // Skip under ASAN: the inner free can't be drained re-entrantly from within
124+ // a drain, so its notifier fires later (at the next drain/teardown).
109125 ASSERT_EQ (1 , notifiers[1 ].callback_status ) << " Callback not executed." ;
126+ #endif
110127}
111128
112129DeallocationNotifierTest::DeallocationNotifierTest () : TestBase() {
@@ -187,6 +204,7 @@ void DeallocationNotifierTest::TestDeallocationNotifier(void) {
187204 REGISTER (ptr, call, 0 );
188205 status = hsa_amd_memory_pool_free (ptr);
189206 ASSERT_EQ (HSA_STATUS_SUCCESS , status) << " Memory free failure." ;
207+ DrainAsanQuarantine ();
190208 ASSERT_EQ (1 , notifiers[0 ].callback_status ) << " Callback not executed." ;
191209
192210 // Re-allocate, free. No callback should be invoked.
@@ -203,6 +221,7 @@ void DeallocationNotifierTest::TestDeallocationNotifier(void) {
203221 REGISTER ((char *)ptr + 1024 , call, 0 );
204222 status = hsa_amd_memory_pool_free (ptr);
205223 ASSERT_EQ (HSA_STATUS_SUCCESS , status) << " Memory free failure." ;
224+ DrainAsanQuarantine ();
206225 ASSERT_EQ (1 , notifiers[0 ].callback_status ) << " Callback not executed." ;
207226
208227 // Allocate, Register, Deregister, Free. No callback should be invoked.
@@ -222,6 +241,7 @@ void DeallocationNotifierTest::TestDeallocationNotifier(void) {
222241 REGISTER ((char *)ptr + 1024 , call, 1 );
223242 status = hsa_amd_memory_pool_free (ptr);
224243 ASSERT_EQ (HSA_STATUS_SUCCESS , status) << " Memory free failure." ;
244+ DrainAsanQuarantine ();
225245 ASSERT_EQ (1 , notifiers[0 ].callback_status ) << " Callback not executed." ;
226246 ASSERT_EQ (1 , notifiers[1 ].callback_status ) << " Callback not executed." ;
227247
@@ -242,6 +262,7 @@ void DeallocationNotifierTest::TestDeallocationNotifier(void) {
242262 REGISTER (ptr, call, 0 );
243263 status = hsa_amd_memory_pool_free (ptr);
244264 ASSERT_EQ (HSA_STATUS_SUCCESS , status) << " Memory free failure." ;
265+ DrainAsanQuarantine ();
245266 ASSERT_EQ (1 , notifiers[0 ].callback_status ) << " Callback not executed." ;
246267
247268 // Allocate multiple fragments, register, free. Free order should be respected by callbacks.
@@ -252,10 +273,12 @@ void DeallocationNotifierTest::TestDeallocationNotifier(void) {
252273 REGISTER (ptr0, call, 1 );
253274 status = hsa_amd_memory_pool_free (ptr0);
254275 ASSERT_EQ (HSA_STATUS_SUCCESS , status) << " Memory free failure." ;
276+ DrainAsanQuarantine ();
255277 ASSERT_EQ (1 , notifiers[1 ].callback_status ) << " Callback not executed." ;
256278 ASSERT_EQ (0 , notifiers[0 ].callback_status ) << " Callback executed improperly." ;
257279 status = hsa_amd_memory_pool_free (ptr);
258280 ASSERT_EQ (HSA_STATUS_SUCCESS , status) << " Memory free failure." ;
281+ DrainAsanQuarantine ();
259282 ASSERT_EQ (1 , notifiers[0 ].callback_status ) << " Callback not executed." ;
260283
261284 // Allocate, register, free, with double free in callback. Callbacks should not be able to free
@@ -265,6 +288,7 @@ void DeallocationNotifierTest::TestDeallocationNotifier(void) {
265288 REGISTER (ptr, doublefree, 0 );
266289 status = hsa_amd_memory_pool_free (ptr);
267290 ASSERT_EQ (HSA_STATUS_SUCCESS , status) << " Memory free failure." ;
291+ DrainAsanQuarantine ();
268292 ASSERT_EQ (1 , notifiers[0 ].callback_status ) << " Callback not executed." ;
269293
270294 // Allocate, register, free, with allocate, register, free in callback. Callbacks should nest and
@@ -274,5 +298,6 @@ void DeallocationNotifierTest::TestDeallocationNotifier(void) {
274298 REGISTER (ptr, recursive, 0 );
275299 status = hsa_amd_memory_pool_free (ptr);
276300 ASSERT_EQ (HSA_STATUS_SUCCESS , status) << " Memory free failure." ;
301+ DrainAsanQuarantine ();
277302 ASSERT_EQ (1 , notifiers[0 ].callback_status ) << " Callback not executed." ;
278303}
0 commit comments