summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKostya Kortchinsky <kostyak@google.com>2017-11-21 21:14:00 +0000
committerKostya Kortchinsky <kostyak@google.com>2017-11-21 21:14:00 +0000
commit8d1ef4a759edc138efdfab9c86047739fab8a536 (patch)
treecf71bb163e1b7ccb5ebc429352d6ce8661eeb0b9 /lib
parentf5c4e6980b9a03990cbe80ce7eb85029fd9b37de (diff)
[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.cc1
-rw-r--r--lib/sanitizer_common/sanitizer_common.h9
-rw-r--r--lib/sanitizer_common/sanitizer_fuchsia.cc4
-rw-r--r--lib/sanitizer_common/sanitizer_linux_libcdep.cc68
-rw-r--r--lib/sanitizer_common/sanitizer_mac.cc5
-rw-r--r--lib/sanitizer_common/sanitizer_win.cc5
-rw-r--r--lib/scudo/scudo_tsd_shared.cpp9
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"));