llvm-project/compiler-rt/lib/scudo/scudo_tls_android.cpp
Kostya Kortchinsky 0ce4999002 [scudo] Change aligned alloc functions to be more compliant & perf changes
Summary:
We were not following the `man` documented behaviors for invalid arguments to
`memalign` and associated functions. Using `CHECK` for those was a bit extreme,
so we relax the behavior to return null pointers as expected when this happens.
Adapt the associated test.

I am using this change also to change a few more minor performance improvements:
- mark as `UNLIKELY` a bunch of unlikely conditions;
- the current `CHECK` in `__sanitizer::RoundUpTo` is redundant for us in *all*
  calls. So I am introducing our own version without said `CHECK`.
- change our combined allocator `GetActuallyAllocatedSize`. We already know if
  the pointer is from the Primary or Secondary, so the `PointerIsMine` check is
  redundant as well, and costly for the 32-bit Primary. So we get the size by
  directly using the available Primary functions.

Finally, change a `int` to `uptr` to avoid a warning/error when compiling on
Android.

Reviewers: alekseyshl

Reviewed By: alekseyshl

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D34782

llvm-svn: 306698
2017-06-29 16:45:20 +00:00

96 lines
3.3 KiB
C++

//===-- scudo_tls_android.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// Scudo thread local structure implementation for Android.
///
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_platform.h"
#if SANITIZER_LINUX && SANITIZER_ANDROID
#include "scudo_tls.h"
#include <pthread.h>
namespace __scudo {
static pthread_once_t GlobalInitialized = PTHREAD_ONCE_INIT;
static pthread_key_t PThreadKey;
static atomic_uint32_t ThreadContextCurrentIndex;
static ScudoThreadContext *ThreadContexts;
static uptr NumberOfContexts;
// sysconf(_SC_NPROCESSORS_{CONF,ONLN}) cannot be used as they allocate memory.
static uptr getNumberOfCPUs() {
cpu_set_t CPUs;
CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0);
return CPU_COUNT(&CPUs);
}
static void initOnce() {
// Hack: TLS_SLOT_TSAN was introduced in N. To be able to use it on M for
// testing, we create an unused key. Since the key_data array follows the tls
// array, it basically gives us the extra entry we need.
// TODO(kostyak): remove and restrict to N and above.
CHECK_EQ(pthread_key_create(&PThreadKey, NULL), 0);
initScudo();
NumberOfContexts = getNumberOfCPUs();
ThreadContexts = reinterpret_cast<ScudoThreadContext *>(
MmapOrDie(sizeof(ScudoThreadContext) * NumberOfContexts, __func__));
for (uptr i = 0; i < NumberOfContexts; i++)
ThreadContexts[i].init();
}
void initThread() {
pthread_once(&GlobalInitialized, initOnce);
// Initial context assignment is done in a plain round-robin fashion.
u32 Index = atomic_fetch_add(&ThreadContextCurrentIndex, 1,
memory_order_relaxed);
ScudoThreadContext *ThreadContext =
&ThreadContexts[Index % NumberOfContexts];
*get_android_tls_ptr() = reinterpret_cast<uptr>(ThreadContext);
}
ScudoThreadContext *getThreadContextAndLockSlow() {
ScudoThreadContext *ThreadContext;
// Go through all the contexts and find the first unlocked one.
for (u32 i = 0; i < NumberOfContexts; i++) {
ThreadContext = &ThreadContexts[i];
if (ThreadContext->tryLock()) {
*get_android_tls_ptr() = reinterpret_cast<uptr>(ThreadContext);
return ThreadContext;
}
}
// No luck, find the one with the lowest precedence, and slow lock it.
u64 Precedence = UINT64_MAX;
for (u32 i = 0; i < NumberOfContexts; i++) {
u64 SlowLockPrecedence = ThreadContexts[i].getSlowLockPrecedence();
if (SlowLockPrecedence && SlowLockPrecedence < Precedence) {
ThreadContext = &ThreadContexts[i];
Precedence = SlowLockPrecedence;
}
}
if (LIKELY(Precedence != UINT64_MAX)) {
ThreadContext->lock();
*get_android_tls_ptr() = reinterpret_cast<uptr>(ThreadContext);
return ThreadContext;
}
// Last resort (can this happen?), stick with the current one.
ThreadContext =
reinterpret_cast<ScudoThreadContext *>(*get_android_tls_ptr());
ThreadContext->lock();
return ThreadContext;
}
} // namespace __scudo
#endif // SANITIZER_LINUX && SANITIZER_ANDROID