Skip to content

Commit

Permalink
[asan] Switch initialization to "double-checked locking"
Browse files Browse the repository at this point in the history
This allows to remove `asan_init_is_running` which likely had a data
race.

Simplifies llvm#74086 and reduces a difference between platforms.

Reviewers: zacklj89, eugenis, dvyukov

Reviewed By: zacklj89, dvyukov

Pull Request: llvm#74387
  • Loading branch information
vitalybuka authored Dec 12, 2023
1 parent 8227072 commit 9567b33
Showing 1 changed file with 25 additions and 24 deletions.
49 changes: 25 additions & 24 deletions compiler-rt/lib/asan/asan_rtl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,16 @@ static void CheckUnwind() {
}

// -------------------------- Globals --------------------- {{{1
static int asan_inited = 0;
static int asan_init_is_running = 0;
static StaticSpinMutex asan_inited_mutex;
static atomic_uint8_t asan_inited = {0};

static void SetAsanInited() { asan_inited = 1; }

static void SetAsanInitIsRunning(u32 val) { asan_init_is_running = val; }

bool AsanInited() { return asan_inited == 1; }
static void SetAsanInited() {
atomic_store(&asan_inited, 1, memory_order_release);
}

static bool AsanInitIsRunning() { return asan_init_is_running == 1; }
bool AsanInited() {
return atomic_load(&asan_inited, memory_order_acquire) == 1;
}

bool replace_intrin_cached;

Expand Down Expand Up @@ -390,12 +390,10 @@ void PrintAddressSpaceLayout() {
kHighShadowBeg > kMidMemEnd);
}

static void AsanInitInternal() {
static bool AsanInitInternal() {
if (LIKELY(AsanInited()))
return;
return true;
SanitizerToolName = "AddressSanitizer";
CHECK(!AsanInitIsRunning() && "ASan init calls itself!");
SetAsanInitIsRunning(1);

CacheBinaryName();

Expand All @@ -408,9 +406,8 @@ static void AsanInitInternal() {
// Stop performing init at this point if we are being loaded via
// dlopen() and the platform supports it.
if (SANITIZER_SUPPORTS_INIT_FOR_DLOPEN && UNLIKELY(HandleDlopenInit())) {
SetAsanInitIsRunning(0);
VReport(1, "AddressSanitizer init is being performed for dlopen().\n");
return;
return false;
}

AsanCheckIncompatibleRT();
Expand Down Expand Up @@ -471,7 +468,6 @@ static void AsanInitInternal() {
// should be set to 1 prior to initializing the threads.
replace_intrin_cached = flags()->replace_intrin;
SetAsanInited();
SetAsanInitIsRunning(0);

if (flags()->atexit)
Atexit(asan_atexit);
Expand Down Expand Up @@ -515,22 +511,27 @@ static void AsanInitInternal() {
VReport(1, "AddressSanitizer Init done\n");

WaitForDebugger(flags()->sleep_after_init, "after init");

return true;
}

// Initialize as requested from some part of ASan runtime library (interceptors,
// allocator, etc).
void AsanInitFromRtl() {
CHECK(!AsanInitIsRunning());
if (UNLIKELY(!AsanInited()))
AsanInitInternal();
if (LIKELY(AsanInited()))
return;
SpinMutexLock lock(&asan_inited_mutex);
AsanInitInternal();
}

bool TryAsanInitFromRtl() {
if (UNLIKELY(AsanInitIsRunning()))
if (LIKELY(AsanInited()))
return true;
if (!asan_inited_mutex.TryLock())
return false;
if (UNLIKELY(!AsanInited()))
AsanInitInternal();
return true;
bool result = AsanInitInternal();
asan_inited_mutex.Unlock();
return result;
}

#if ASAN_DYNAMIC
Expand Down Expand Up @@ -603,7 +604,7 @@ static void UnpoisonFakeStack() {
using namespace __asan;

void NOINLINE __asan_handle_no_return() {
if (AsanInitIsRunning())
if (UNLIKELY(!AsanInited()))
return;

if (!PlatformUnpoisonStacks())
Expand Down Expand Up @@ -633,7 +634,7 @@ void NOINLINE __asan_set_death_callback(void (*callback)(void)) {
// We use this call as a trigger to wake up ASan from deactivated state.
void __asan_init() {
AsanActivate();
AsanInitInternal();
AsanInitFromRtl();
}

void __asan_version_mismatch_check() {
Expand Down

0 comments on commit 9567b33

Please sign in to comment.