LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Unix/Process.inc
Go to the documentation of this file.
1 //===- Unix/Process.cpp - Unix Process Implementation --------- -*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file provides the generic Unix implementation of the Process class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "Unix.h"
15 #include "llvm/ADT/Hashing.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/Mutex.h"
19 #include "llvm/Support/TimeValue.h"
20 #ifdef HAVE_SYS_TIME_H
21 #include <sys/time.h>
22 #endif
23 #ifdef HAVE_SYS_RESOURCE_H
24 #include <sys/resource.h>
25 #endif
26 // DragonFlyBSD, OpenBSD, and Bitrig have deprecated <malloc.h> for
27 // <stdlib.h> instead. Unix.h includes this for us already.
28 #if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \
29  !defined(__OpenBSD__) && !defined(__Bitrig__)
30 #include <malloc.h>
31 #endif
32 #ifdef HAVE_MALLOC_MALLOC_H
33 #include <malloc/malloc.h>
34 #endif
35 #ifdef HAVE_SYS_IOCTL_H
36 # include <sys/ioctl.h>
37 #endif
38 #ifdef HAVE_TERMIOS_H
39 # include <termios.h>
40 #endif
41 
42 //===----------------------------------------------------------------------===//
43 //=== WARNING: Implementation here must contain only generic UNIX code that
44 //=== is guaranteed to work on *all* UNIX variants.
45 //===----------------------------------------------------------------------===//
46 
47 using namespace llvm;
48 using namespace sys;
49 
50 
52  return getpid();
53 }
54 
55 static std::pair<TimeValue, TimeValue> getRUsageTimes() {
56 #if defined(HAVE_GETRUSAGE)
57  struct rusage RU;
58  ::getrusage(RUSAGE_SELF, &RU);
59  return std::make_pair(
60  TimeValue(
61  static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec),
62  static_cast<TimeValue::NanoSecondsType>(
63  RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)),
64  TimeValue(
65  static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec),
66  static_cast<TimeValue::NanoSecondsType>(
67  RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)));
68 #else
69 #warning Cannot get usage times on this platform
70  return std::make_pair(TimeValue(), TimeValue());
71 #endif
72 }
73 
74 TimeValue self_process::get_user_time() const {
75 #if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0
76  // Try to get a high resolution CPU timer.
77  struct timespec TS;
78  if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0)
79  return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec),
80  static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec));
81 #endif
82 
83  // Otherwise fall back to rusage based timing.
84  return getRUsageTimes().first;
85 }
86 
87 TimeValue self_process::get_system_time() const {
88  // We can only collect system time by inspecting the results of getrusage.
89  return getRUsageTimes().second;
90 }
91 
92 // On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
93 // offset in mmap(3) should be aligned to the AllocationGranularity.
94 static unsigned getPageSize() {
95 #if defined(HAVE_GETPAGESIZE)
96  const int page_size = ::getpagesize();
97 #elif defined(HAVE_SYSCONF)
98  long page_size = ::sysconf(_SC_PAGE_SIZE);
99 #else
100 #warning Cannot get the page size on this machine
101 #endif
102  return static_cast<unsigned>(page_size);
103 }
104 
105 // This constructor guaranteed to be run exactly once on a single thread, and
106 // sets up various process invariants that can be queried cheaply from then on.
107 self_process::self_process() : PageSize(getPageSize()) {
108 }
109 
110 
111 size_t Process::GetMallocUsage() {
112 #if defined(HAVE_MALLINFO)
113  struct mallinfo mi;
114  mi = ::mallinfo();
115  return mi.uordblks;
116 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
117  malloc_statistics_t Stats;
118  malloc_zone_statistics(malloc_default_zone(), &Stats);
119  return Stats.size_in_use; // darwin
120 #elif defined(HAVE_SBRK)
121  // Note this is only an approximation and more closely resembles
122  // the value returned by mallinfo in the arena field.
123  static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
124  char *EndOfMemory = (char*)sbrk(0);
125  if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
126  return EndOfMemory - StartOfMemory;
127  else
128  return 0;
129 #else
130 #warning Cannot get malloc info on this platform
131  return 0;
132 #endif
133 }
134 
135 void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
136  TimeValue &sys_time) {
137  elapsed = TimeValue::now();
138  llvm::tie(user_time, sys_time) = getRUsageTimes();
139 }
140 
141 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
142 #include <mach/mach.h>
143 #endif
144 
145 // Some LLVM programs such as bugpoint produce core files as a normal part of
146 // their operation. To prevent the disk from filling up, this function
147 // does what's necessary to prevent their generation.
149 #if HAVE_SETRLIMIT
150  struct rlimit rlim;
151  rlim.rlim_cur = rlim.rlim_max = 0;
152  setrlimit(RLIMIT_CORE, &rlim);
153 #endif
154 
155 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
156  // Disable crash reporting on Mac OS X 10.0-10.4
157 
158  // get information about the original set of exception ports for the task
159  mach_msg_type_number_t Count = 0;
160  exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
161  exception_port_t OriginalPorts[EXC_TYPES_COUNT];
162  exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
163  thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
164  kern_return_t err =
165  task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
166  &Count, OriginalPorts, OriginalBehaviors,
167  OriginalFlavors);
168  if (err == KERN_SUCCESS) {
169  // replace each with MACH_PORT_NULL.
170  for (unsigned i = 0; i != Count; ++i)
171  task_set_exception_ports(mach_task_self(), OriginalMasks[i],
172  MACH_PORT_NULL, OriginalBehaviors[i],
173  OriginalFlavors[i]);
174  }
175 
176  // Disable crash reporting on Mac OS X 10.5
177  signal(SIGABRT, _exit);
178  signal(SIGILL, _exit);
179  signal(SIGFPE, _exit);
180  signal(SIGSEGV, _exit);
181  signal(SIGBUS, _exit);
182 #endif
183 }
184 
186  std::string NameStr = Name.str();
187  const char *Val = ::getenv(NameStr.c_str());
188  if (!Val)
189  return None;
190  return std::string(Val);
191 }
192 
194  ArrayRef<const char *> ArgsIn,
196  ArgsOut.append(ArgsIn.begin(), ArgsIn.end());
197 
198  return error_code::success();
199 }
200 
202  return FileDescriptorIsDisplayed(STDIN_FILENO);
203 }
204 
206  return FileDescriptorIsDisplayed(STDOUT_FILENO);
207 }
208 
210  return FileDescriptorIsDisplayed(STDERR_FILENO);
211 }
212 
214 #if HAVE_ISATTY
215  return isatty(fd);
216 #else
217  // If we don't have isatty, just return false.
218  return false;
219 #endif
220 }
221 
222 static unsigned getColumns(int FileID) {
223  // If COLUMNS is defined in the environment, wrap to that many columns.
224  if (const char *ColumnsStr = std::getenv("COLUMNS")) {
225  int Columns = std::atoi(ColumnsStr);
226  if (Columns > 0)
227  return Columns;
228  }
229 
230  unsigned Columns = 0;
231 
232 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
233  // Try to determine the width of the terminal.
234  struct winsize ws;
235  if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
236  Columns = ws.ws_col;
237 #endif
238 
239  return Columns;
240 }
241 
242 unsigned Process::StandardOutColumns() {
243  if (!StandardOutIsDisplayed())
244  return 0;
245 
246  return getColumns(1);
247 }
248 
249 unsigned Process::StandardErrColumns() {
250  if (!StandardErrIsDisplayed())
251  return 0;
252 
253  return getColumns(2);
254 }
255 
256 #ifdef HAVE_TERMINFO
257 // We manually declare these extern functions because finding the correct
258 // headers from various terminfo, curses, or other sources is harder than
259 // writing their specs down.
260 extern "C" int setupterm(char *term, int filedes, int *errret);
261 extern "C" struct term *set_curterm(struct term *termp);
262 extern "C" int del_curterm(struct term *termp);
263 extern "C" int tigetnum(char *capname);
264 #endif
265 
266 static bool terminalHasColors(int fd) {
267 #ifdef HAVE_TERMINFO
268  // First, acquire a global lock because these C routines are thread hostile.
269  static sys::Mutex M;
270  MutexGuard G(M);
271 
272  int errret = 0;
273  if (setupterm((char *)0, fd, &errret) != 0)
274  // Regardless of why, if we can't get terminfo, we shouldn't try to print
275  // colors.
276  return false;
277 
278  // Test whether the terminal as set up supports color output. How to do this
279  // isn't entirely obvious. We can use the curses routine 'has_colors' but it
280  // would be nice to avoid a dependency on curses proper when we can make do
281  // with a minimal terminfo parsing library. Also, we don't really care whether
282  // the terminal supports the curses-specific color changing routines, merely
283  // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
284  // strategy here is just to query the baseline colors capability and if it
285  // supports colors at all to assume it will translate the escape codes into
286  // whatever range of colors it does support. We can add more detailed tests
287  // here if users report them as necessary.
288  //
289  // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
290  // the terminfo says that no colors are supported.
291  bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
292 
293  // Now extract the structure allocated by setupterm and free its memory
294  // through a really silly dance.
295  struct term *termp = set_curterm((struct term *)0);
296  (void)del_curterm(termp); // Drop any errors here.
297 
298  // Return true if we found a color capabilities for the current terminal.
299  if (HasColors)
300  return true;
301 #endif
302 
303  // Otherwise, be conservative.
304  return false;
305 }
306 
308  // A file descriptor has colors if it is displayed and the terminal has
309  // colors.
310  return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
311 }
312 
314  return FileDescriptorHasColors(STDOUT_FILENO);
315 }
316 
318  return FileDescriptorHasColors(STDERR_FILENO);
319 }
320 
321 void Process::UseANSIEscapeCodes(bool /*enable*/) {
322  // No effect.
323 }
324 
326  // No, we use ANSI escape sequences.
327  return false;
328 }
329 
330 const char *Process::OutputColor(char code, bool bold, bool bg) {
331  return colorcodes[bg?1:0][bold?1:0][code&7];
332 }
333 
334 const char *Process::OutputBold(bool bg) {
335  return "\033[1m";
336 }
337 
338 const char *Process::OutputReverse() {
339  return "\033[7m";
340 }
341 
342 const char *Process::ResetColor() {
343  return "\033[0m";
344 }
345 
346 #if !defined(HAVE_ARC4RANDOM)
347 static unsigned GetRandomNumberSeed() {
348  // Attempt to get the initial seed from /dev/urandom, if possible.
349  if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
350  unsigned seed;
351  int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
352  ::fclose(RandomSource);
353 
354  // Return the seed if the read was successful.
355  if (count == 1)
356  return seed;
357  }
358 
359  // Otherwise, swizzle the current time and the process ID to form a reasonable
360  // seed.
361  TimeValue Now = TimeValue::now();
362  return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
363 }
364 #endif
365 
367 #if defined(HAVE_ARC4RANDOM)
368  return arc4random();
369 #else
370  static int x = (::srand(GetRandomNumberSeed()), 0);
371  (void)x;
372  return ::rand();
373 #endif
374 }
size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
static TimeValue now()
Creates a TimeValue with the current time (UTC).
static const char * ResetColor()
Resets the terminals colors, or returns an escape sequence to do so.
virtual TimeValue get_system_time() const
Get the system time consumed by this process.
static const char * OutputColor(char c, bool bold, bool bg)
iterator end() const
Definition: ArrayRef.h:98
static bool StandardErrHasColors()
static bool FileDescriptorHasColors(int fd)
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:181
FILE *fopen(const char *filename, const char *mode);.
static bool FileDescriptorIsDisplayed(int fd)
int fclose(FILE *stream);
virtual id_type get_id()
Get the operating system specific identifier for this process.
static bool ColorNeedsFlush()
static const char * OutputReverse()
static const char colorcodes[2][2][8][10]
Definition: Process.cpp:96
block placement Basic Block Placement Stats
#define G(x, y, z)
Definition: MD5.cpp:52
int atoi(const char *str);
static bool StandardInIsUserInput()
static bool StandardOutIsDisplayed()
static void UseANSIEscapeCodes(bool enable)
Guard a section of code with a Mutex.
Definition: MutexGuard.h:27
static unsigned StandardOutColumns()
static void GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, TimeValue &sys_time)
hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6)
Definition: Hashing.h:674
virtual TimeValue get_user_time() const
Get the user time consumed by this process.
iterator begin() const
Definition: ArrayRef.h:97
pid_t id_type
Operating system specific type to identify a process.
Definition: Process.h:63
void append(in_iter in_start, in_iter in_end)
Definition: SmallVector.h:445
static size_t GetMallocUsage()
Return process memory usage. This static function will return the total amount of memory allocated by...
static bool StandardErrIsDisplayed()
static void PreventCoreFiles()
Prevent core file generation.
static unsigned StandardErrColumns()
static bool StandardOutHasColors()
static unsigned GetRandomNumber()
static error_code success()
Definition: system_error.h:732
static error_code GetArgumentVector(SmallVectorImpl< const char * > &Args, ArrayRef< const char * > ArgsFromMain, SpecificBumpPtrAllocator< char > &ArgAllocator)
static const char * OutputBold(bool bg)
Same as OutputColor, but only enables the bold attribute.
char *getenv(const char *name);
tier< T1, T2 > tie(T1 &f, T2 &s)
Definition: STLExtras.h:216
static Optional< std::string > GetEnv(StringRef name)