| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef ART_LIBARTBASE_BASE_UTILS_H_ |
| #define ART_LIBARTBASE_BASE_UTILS_H_ |
| |
| #include <pthread.h> |
| #include <stdlib.h> |
| |
| #include <random> |
| #include <string> |
| |
| #include <android-base/logging.h> |
| #include <android-base/parseint.h> |
| |
| #include "casts.h" |
| #include "globals.h" |
| #include "macros.h" |
| #include "pointer_size.h" |
| |
| #if defined(__linux__) |
| #include <sys/utsname.h> |
| #endif |
| |
| namespace art { |
| |
| static inline uint32_t PointerToLowMemUInt32(const void* p) { |
| uintptr_t intp = reinterpret_cast<uintptr_t>(p); |
| DCHECK_LE(intp, 0xFFFFFFFFU); |
| return intp & 0xFFFFFFFFU; |
| } |
| |
| // Returns a human-readable size string such as "1MB". |
| std::string PrettySize(uint64_t size_in_bytes); |
| |
| // Splits a string using the given separator character into a vector of |
| // strings. Empty strings will be omitted. |
| template<typename StrIn, typename Str> |
| void Split(const StrIn& s, char separator, std::vector<Str>* out_result); |
| |
| template<typename Str> |
| void Split(const Str& s, char separator, size_t len, Str* out_result); |
| |
| template<typename StrIn, typename Str, size_t kLen> |
| void Split(const StrIn& s, char separator, std::array<Str, kLen>* out_result) { |
| Split<Str>(Str(s), separator, kLen, &((*out_result)[0])); |
| } |
| |
| // Returns the calling thread's tid. (The C libraries don't expose this.) |
| uint32_t GetTid(); |
| |
| // Returns the given thread's name. |
| std::string GetThreadName(pid_t tid); |
| |
| // Sets the pthread name of the current thread. The name may be truncated to an |
| // implementation-defined limit. |
| void SetThreadName(const char* thread_name); |
| |
| // Sets the pthread name of the given thread. The name may be truncated to an |
| // implementation-defined limit. Does nothing if not supported by the OS. |
| void SetThreadName(pthread_t thr, const char* thread_name); |
| |
| // Reads data from "/proc/self/task/${tid}/stat". |
| void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu); |
| |
| class VoidFunctor { |
| public: |
| template <typename A> |
| inline void operator()([[maybe_unused]] A a) const {} |
| |
| template <typename A, typename B> |
| inline void operator()([[maybe_unused]] A a, [[maybe_unused]] B b) const {} |
| |
| template <typename A, typename B, typename C> |
| inline void operator()([[maybe_unused]] A a, [[maybe_unused]] B b, [[maybe_unused]] C c) const {} |
| }; |
| |
| static inline const void* EntryPointToCodePointer(const void* entry_point) { |
| uintptr_t code = reinterpret_cast<uintptr_t>(entry_point); |
| // TODO: Make this Thumb2 specific. It is benign on other architectures as code is always at |
| // least 2 byte aligned. |
| code &= ~0x1; |
| return reinterpret_cast<const void*>(code); |
| } |
| |
| #if defined(__BIONIC__) |
| struct Arc4RandomGenerator { |
| using result_type = uint32_t; |
| static constexpr uint32_t min() { return std::numeric_limits<uint32_t>::min(); } |
| static constexpr uint32_t max() { return std::numeric_limits<uint32_t>::max(); } |
| uint32_t operator() () { return arc4random(); } |
| }; |
| using RNG = Arc4RandomGenerator; |
| #else |
| using RNG = std::random_device; |
| #endif |
| |
| template <typename T> |
| static T GetRandomNumber(T min, T max) { |
| CHECK_LT(min, max); |
| std::uniform_int_distribution<T> dist(min, max); |
| RNG rng; |
| return dist(rng); |
| } |
| |
| // Sleep forever and never come back. |
| NO_RETURN void SleepForever(); |
| |
| // Flush CPU caches. Returns true on success, false if flush failed. |
| WARN_UNUSED bool FlushCpuCaches(void* begin, void* end); |
| |
| #if defined(__linux__) |
| bool IsKernelVersionAtLeast(int reqd_major, int reqd_minor); |
| #endif |
| |
| // On some old kernels, a cache operation may segfault. |
| WARN_UNUSED bool CacheOperationsMaySegFault(); |
| |
| // Is the execution environment on a virtual machine? See ART_TEST_ON_VM. |
| WARN_UNUSED bool RunningOnVM(); |
| |
| // Is the execution environment on a single-board computer? See ART_TEST_ON_SBC. |
| WARN_UNUSED bool RunningOnSBC(); |
| |
| template <typename Func, typename... Args> |
| static inline void CheckedCall(const Func& function, const char* what, Args... args) { |
| int rc = function(args...); |
| if (UNLIKELY(rc != 0)) { |
| PLOG(FATAL) << "Checked call failed for " << what; |
| } |
| } |
| |
| // Forces the compiler to emit a load instruction, but discards the value. |
| // Useful when dealing with memory paging. |
| template <typename T> |
| inline void ForceRead(const T* pointer) { |
| static_cast<void>(*const_cast<volatile T*>(pointer)); |
| } |
| |
| // Lookup value for a given key in /proc/self/status. Keys and values are separated by a ':' in |
| // the status file. Returns value found on success and "<unknown>" if the key is not found or |
| // there is an I/O error. |
| std::string GetProcessStatus(const char* key); |
| |
| // Copy a prefix of /proc/pid/task/tid/stat of the given length into buf. Return the number of |
| // bytes actually read, 0 on error. |
| size_t GetOsThreadStat(pid_t tid, char* buf, size_t len); |
| |
| // Return a short prefix of /proc/pid/task/tid/stat as quickly and robustly as possible. Used for |
| // debugging timing issues and possibly issues with /proc itself. Always atomic. |
| std::string GetOsThreadStatQuick(pid_t tid); |
| |
| // Given a /proc/.../stat string or prefix, such as those returned by the above, return the single |
| // character representation of the thread state from that string, or '?' if it can't be found. |
| char GetStateFromStatString(const std::string& stat_output); |
| |
| // Return a concatenation of the output of GetOsThreadStatQuick(tid) for all other tids. |
| // Less robust against concurrent change, but individual stat strings should still always |
| // be consistent. Called only when we are nearly certain to crash anyway. |
| std::string GetOtherThreadOsStats(); |
| |
| // Retrieve the first 3 fields of each of the sum and full lines in /proc/pressure/io, and |
| // combine them into a string. Returns an empty string if something goes wrong, including the |
| // common case in which we don't have permission to read /proc/pressure/io. |
| std::string GetOSPressureIOSummary(); |
| |
| // Retrieve the first line from /proc/diskstats whose device name starts with disk_name, and copy |
| // the result, except for major and minor device number, into buf. If the fields in the result are |
| // numbered starting with 0, reulting field numbers match those in the kernel iostats.rst file. |
| // Return the number of characters in the resulting buffer. |
| // Note: Likely to fail and return 0 for normal unprivileged Android processes. |
| size_t GetOSDiskStats(const char* disk_name, char* buf, size_t len); |
| |
| // Encapulates the /proc/diskstats fields we currently consider the most interesting: |
| // See iostats.rst for field descriptions. |
| // Field 8: milliseconds spent writing. |
| // Field 10: milliseconds spent doing IO. |
| // Field 17: milliseconds spent flushing. |
| // Field 9: IOs in progress. |
| // |
| // Note that the first 3 really require two observations to be meaningful. |
| // We assign only those values we actually find. |
| // |
| // These fields are written by the kernel as unsigned int's, and could theoretically wrap. |
| struct ConciseDiskStats { |
| unsigned int write_millis_; |
| unsigned int io_millis_; |
| unsigned int flush_millis_; |
| unsigned int in_progress_; |
| |
| // Construct ConciseDiskStats representing the current statistics for disk_name. |
| // If this fails. e.g. because /proc/diskstats is not readable (likely on Android), then all |
| // fields are zero. It's possible flush_millis_ is not supported, and will always be zero, even |
| // if the other fields are nonzero. If disk_name is nullptr, leave all fields zeroed. |
| explicit ConciseDiskStats(const char* disk_name); |
| |
| // Return a string representing the evolution of 'this' from 'earlier'. These should correspond |
| // to the same disk. This is arguably the only meaningful way to print results. |
| // Returns an empty string if the information is unavailable. |
| std::string SummarizeDiff(ConciseDiskStats earlier); |
| |
| bool IsEmpty() { return io_millis_ == 0; } |
| }; |
| |
| } // namespace art |
| |
| #endif // ART_LIBARTBASE_BASE_UTILS_H_ |