Ninja
util.cc
Go to the documentation of this file.
1 // Copyright 2011 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "util.h"
16 
17 #ifdef __CYGWIN__
18 #include <windows.h>
19 #include <io.h>
20 #elif defined( _WIN32)
21 #include <windows.h>
22 #include <io.h>
23 #include <share.h>
24 #endif
25 
26 #include <assert.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 
36 #ifndef _WIN32
37 #include <unistd.h>
38 #include <sys/time.h>
39 #endif
40 
41 #include <vector>
42 
43 #if defined(__APPLE__) || defined(__FreeBSD__)
44 #include <sys/sysctl.h>
45 #elif defined(__SVR4) && defined(__sun)
46 #include <unistd.h>
47 #include <sys/loadavg.h>
48 #elif defined(_AIX) && !defined(__PASE__)
49 #include <libperfstat.h>
50 #elif defined(linux) || defined(__GLIBC__)
51 #include <sys/sysinfo.h>
52 #include <fstream>
53 #include <map>
54 #include "string_piece_util.h"
55 #endif
56 
57 #if defined(__FreeBSD__)
58 #include <sys/cpuset.h>
59 #endif
60 
61 #include "edit_distance.h"
62 
63 using namespace std;
64 
65 void Fatal(const char* msg, ...) {
66  va_list ap;
67  fprintf(stderr, "ninja: fatal: ");
68  va_start(ap, msg);
69  vfprintf(stderr, msg, ap);
70  va_end(ap);
71  fprintf(stderr, "\n");
72 #ifdef _WIN32
73  // On Windows, some tools may inject extra threads.
74  // exit() may block on locks held by those threads, so forcibly exit.
75  fflush(stderr);
76  fflush(stdout);
77  ExitProcess(1);
78 #else
79  exit(1);
80 #endif
81 }
82 
83 void Warning(const char* msg, va_list ap) {
84  fprintf(stderr, "ninja: warning: ");
85  vfprintf(stderr, msg, ap);
86  fprintf(stderr, "\n");
87 }
88 
89 void Warning(const char* msg, ...) {
90  va_list ap;
91  va_start(ap, msg);
92  Warning(msg, ap);
93  va_end(ap);
94 }
95 
96 void Error(const char* msg, va_list ap) {
97  fprintf(stderr, "ninja: error: ");
98  vfprintf(stderr, msg, ap);
99  fprintf(stderr, "\n");
100 }
101 
102 void Error(const char* msg, ...) {
103  va_list ap;
104  va_start(ap, msg);
105  Error(msg, ap);
106  va_end(ap);
107 }
108 
109 void Info(const char* msg, va_list ap) {
110  fprintf(stdout, "ninja: ");
111  vfprintf(stdout, msg, ap);
112  fprintf(stdout, "\n");
113 }
114 
115 void Info(const char* msg, ...) {
116  va_list ap;
117  va_start(ap, msg);
118  Info(msg, ap);
119  va_end(ap);
120 }
121 
122 void CanonicalizePath(string* path, uint64_t* slash_bits) {
123  size_t len = path->size();
124  char* str = 0;
125  if (len > 0)
126  str = &(*path)[0];
127  CanonicalizePath(str, &len, slash_bits);
128  path->resize(len);
129 }
130 
131 static bool IsPathSeparator(char c) {
132 #ifdef _WIN32
133  return c == '/' || c == '\\';
134 #else
135  return c == '/';
136 #endif
137 }
138 
139 void CanonicalizePath(char* path, size_t* len, uint64_t* slash_bits) {
140  // WARNING: this function is performance-critical; please benchmark
141  // any changes you make to it.
142  if (*len == 0) {
143  return;
144  }
145 
146  const int kMaxPathComponents = 60;
147  char* components[kMaxPathComponents];
148  int component_count = 0;
149 
150  char* start = path;
151  char* dst = start;
152  const char* src = start;
153  const char* end = start + *len;
154 
155  if (IsPathSeparator(*src)) {
156 #ifdef _WIN32
157 
158  // network path starts with //
159  if (*len > 1 && IsPathSeparator(*(src + 1))) {
160  src += 2;
161  dst += 2;
162  } else {
163  ++src;
164  ++dst;
165  }
166 #else
167  ++src;
168  ++dst;
169 #endif
170  }
171 
172  while (src < end) {
173  if (*src == '.') {
174  if (src + 1 == end || IsPathSeparator(src[1])) {
175  // '.' component; eliminate.
176  src += 2;
177  continue;
178  } else if (src[1] == '.' && (src + 2 == end || IsPathSeparator(src[2]))) {
179  // '..' component. Back up if possible.
180  if (component_count > 0) {
181  dst = components[component_count - 1];
182  src += 3;
183  --component_count;
184  } else {
185  *dst++ = *src++;
186  *dst++ = *src++;
187  *dst++ = *src++;
188  }
189  continue;
190  }
191  }
192 
193  if (IsPathSeparator(*src)) {
194  src++;
195  continue;
196  }
197 
198  if (component_count == kMaxPathComponents)
199  Fatal("path has too many components : %s", path);
200  components[component_count] = dst;
201  ++component_count;
202 
203  while (src != end && !IsPathSeparator(*src))
204  *dst++ = *src++;
205  *dst++ = *src++; // Copy '/' or final \0 character as well.
206  }
207 
208  if (dst == start) {
209  *dst++ = '.';
210  *dst++ = '\0';
211  }
212 
213  *len = dst - start - 1;
214 #ifdef _WIN32
215  uint64_t bits = 0;
216  uint64_t bits_mask = 1;
217 
218  for (char* c = start; c < start + *len; ++c) {
219  switch (*c) {
220  case '\\':
221  bits |= bits_mask;
222  *c = '/';
224  case '/':
225  bits_mask <<= 1;
226  }
227  }
228 
229  *slash_bits = bits;
230 #else
231  *slash_bits = 0;
232 #endif
233 }
234 
235 static inline bool IsKnownShellSafeCharacter(char ch) {
236  if ('A' <= ch && ch <= 'Z') return true;
237  if ('a' <= ch && ch <= 'z') return true;
238  if ('0' <= ch && ch <= '9') return true;
239 
240  switch (ch) {
241  case '_':
242  case '+':
243  case '-':
244  case '.':
245  case '/':
246  return true;
247  default:
248  return false;
249  }
250 }
251 
252 static inline bool IsKnownWin32SafeCharacter(char ch) {
253  switch (ch) {
254  case ' ':
255  case '"':
256  return false;
257  default:
258  return true;
259  }
260 }
261 
262 static inline bool StringNeedsShellEscaping(const string& input) {
263  for (size_t i = 0; i < input.size(); ++i) {
264  if (!IsKnownShellSafeCharacter(input[i])) return true;
265  }
266  return false;
267 }
268 
269 static inline bool StringNeedsWin32Escaping(const string& input) {
270  for (size_t i = 0; i < input.size(); ++i) {
271  if (!IsKnownWin32SafeCharacter(input[i])) return true;
272  }
273  return false;
274 }
275 
276 void GetShellEscapedString(const string& input, string* result) {
277  assert(result);
278 
279  if (!StringNeedsShellEscaping(input)) {
280  result->append(input);
281  return;
282  }
283 
284  const char kQuote = '\'';
285  const char kEscapeSequence[] = "'\\'";
286 
287  result->push_back(kQuote);
288 
289  string::const_iterator span_begin = input.begin();
290  for (string::const_iterator it = input.begin(), end = input.end(); it != end;
291  ++it) {
292  if (*it == kQuote) {
293  result->append(span_begin, it);
294  result->append(kEscapeSequence);
295  span_begin = it;
296  }
297  }
298  result->append(span_begin, input.end());
299  result->push_back(kQuote);
300 }
301 
302 
303 void GetWin32EscapedString(const string& input, string* result) {
304  assert(result);
305  if (!StringNeedsWin32Escaping(input)) {
306  result->append(input);
307  return;
308  }
309 
310  const char kQuote = '"';
311  const char kBackslash = '\\';
312 
313  result->push_back(kQuote);
314  size_t consecutive_backslash_count = 0;
315  string::const_iterator span_begin = input.begin();
316  for (string::const_iterator it = input.begin(), end = input.end(); it != end;
317  ++it) {
318  switch (*it) {
319  case kBackslash:
320  ++consecutive_backslash_count;
321  break;
322  case kQuote:
323  result->append(span_begin, it);
324  result->append(consecutive_backslash_count + 1, kBackslash);
325  span_begin = it;
326  consecutive_backslash_count = 0;
327  break;
328  default:
329  consecutive_backslash_count = 0;
330  break;
331  }
332  }
333  result->append(span_begin, input.end());
334  result->append(consecutive_backslash_count, kBackslash);
335  result->push_back(kQuote);
336 }
337 
338 int ReadFile(const string& path, string* contents, string* err) {
339 #ifdef _WIN32
340  // This makes a ninja run on a set of 1500 manifest files about 4% faster
341  // than using the generic fopen code below.
342  err->clear();
343  HANDLE f = ::CreateFileA(path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
344  OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
345  if (f == INVALID_HANDLE_VALUE) {
346  err->assign(GetLastErrorString());
347  return -ENOENT;
348  }
349 
350  for (;;) {
351  DWORD len;
352  char buf[64 << 10];
353  if (!::ReadFile(f, buf, sizeof(buf), &len, NULL)) {
354  err->assign(GetLastErrorString());
355  contents->clear();
356  ::CloseHandle(f);
357  return -EIO;
358  }
359  if (len == 0)
360  break;
361  contents->append(buf, len);
362  }
363  ::CloseHandle(f);
364  return 0;
365 #else
366  FILE* f = fopen(path.c_str(), "rb");
367  if (!f) {
368  err->assign(strerror(errno));
369  return -errno;
370  }
371 
372  struct stat st;
373  if (fstat(fileno(f), &st) < 0) {
374  err->assign(strerror(errno));
375  fclose(f);
376  return -errno;
377  }
378 
379  // +1 is for the resize in ManifestParser::Load
380  contents->reserve(st.st_size + 1);
381 
382  char buf[64 << 10];
383  size_t len;
384  while (!feof(f) && (len = fread(buf, 1, sizeof(buf), f)) > 0) {
385  contents->append(buf, len);
386  }
387  if (ferror(f)) {
388  err->assign(strerror(errno)); // XXX errno?
389  contents->clear();
390  fclose(f);
391  return -errno;
392  }
393  fclose(f);
394  return 0;
395 #endif
396 }
397 
398 void SetCloseOnExec(int fd) {
399 #ifndef _WIN32
400  int flags = fcntl(fd, F_GETFD);
401  if (flags < 0) {
402  perror("fcntl(F_GETFD)");
403  } else {
404  if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
405  perror("fcntl(F_SETFD)");
406  }
407 #else
408  HANDLE hd = (HANDLE) _get_osfhandle(fd);
409  if (! SetHandleInformation(hd, HANDLE_FLAG_INHERIT, 0)) {
410  fprintf(stderr, "SetHandleInformation(): %s", GetLastErrorString().c_str());
411  }
412 #endif // ! _WIN32
413 }
414 
415 
416 const char* SpellcheckStringV(const string& text,
417  const vector<const char*>& words) {
418  const bool kAllowReplacements = true;
419  const int kMaxValidEditDistance = 3;
420 
421  int min_distance = kMaxValidEditDistance + 1;
422  const char* result = NULL;
423  for (vector<const char*>::const_iterator i = words.begin();
424  i != words.end(); ++i) {
425  int distance = EditDistance(*i, text, kAllowReplacements,
426  kMaxValidEditDistance);
427  if (distance < min_distance) {
428  min_distance = distance;
429  result = *i;
430  }
431  }
432  return result;
433 }
434 
435 const char* SpellcheckString(const char* text, ...) {
436  // Note: This takes a const char* instead of a string& because using
437  // va_start() with a reference parameter is undefined behavior.
438  va_list ap;
439  va_start(ap, text);
440  vector<const char*> words;
441  const char* word;
442  while ((word = va_arg(ap, const char*)))
443  words.push_back(word);
444  va_end(ap);
445  return SpellcheckStringV(text, words);
446 }
447 
448 #ifdef _WIN32
449 string GetLastErrorString() {
450  DWORD err = GetLastError();
451 
452  char* msg_buf;
453  FormatMessageA(
454  FORMAT_MESSAGE_ALLOCATE_BUFFER |
455  FORMAT_MESSAGE_FROM_SYSTEM |
456  FORMAT_MESSAGE_IGNORE_INSERTS,
457  NULL,
458  err,
459  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
460  (char*)&msg_buf,
461  0,
462  NULL);
463  string msg = msg_buf;
464  LocalFree(msg_buf);
465  return msg;
466 }
467 
468 void Win32Fatal(const char* function, const char* hint) {
469  if (hint) {
470  Fatal("%s: %s (%s)", function, GetLastErrorString().c_str(), hint);
471  } else {
472  Fatal("%s: %s", function, GetLastErrorString().c_str());
473  }
474 }
475 #endif
476 
477 bool islatinalpha(int c) {
478  // isalpha() is locale-dependent.
479  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
480 }
481 
482 string StripAnsiEscapeCodes(const string& in) {
483  string stripped;
484  stripped.reserve(in.size());
485 
486  for (size_t i = 0; i < in.size(); ++i) {
487  if (in[i] != '\33') {
488  // Not an escape code.
489  stripped.push_back(in[i]);
490  continue;
491  }
492 
493  // Only strip CSIs for now.
494  if (i + 1 >= in.size()) break;
495  if (in[i + 1] != '[') continue; // Not a CSI.
496  i += 2;
497 
498  // Skip everything up to and including the next [a-zA-Z].
499  while (i < in.size() && !islatinalpha(in[i]))
500  ++i;
501  }
502  return stripped;
503 }
504 
505 #if defined(linux) || defined(__GLIBC__)
506 std::pair<int64_t, bool> readCount(const std::string& path) {
507  std::ifstream file(path.c_str());
508  if (!file.is_open())
509  return std::make_pair(0, false);
510  int64_t n = 0;
511  file >> n;
512  if (file.good())
513  return std::make_pair(n, true);
514  return std::make_pair(0, false);
515 }
516 
517 struct MountPoint {
518  int mountId;
519  int parentId;
520  StringPiece deviceId;
521  StringPiece root;
522  StringPiece mountPoint;
523  vector<StringPiece> options;
524  vector<StringPiece> optionalFields;
525  StringPiece fsType;
526  StringPiece mountSource;
527  vector<StringPiece> superOptions;
528  bool parse(const string& line) {
529  vector<StringPiece> pieces = SplitStringPiece(line, ' ');
530  if (pieces.size() < 10)
531  return false;
532  size_t optionalStart = 0;
533  for (size_t i = 6; i < pieces.size(); i++) {
534  if (pieces[i] == "-") {
535  optionalStart = i + 1;
536  break;
537  }
538  }
539  if (optionalStart == 0)
540  return false;
541  if (optionalStart + 3 != pieces.size())
542  return false;
543  mountId = atoi(pieces[0].AsString().c_str());
544  parentId = atoi(pieces[1].AsString().c_str());
545  deviceId = pieces[2];
546  root = pieces[3];
547  mountPoint = pieces[4];
548  options = SplitStringPiece(pieces[5], ',');
549  optionalFields =
550  vector<StringPiece>(&pieces[6], &pieces[optionalStart - 1]);
551  fsType = pieces[optionalStart];
552  mountSource = pieces[optionalStart + 1];
553  superOptions = SplitStringPiece(pieces[optionalStart + 2], ',');
554  return true;
555  }
556  string translate(string& path) const {
557  // path must be sub dir of root
558  if (path.compare(0, root.len_, root.str_, root.len_) != 0) {
559  return string();
560  }
561  path.erase(0, root.len_);
562  if (path == ".." || (path.length() > 2 && path.compare(0, 3, "../") == 0)) {
563  return string();
564  }
565  return mountPoint.AsString() + "/" + path;
566  }
567 };
568 
569 struct CGroupSubSys {
570  int id;
571  string name;
572  vector<string> subsystems;
573  bool parse(string& line) {
574  size_t first = line.find(':');
575  if (first == string::npos)
576  return false;
577  line[first] = '\0';
578  size_t second = line.find(':', first + 1);
579  if (second == string::npos)
580  return false;
581  line[second] = '\0';
582  id = atoi(line.c_str());
583  name = line.substr(second + 1);
584  vector<StringPiece> pieces =
585  SplitStringPiece(StringPiece(line.c_str() + first + 1), ',');
586  for (size_t i = 0; i < pieces.size(); i++) {
587  subsystems.push_back(pieces[i].AsString());
588  }
589  return true;
590  }
591 };
592 
593 map<string, string> ParseMountInfo(map<string, CGroupSubSys>& subsystems) {
594  map<string, string> cgroups;
595  ifstream mountinfo("/proc/self/mountinfo");
596  if (!mountinfo.is_open())
597  return cgroups;
598  while (!mountinfo.eof()) {
599  string line;
600  getline(mountinfo, line);
601  MountPoint mp;
602  if (!mp.parse(line))
603  continue;
604  if (mp.fsType != "cgroup")
605  continue;
606  for (size_t i = 0; i < mp.superOptions.size(); i++) {
607  string opt = mp.superOptions[i].AsString();
608  map<string, CGroupSubSys>::iterator subsys = subsystems.find(opt);
609  if (subsys == subsystems.end())
610  continue;
611  string newPath = mp.translate(subsys->second.name);
612  if (!newPath.empty())
613  cgroups.insert(make_pair(opt, newPath));
614  }
615  }
616  return cgroups;
617 }
618 
619 map<string, CGroupSubSys> ParseSelfCGroup() {
620  map<string, CGroupSubSys> cgroups;
621  ifstream cgroup("/proc/self/cgroup");
622  if (!cgroup.is_open())
623  return cgroups;
624  string line;
625  while (!cgroup.eof()) {
626  getline(cgroup, line);
627  CGroupSubSys subsys;
628  if (!subsys.parse(line))
629  continue;
630  for (size_t i = 0; i < subsys.subsystems.size(); i++) {
631  cgroups.insert(make_pair(subsys.subsystems[i], subsys));
632  }
633  }
634  return cgroups;
635 }
636 
637 int ParseCPUFromCGroup() {
638  map<string, CGroupSubSys> subsystems = ParseSelfCGroup();
639  map<string, string> cgroups = ParseMountInfo(subsystems);
640  map<string, string>::iterator cpu = cgroups.find("cpu");
641  if (cpu == cgroups.end())
642  return -1;
643  std::pair<int64_t, bool> quota = readCount(cpu->second + "/cpu.cfs_quota_us");
644  if (!quota.second || quota.first == -1)
645  return -1;
646  std::pair<int64_t, bool> period =
647  readCount(cpu->second + "/cpu.cfs_period_us");
648  if (!period.second)
649  return -1;
650  if (period.first == 0)
651  return -1;
652  return quota.first / period.first;
653 }
654 #endif
655 
657 #ifdef _WIN32
658  DWORD cpuCount = 0;
659 #ifndef _WIN64
660  // Need to use GetLogicalProcessorInformationEx to get real core count on
661  // machines with >64 cores. See https://stackoverflow.com/a/31209344/21475
662  DWORD len = 0;
663  if (!GetLogicalProcessorInformationEx(RelationProcessorCore, nullptr, &len)
664  && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
665  std::vector<char> buf(len);
666  int cores = 0;
667  if (GetLogicalProcessorInformationEx(RelationProcessorCore,
668  reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>(
669  buf.data()), &len)) {
670  for (DWORD i = 0; i < len; ) {
671  auto info = reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>(
672  buf.data() + i);
673  if (info->Relationship == RelationProcessorCore &&
674  info->Processor.GroupCount == 1) {
675  for (KAFFINITY core_mask = info->Processor.GroupMask[0].Mask;
676  core_mask; core_mask >>= 1) {
677  cores += (core_mask & 1);
678  }
679  }
680  i += info->Size;
681  }
682  if (cores != 0) {
683  cpuCount = cores;
684  }
685  }
686  }
687 #endif
688  if (cpuCount == 0) {
689  cpuCount = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
690  }
691  JOBOBJECT_CPU_RATE_CONTROL_INFORMATION info;
692  // reference:
693  // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_cpu_rate_control_information
694  if (QueryInformationJobObject(NULL, JobObjectCpuRateControlInformation, &info,
695  sizeof(info), NULL)) {
696  if (info.ControlFlags & (JOB_OBJECT_CPU_RATE_CONTROL_ENABLE |
697  JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP)) {
698  return cpuCount * info.CpuRate / 10000;
699  }
700  }
701  return cpuCount;
702 #else
703  int cgroupCount = -1;
704  int schedCount = -1;
705 #if defined(linux) || defined(__GLIBC__)
706  cgroupCount = ParseCPUFromCGroup();
707 #endif
708  // The number of exposed processors might not represent the actual number of
709  // processors threads can run on. This happens when a CPU set limitation is
710  // active, see https://github.com/ninja-build/ninja/issues/1278
711 #if defined(__FreeBSD__)
712  cpuset_t mask;
713  CPU_ZERO(&mask);
714  if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(mask),
715  &mask) == 0) {
716  return CPU_COUNT(&mask);
717  }
718 #elif defined(CPU_COUNT)
719  cpu_set_t set;
720  if (sched_getaffinity(getpid(), sizeof(set), &set) == 0) {
721  schedCount = CPU_COUNT(&set);
722  }
723 #endif
724  if (cgroupCount >= 0 && schedCount >= 0) return std::min(cgroupCount, schedCount);
725  if (cgroupCount < 0 && schedCount < 0) return sysconf(_SC_NPROCESSORS_ONLN);
726  return std::max(cgroupCount, schedCount);
727 #endif
728 }
729 
730 #if defined(_WIN32) || defined(__CYGWIN__)
731 static double CalculateProcessorLoad(uint64_t idle_ticks, uint64_t total_ticks)
732 {
733  static uint64_t previous_idle_ticks = 0;
734  static uint64_t previous_total_ticks = 0;
735  static double previous_load = -0.0;
736 
737  uint64_t idle_ticks_since_last_time = idle_ticks - previous_idle_ticks;
738  uint64_t total_ticks_since_last_time = total_ticks - previous_total_ticks;
739 
740  bool first_call = (previous_total_ticks == 0);
741  bool ticks_not_updated_since_last_call = (total_ticks_since_last_time == 0);
742 
743  double load;
744  if (first_call || ticks_not_updated_since_last_call) {
745  load = previous_load;
746  } else {
747  // Calculate load.
748  double idle_to_total_ratio =
749  ((double)idle_ticks_since_last_time) / total_ticks_since_last_time;
750  double load_since_last_call = 1.0 - idle_to_total_ratio;
751 
752  // Filter/smooth result when possible.
753  if(previous_load > 0) {
754  load = 0.9 * previous_load + 0.1 * load_since_last_call;
755  } else {
756  load = load_since_last_call;
757  }
758  }
759 
760  previous_load = load;
761  previous_total_ticks = total_ticks;
762  previous_idle_ticks = idle_ticks;
763 
764  return load;
765 }
766 
767 static uint64_t FileTimeToTickCount(const FILETIME & ft)
768 {
769  uint64_t high = (((uint64_t)(ft.dwHighDateTime)) << 32);
770  uint64_t low = ft.dwLowDateTime;
771  return (high | low);
772 }
773 
774 double GetLoadAverage() {
775  FILETIME idle_time, kernel_time, user_time;
776  BOOL get_system_time_succeeded =
777  GetSystemTimes(&idle_time, &kernel_time, &user_time);
778 
779  double posix_compatible_load;
780  if (get_system_time_succeeded) {
781  uint64_t idle_ticks = FileTimeToTickCount(idle_time);
782 
783  // kernel_time from GetSystemTimes already includes idle_time.
784  uint64_t total_ticks =
785  FileTimeToTickCount(kernel_time) + FileTimeToTickCount(user_time);
786 
787  double processor_load = CalculateProcessorLoad(idle_ticks, total_ticks);
788  posix_compatible_load = processor_load * GetProcessorCount();
789 
790  } else {
791  posix_compatible_load = -0.0;
792  }
793 
794  return posix_compatible_load;
795 }
796 #elif defined(__PASE__)
797 double GetLoadAverage() {
798  return -0.0f;
799 }
800 #elif defined(_AIX)
801 double GetLoadAverage() {
802  perfstat_cpu_total_t cpu_stats;
803  if (perfstat_cpu_total(NULL, &cpu_stats, sizeof(cpu_stats), 1) < 0) {
804  return -0.0f;
805  }
806 
807  // Calculation taken from comment in libperfstats.h
808  return double(cpu_stats.loadavg[0]) / double(1 << SBITS);
809 }
810 #elif defined(__UCLIBC__) || (defined(__BIONIC__) && __ANDROID_API__ < 29)
811 double GetLoadAverage() {
812  struct sysinfo si;
813  if (sysinfo(&si) != 0)
814  return -0.0f;
815  return 1.0 / (1 << SI_LOAD_SHIFT) * si.loads[0];
816 }
817 #elif defined(__HAIKU__)
818 double GetLoadAverage() {
819  return -0.0f;
820 }
821 #else
822 double GetLoadAverage() {
823  double loadavg[3] = { 0.0f, 0.0f, 0.0f };
824  if (getloadavg(loadavg, 3) < 0) {
825  // Maybe we should return an error here or the availability of
826  // getloadavg(3) should be checked when ninja is configured.
827  return -0.0f;
828  }
829  return loadavg[0];
830 }
831 #endif // _WIN32
832 
833 string ElideMiddle(const string& str, size_t width) {
834  switch (width) {
835  case 0: return "";
836  case 1: return ".";
837  case 2: return "..";
838  case 3: return "...";
839  }
840  const int kMargin = 3; // Space for "...".
841  string result = str;
842  if (result.size() > width) {
843  size_t elide_size = (width - kMargin) / 2;
844  result = result.substr(0, elide_size)
845  + "..."
846  + result.substr(result.size() - elide_size, elide_size);
847  }
848  return result;
849 }
850 
851 bool Truncate(const string& path, size_t size, string* err) {
852 #ifdef _WIN32
853  int fh = _sopen(path.c_str(), _O_RDWR | _O_CREAT, _SH_DENYNO,
854  _S_IREAD | _S_IWRITE);
855  int success = _chsize(fh, size);
856  _close(fh);
857 #else
858  int success = truncate(path.c_str(), size);
859 #endif
860  // Both truncate() and _chsize() return 0 on success and set errno and return
861  // -1 on failure.
862  if (success < 0) {
863  *err = strerror(errno);
864  return false;
865  }
866  return true;
867 }
vector< StringPiece > SplitStringPiece(StringPiece input, char sep)
const char * SpellcheckStringV(const string &text, const vector< const char *> &words)
Definition: util.cc:416
static bool StringNeedsShellEscaping(const string &input)
Definition: util.cc:262
static bool IsPathSeparator(char c)
Definition: util.cc:131
std::string AsString() const
Convert the slice into a full-fledged std::string, copying the data into a new string.
Definition: string_piece.h:46
const char * str_
Definition: string_piece.h:66
const char * SpellcheckString(const char *text,...)
Like SpellcheckStringV, but takes a NULL-terminated list.
Definition: util.cc:435
void GetWin32EscapedString(const string &input, string *result)
Definition: util.cc:303
StringPiece represents a slice of a string whose memory is managed externally.
Definition: string_piece.h:25
void GetShellEscapedString(const string &input, string *result)
Definition: util.cc:276
void SetCloseOnExec(int fd)
Mark a file descriptor to not be inherited on exec()s.
Definition: util.cc:398
static bool IsKnownWin32SafeCharacter(char ch)
Definition: util.cc:252
signed long long int64_t
A 64-bit integer type.
Definition: win32port.h:28
double GetLoadAverage()
Definition: util.cc:822
static bool StringNeedsWin32Escaping(const string &input)
Definition: util.cc:269
#define NINJA_FALLTHROUGH
Definition: util.h:49
int ReadFile(const string &path, string *contents, string *err)
Definition: util.cc:338
void Info(const char *msg, va_list ap)
Definition: util.cc:109
static bool IsKnownShellSafeCharacter(char ch)
Definition: util.cc:235
bool Truncate(const string &path, size_t size, string *err)
Definition: util.cc:851
string StripAnsiEscapeCodes(const string &in)
Definition: util.cc:482
void Fatal(const char *msg,...)
Log a fatal message and exit.
Definition: util.cc:65
void Warning(const char *msg, va_list ap)
Definition: util.cc:83
size_t len_
Definition: string_piece.h:67
void CanonicalizePath(string *path, uint64_t *slash_bits)
Definition: util.cc:122
int GetProcessorCount()
Definition: util.cc:656
void Error(const char *msg, va_list ap)
Definition: util.cc:96
unsigned long long uint64_t
Definition: win32port.h:29
bool islatinalpha(int c)
Definition: util.cc:477
int EditDistance(const StringPiece &s1, const StringPiece &s2, bool allow_replacements, int max_edit_distance)
string ElideMiddle(const string &str, size_t width)
Definition: util.cc:833