1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "utils.h" 18 19#include <inttypes.h> 20#include <pthread.h> 21#include <sys/stat.h> 22#include <sys/syscall.h> 23#include <sys/types.h> 24#include <sys/wait.h> 25#include <unistd.h> 26 27#include <memory> 28 29#include "android-base/file.h" 30#include "android-base/stringprintf.h" 31#include "android-base/strings.h" 32 33#include "base/os.h" 34 35#if defined(__APPLE__) 36#include <crt_externs.h> 37#include <sys/syscall.h> 38#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED 39#endif 40 41#if defined(__linux__) 42#include <linux/unistd.h> 43#endif 44 45namespace art { 46 47using android::base::ReadFileToString; 48using android::base::StringAppendF; 49using android::base::StringPrintf; 50 51pid_t GetTid() { 52#if defined(__APPLE__) 53 uint64_t owner; 54 CHECK_PTHREAD_CALL(pthread_threadid_np, (nullptr, &owner), __FUNCTION__); // Requires Mac OS 10.6 55 return owner; 56#elif defined(__BIONIC__) 57 return gettid(); 58#else 59 return syscall(__NR_gettid); 60#endif 61} 62 63std::string GetThreadName(pid_t tid) { 64 std::string result; 65 // TODO: make this less Linux-specific. 66 if (ReadFileToString(StringPrintf("/proc/self/task/%d/comm", tid), &result)) { 67 result.resize(result.size() - 1); // Lose the trailing '\n'. 68 } else { 69 result = "<unknown>"; 70 } 71 return result; 72} 73 74std::string PrettySize(int64_t byte_count) { 75 // The byte thresholds at which we display amounts. A byte count is displayed 76 // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1]. 77 static const int64_t kUnitThresholds[] = { 78 0, // B up to... 79 3*1024, // KB up to... 80 2*1024*1024, // MB up to... 81 1024*1024*1024 // GB from here. 82 }; 83 static const int64_t kBytesPerUnit[] = { 1, KB, MB, GB }; 84 static const char* const kUnitStrings[] = { "B", "KB", "MB", "GB" }; 85 const char* negative_str = ""; 86 if (byte_count < 0) { 87 negative_str = "-"; 88 byte_count = -byte_count; 89 } 90 int i = arraysize(kUnitThresholds); 91 while (--i > 0) { 92 if (byte_count >= kUnitThresholds[i]) { 93 break; 94 } 95 } 96 return StringPrintf("%s%" PRId64 "%s", 97 negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]); 98} 99 100void Split(const std::string& s, char separator, std::vector<std::string>* result) { 101 const char* p = s.data(); 102 const char* end = p + s.size(); 103 while (p != end) { 104 if (*p == separator) { 105 ++p; 106 } else { 107 const char* start = p; 108 while (++p != end && *p != separator) { 109 // Skip to the next occurrence of the separator. 110 } 111 result->push_back(std::string(start, p - start)); 112 } 113 } 114} 115 116void SetThreadName(const char* thread_name) { 117 int hasAt = 0; 118 int hasDot = 0; 119 const char* s = thread_name; 120 while (*s) { 121 if (*s == '.') { 122 hasDot = 1; 123 } else if (*s == '@') { 124 hasAt = 1; 125 } 126 s++; 127 } 128 int len = s - thread_name; 129 if (len < 15 || hasAt || !hasDot) { 130 s = thread_name; 131 } else { 132 s = thread_name + len - 15; 133 } 134#if defined(__linux__) 135 // pthread_setname_np fails rather than truncating long strings. 136 char buf[16]; // MAX_TASK_COMM_LEN=16 is hard-coded in the kernel. 137 strncpy(buf, s, sizeof(buf)-1); 138 buf[sizeof(buf)-1] = '\0'; 139 errno = pthread_setname_np(pthread_self(), buf); 140 if (errno != 0) { 141 PLOG(WARNING) << "Unable to set the name of current thread to '" << buf << "'"; 142 } 143#else // __APPLE__ 144 pthread_setname_np(thread_name); 145#endif 146} 147 148void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) { 149 *utime = *stime = *task_cpu = 0; 150 std::string stats; 151 // TODO: make this less Linux-specific. 152 if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid), &stats)) { 153 return; 154 } 155 // Skip the command, which may contain spaces. 156 stats = stats.substr(stats.find(')') + 2); 157 // Extract the three fields we care about. 158 std::vector<std::string> fields; 159 Split(stats, ' ', &fields); 160 *state = fields[0][0]; 161 *utime = strtoull(fields[11].c_str(), nullptr, 10); 162 *stime = strtoull(fields[12].c_str(), nullptr, 10); 163 *task_cpu = strtoull(fields[36].c_str(), nullptr, 10); 164} 165 166static void ParseStringAfterChar(const std::string& s, 167 char c, 168 std::string* parsed_value, 169 UsageFn Usage) { 170 std::string::size_type colon = s.find(c); 171 if (colon == std::string::npos) { 172 Usage("Missing char %c in option %s\n", c, s.c_str()); 173 } 174 // Add one to remove the char we were trimming until. 175 *parsed_value = s.substr(colon + 1); 176} 177 178void ParseDouble(const std::string& option, 179 char after_char, 180 double min, 181 double max, 182 double* parsed_value, 183 UsageFn Usage) { 184 std::string substring; 185 ParseStringAfterChar(option, after_char, &substring, Usage); 186 bool sane_val = true; 187 double value; 188 if ((false)) { 189 // TODO: this doesn't seem to work on the emulator. b/15114595 190 std::stringstream iss(substring); 191 iss >> value; 192 // Ensure that we have a value, there was no cruft after it and it satisfies a sensible range. 193 sane_val = iss.eof() && (value >= min) && (value <= max); 194 } else { 195 char* end = nullptr; 196 value = strtod(substring.c_str(), &end); 197 sane_val = *end == '\0' && value >= min && value <= max; 198 } 199 if (!sane_val) { 200 Usage("Invalid double value %s for option %s\n", substring.c_str(), option.c_str()); 201 } 202 *parsed_value = value; 203} 204 205void SleepForever() { 206 while (true) { 207 usleep(1000000); 208 } 209} 210 211} // namespace art 212