diff options
author | Kostya Kortchinsky <kostyak@google.com> | 2017-11-21 21:14:00 +0000 |
---|---|---|
committer | Kostya Kortchinsky <kostyak@google.com> | 2017-11-21 21:14:00 +0000 |
commit | 8d1ef4a759edc138efdfab9c86047739fab8a536 (patch) | |
tree | cf71bb163e1b7ccb5ebc429352d6ce8661eeb0b9 /lib | |
parent | f5c4e6980b9a03990cbe80ce7eb85029fd9b37de (diff) | |
download | compiler-rt-8d1ef4a759edc138efdfab9c86047739fab8a536.tar.gz |
[scudo] Make getNumberOfCPUs Fuchsia compliant v2
Summary:
This change allows Fuchsia to boot properly using the Scudo allocator.
A first version of this commit was reverted by rL317834 because it broke Android
builds for toolchains generated with older NDKs. This commit introduces a
fall back to solve that issue.
Reviewers: cryptoad, krytarowski, rnk, alekseyshl
Reviewed By: cryptoad, krytarowski, alekseyshl
Subscribers: llvm-commits, srhines, kubamracek, krytarowski
Differential Revision: https://reviews.llvm.org/D40121
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@318802 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.cc | 1 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.h | 9 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_fuchsia.cc | 4 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_linux_libcdep.cc | 68 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_mac.cc | 5 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_win.cc | 5 | ||||
-rw-r--r-- | lib/scudo/scudo_tsd_shared.cpp | 9 |
7 files changed, 93 insertions, 8 deletions
diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc index 87e04240a..ae26d5efc 100644 --- a/lib/sanitizer_common/sanitizer_common.cc +++ b/lib/sanitizer_common/sanitizer_common.cc @@ -26,6 +26,7 @@ const char *SanitizerToolName = "SanitizerTool"; atomic_uint32_t current_verbosity; uptr PageSizeCached; +u32 NumberOfCPUsCached; // PID of the tracer task in StopTheWorld. It shares the address space with the // main process, but has a different PID and thus requires special handling. diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index 92ea4876c..2633a9816 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -932,6 +932,15 @@ void CheckNoDeepBind(const char *filename, int flag); // be used to seed a PRNG. Defaults to blocking like the underlying syscall. bool GetRandom(void *buffer, uptr length, bool blocking = true); +// Returns the number of logical processors on the system. +u32 GetNumberOfCPUs(); +extern u32 NumberOfCPUsCached; +INLINE u32 GetNumberOfCPUsCached() { + if (!NumberOfCPUsCached) + NumberOfCPUsCached = GetNumberOfCPUs(); + return NumberOfCPUsCached; +} + } // namespace __sanitizer inline void *operator new(__sanitizer::operator_new_size_type size, diff --git a/lib/sanitizer_common/sanitizer_fuchsia.cc b/lib/sanitizer_common/sanitizer_fuchsia.cc index c130c10c2..23df9aad5 100644 --- a/lib/sanitizer_common/sanitizer_fuchsia.cc +++ b/lib/sanitizer_common/sanitizer_fuchsia.cc @@ -528,6 +528,10 @@ bool GetRandom(void *buffer, uptr length, bool blocking) { return true; } +u32 GetNumberOfCPUs() { + return zx_system_get_num_cpus(); +} + } // namespace __sanitizer using namespace __sanitizer; // NOLINT diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index 6fc1396ab..f89c93a9d 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -37,15 +37,30 @@ #if SANITIZER_FREEBSD #include <pthread_np.h> #include <osreldate.h> +#include <sys/sysctl.h> #define pthread_getattr_np pthread_attr_get_np #endif +#if SANITIZER_NETBSD +#include <sys/sysctl.h> +#endif + #if SANITIZER_LINUX #include <sys/prctl.h> #endif #if SANITIZER_ANDROID #include <android/api-level.h> +#if !defined(CPU_COUNT) && !defined(__aarch64__) +#include <dirent.h> +#include <fcntl.h> +struct __sanitizer::linux_dirent { + long d_ino; + off_t d_off; + unsigned short d_reclen; + char d_name[]; +}; +#endif #endif #if !SANITIZER_ANDROID @@ -532,6 +547,59 @@ uptr GetRSS() { return rss * GetPageSizeCached(); } +// sysconf(_SC_NPROCESSORS_{CONF,ONLN}) cannot be used as they allocate memory. +u32 GetNumberOfCPUs() { +#if SANITIZER_FREEBSD || SANITIZER_NETBSD + u32 ncpu; + int req[2]; + size_t len = sizeof(ncpu); + req[0] = CTL_HW; + req[1] = HW_NCPU; + CHECK_EQ(sysctl(req, 2, &ncpu, &len, NULL, 0), 0); + return ncpu; +#elif SANITIZER_ANDROID && !defined(CPU_COUNT) && !defined(__aarch64__) + // Fall back to /sys/devices/system/cpu on Android when cpu_set_t doesn't + // exist in sched.h. That is the case for toolchains generated with older + // NDKs. + // This code doesn't work on AArch64 because internal_getdents makes use of + // the 64bit getdents syscall, but cpu_set_t seems to always exist on AArch64. + uptr fd = internal_open("/sys/devices/system/cpu", O_RDONLY | O_DIRECTORY); + if (internal_iserror(fd)) + return 0; + InternalScopedBuffer<u8> buffer(4096); + uptr bytes_read = buffer.size(); + uptr n_cpus = 0; + u8 *d_type; + struct linux_dirent *entry = (struct linux_dirent *)&buffer[bytes_read]; + while (true) { + if ((u8 *)entry >= &buffer[bytes_read]) { + bytes_read = internal_getdents(fd, (struct linux_dirent *)buffer.data(), + buffer.size()); + if (internal_iserror(bytes_read) || !bytes_read) + break; + entry = (struct linux_dirent *)buffer.data(); + } + d_type = (u8 *)entry + entry->d_reclen - 1; + if (d_type >= &buffer[bytes_read] || + (u8 *)&entry->d_name[3] >= &buffer[bytes_read]) + break; + if (entry->d_ino != 0 && *d_type == DT_DIR) { + if (entry->d_name[0] == 'c' && entry->d_name[1] == 'p' && + entry->d_name[2] == 'u' && + entry->d_name[3] >= '0' && entry->d_name[3] <= '9') + n_cpus++; + } + entry = (struct linux_dirent *)(((u8 *)entry) + entry->d_reclen); + } + internal_close(fd); + return n_cpus; +#else + cpu_set_t CPUs; + CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0); + return CPU_COUNT(&CPUs); +#endif +} + #if SANITIZER_LINUX # if SANITIZER_ANDROID diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index 195a52c47..a43260f84 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -1004,6 +1004,11 @@ bool GetRandom(void *buffer, uptr length, bool blocking) { UNIMPLEMENTED(); } +// FIXME: implement on this platform. +u32 GetNumberOfCPUs() { + UNIMPLEMENTED(); +} + } // namespace __sanitizer #endif // SANITIZER_MAC diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc index 0d72b494d..fab2babea 100644 --- a/lib/sanitizer_common/sanitizer_win.cc +++ b/lib/sanitizer_common/sanitizer_win.cc @@ -1101,6 +1101,11 @@ bool GetRandom(void *buffer, uptr length, bool blocking) { UNIMPLEMENTED(); } +// FIXME: implement on this platform. +u32 GetNumberOfCPUs() { + UNIMPLEMENTED(); +} + } // namespace __sanitizer #endif // _WIN32 diff --git a/lib/scudo/scudo_tsd_shared.cpp b/lib/scudo/scudo_tsd_shared.cpp index 191c9ff13..3e13e5d3a 100644 --- a/lib/scudo/scudo_tsd_shared.cpp +++ b/lib/scudo/scudo_tsd_shared.cpp @@ -24,17 +24,10 @@ static atomic_uint32_t CurrentIndex; static ScudoTSD *TSDs; static u32 NumberOfTSDs; -// sysconf(_SC_NPROCESSORS_{CONF,ONLN}) cannot be used as they allocate memory. -static u32 getNumberOfCPUs() { - cpu_set_t CPUs; - CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0); - return CPU_COUNT(&CPUs); -} - static void initOnce() { CHECK_EQ(pthread_key_create(&PThreadKey, NULL), 0); initScudo(); - NumberOfTSDs = Min(Max(1U, getNumberOfCPUs()), + NumberOfTSDs = Min(Max(1U, GetNumberOfCPUsCached()), static_cast<u32>(SCUDO_SHARED_TSD_POOL_SIZE)); TSDs = reinterpret_cast<ScudoTSD *>( MmapOrDie(sizeof(ScudoTSD) * NumberOfTSDs, "ScudoTSDs")); |