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/sanitizer_common/sanitizer_linux_libcdep.cc | |
parent | f5c4e6980b9a03990cbe80ce7eb85029fd9b37de (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/sanitizer_common/sanitizer_linux_libcdep.cc')
-rw-r--r-- | lib/sanitizer_common/sanitizer_linux_libcdep.cc | 68 |
1 files changed, 68 insertions, 0 deletions
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 |