• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
45 namespace art {
46 
47 using android::base::ReadFileToString;
48 using android::base::StringAppendF;
49 using android::base::StringPrintf;
50 
GetTid()51 pid_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 
GetThreadName(pid_t tid)63 std::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 
PrettySize(int64_t byte_count)74 std::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 
Split(const std::string & s,char separator,std::vector<std::string> * result)100 void 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 
SetThreadName(const char * thread_name)116 void 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 
GetTaskStats(pid_t tid,char * state,int * utime,int * stime,int * task_cpu)148 void 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 
ParseStringAfterChar(const std::string & s,char c,std::string * parsed_value,UsageFn Usage)166 static 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 
ParseDouble(const std::string & option,char after_char,double min,double max,double * parsed_value,UsageFn Usage)178 void 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 
SleepForever()205 void SleepForever() {
206   while (true) {
207     usleep(1000000);
208   }
209 }
210 
211 }  // namespace art
212