0a797f6979e5814a43b79340fd272d2442a8d6b5
[oota-llvm.git] / lib / Support / Unix / Process.inc
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/Support/Mutex.h"
17 #include "llvm/Support/MutexGuard.h"
18 #include "llvm/Support/TimeValue.h"
19 #ifdef HAVE_SYS_TIME_H
20 #include <sys/time.h>
21 #endif
22 #ifdef HAVE_SYS_RESOURCE_H
23 #include <sys/resource.h>
24 #endif
25 // DragonFlyBSD, OpenBSD, and Bitrig have deprecated <malloc.h> for
26 // <stdlib.h> instead. Unix.h includes this for us already.
27 #if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \
28     !defined(__OpenBSD__) && !defined(__Bitrig__)
29 #include <malloc.h>
30 #endif
31 #ifdef HAVE_MALLOC_MALLOC_H
32 #include <malloc/malloc.h>
33 #endif
34 #ifdef HAVE_SYS_IOCTL_H
35 #  include <sys/ioctl.h>
36 #endif
37 #ifdef HAVE_TERMIOS_H
38 #  include <termios.h>
39 #endif
40
41 // See if we can use curses to detect information about a terminal when
42 // connected to one.
43 #ifdef HAVE_CURSES
44 # if defined(HAVE_CURSES_H)
45 #  include <curses.h>
46 # elif defined(HAVE_NCURSES_H)
47 #  include <ncurses.h>
48 # elif defined(HAVE_NCURSESW_H)
49 #  include <ncursesw.h>
50 # elif defined(HAVE_NCURSES_CURSES_H)
51 #  include <ncurses/curses.h>
52 # elif defined(HAVE_NCURSESW_CURSES_H)
53 #  include <ncursesw/curses.h>
54 # else
55 #  error Have a curses library but unable to find a curses header!
56 # endif
57 # include <term.h>
58 #endif
59
60 //===----------------------------------------------------------------------===//
61 //=== WARNING: Implementation here must contain only generic UNIX code that
62 //===          is guaranteed to work on *all* UNIX variants.
63 //===----------------------------------------------------------------------===//
64
65 using namespace llvm;
66 using namespace sys;
67
68
69 process::id_type self_process::get_id() {
70   return getpid();
71 }
72
73 static std::pair<TimeValue, TimeValue> getRUsageTimes() {
74 #if defined(HAVE_GETRUSAGE)
75   struct rusage RU;
76   ::getrusage(RUSAGE_SELF, &RU);
77   return std::make_pair(
78       TimeValue(
79           static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec),
80           static_cast<TimeValue::NanoSecondsType>(
81               RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)),
82       TimeValue(
83           static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec),
84           static_cast<TimeValue::NanoSecondsType>(
85               RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)));
86 #else
87 #warning Cannot get usage times on this platform
88   return std::make_pair(TimeValue(), TimeValue());
89 #endif
90 }
91
92 TimeValue self_process::get_user_time() const {
93 #if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0
94   // Try to get a high resolution CPU timer.
95   struct timespec TS;
96   if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0)
97     return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec),
98                      static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec));
99 #endif
100
101   // Otherwise fall back to rusage based timing.
102   return getRUsageTimes().first;
103 }
104
105 TimeValue self_process::get_system_time() const {
106   // We can only collect system time by inspecting the results of getrusage.
107   return getRUsageTimes().second;
108 }
109
110 static unsigned getPageSize() {
111 #if defined(__CYGWIN__)
112   // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
113   // memory protection and mmap() is 4k.
114   // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
115   const int page_size = 0x1000;
116 #elif defined(HAVE_GETPAGESIZE)
117   const int page_size = ::getpagesize();
118 #elif defined(HAVE_SYSCONF)
119   long page_size = ::sysconf(_SC_PAGE_SIZE);
120 #else
121 #warning Cannot get the page size on this machine
122 #endif
123   return static_cast<unsigned>(page_size);
124 }
125
126 // This constructor guaranteed to be run exactly once on a single thread, and
127 // sets up various process invariants that can be queried cheaply from then on.
128 self_process::self_process() : PageSize(getPageSize()) {
129 }
130
131
132 size_t Process::GetMallocUsage() {
133 #if defined(HAVE_MALLINFO)
134   struct mallinfo mi;
135   mi = ::mallinfo();
136   return mi.uordblks;
137 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
138   malloc_statistics_t Stats;
139   malloc_zone_statistics(malloc_default_zone(), &Stats);
140   return Stats.size_in_use;   // darwin
141 #elif defined(HAVE_SBRK)
142   // Note this is only an approximation and more closely resembles
143   // the value returned by mallinfo in the arena field.
144   static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
145   char *EndOfMemory = (char*)sbrk(0);
146   if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
147     return EndOfMemory - StartOfMemory;
148   else
149     return 0;
150 #else
151 #warning Cannot get malloc info on this platform
152   return 0;
153 #endif
154 }
155
156 void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
157                            TimeValue &sys_time) {
158   elapsed = TimeValue::now();
159   llvm::tie(user_time, sys_time) = getRUsageTimes();
160 }
161
162 int Process::GetCurrentUserId() {
163   return getuid();
164 }
165
166 int Process::GetCurrentGroupId() {
167   return getgid();
168 }
169
170 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
171 #include <mach/mach.h>
172 #endif
173
174 // Some LLVM programs such as bugpoint produce core files as a normal part of
175 // their operation. To prevent the disk from filling up, this function
176 // does what's necessary to prevent their generation.
177 void Process::PreventCoreFiles() {
178 #if HAVE_SETRLIMIT
179   struct rlimit rlim;
180   rlim.rlim_cur = rlim.rlim_max = 0;
181   setrlimit(RLIMIT_CORE, &rlim);
182 #endif
183
184 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
185   // Disable crash reporting on Mac OS X 10.0-10.4
186
187   // get information about the original set of exception ports for the task
188   mach_msg_type_number_t Count = 0;
189   exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
190   exception_port_t OriginalPorts[EXC_TYPES_COUNT];
191   exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
192   thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
193   kern_return_t err =
194     task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
195                              &Count, OriginalPorts, OriginalBehaviors,
196                              OriginalFlavors);
197   if (err == KERN_SUCCESS) {
198     // replace each with MACH_PORT_NULL.
199     for (unsigned i = 0; i != Count; ++i)
200       task_set_exception_ports(mach_task_self(), OriginalMasks[i],
201                                MACH_PORT_NULL, OriginalBehaviors[i],
202                                OriginalFlavors[i]);
203   }
204
205   // Disable crash reporting on Mac OS X 10.5
206   signal(SIGABRT, _exit);
207   signal(SIGILL,  _exit);
208   signal(SIGFPE,  _exit);
209   signal(SIGSEGV, _exit);
210   signal(SIGBUS,  _exit);
211 #endif
212 }
213
214 bool Process::StandardInIsUserInput() {
215   return FileDescriptorIsDisplayed(STDIN_FILENO);
216 }
217
218 bool Process::StandardOutIsDisplayed() {
219   return FileDescriptorIsDisplayed(STDOUT_FILENO);
220 }
221
222 bool Process::StandardErrIsDisplayed() {
223   return FileDescriptorIsDisplayed(STDERR_FILENO);
224 }
225
226 bool Process::FileDescriptorIsDisplayed(int fd) {
227 #if HAVE_ISATTY
228   return isatty(fd);
229 #else
230   // If we don't have isatty, just return false.
231   return false;
232 #endif
233 }
234
235 static unsigned getColumns(int FileID) {
236   // If COLUMNS is defined in the environment, wrap to that many columns.
237   if (const char *ColumnsStr = std::getenv("COLUMNS")) {
238     int Columns = std::atoi(ColumnsStr);
239     if (Columns > 0)
240       return Columns;
241   }
242
243   unsigned Columns = 0;
244
245 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
246   // Try to determine the width of the terminal.
247   struct winsize ws;
248   if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
249     Columns = ws.ws_col;
250 #endif
251
252   return Columns;
253 }
254
255 unsigned Process::StandardOutColumns() {
256   if (!StandardOutIsDisplayed())
257     return 0;
258
259   return getColumns(1);
260 }
261
262 unsigned Process::StandardErrColumns() {
263   if (!StandardErrIsDisplayed())
264     return 0;
265
266   return getColumns(2);
267 }
268
269 static bool terminalHasColors(int fd) {
270 #ifdef HAVE_CURSES
271   // First, acquire a global lock because the curses C routines are thread
272   // hostile.
273   static sys::Mutex M;
274   MutexGuard G(M);
275
276   int errret = 0;
277   if (setupterm((char *)0, fd, &errret) != OK)
278     // Regardless of why, if we can't get terminfo, we shouldn't try to print
279     // colors.
280     return false;
281
282   // Test whether the terminal as set up supports color output.
283   if (has_colors() == TRUE)
284     return true;
285 #endif
286
287   // Otherwise, be conservative.
288   return false;
289 }
290
291 bool Process::FileDescriptorHasColors(int fd) {
292   // A file descriptor has colors if it is displayed and the terminal has
293   // colors.
294   return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
295 }
296
297 bool Process::StandardOutHasColors() {
298   return FileDescriptorHasColors(STDOUT_FILENO);
299 }
300
301 bool Process::StandardErrHasColors() {
302   return FileDescriptorHasColors(STDERR_FILENO);
303 }
304
305 bool Process::ColorNeedsFlush() {
306   // No, we use ANSI escape sequences.
307   return false;
308 }
309
310 #define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
311
312 #define ALLCOLORS(FGBG,BOLD) {\
313     COLOR(FGBG, "0", BOLD),\
314     COLOR(FGBG, "1", BOLD),\
315     COLOR(FGBG, "2", BOLD),\
316     COLOR(FGBG, "3", BOLD),\
317     COLOR(FGBG, "4", BOLD),\
318     COLOR(FGBG, "5", BOLD),\
319     COLOR(FGBG, "6", BOLD),\
320     COLOR(FGBG, "7", BOLD)\
321   }
322
323 static const char colorcodes[2][2][8][10] = {
324  { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
325  { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
326 };
327
328 const char *Process::OutputColor(char code, bool bold, bool bg) {
329   return colorcodes[bg?1:0][bold?1:0][code&7];
330 }
331
332 const char *Process::OutputBold(bool bg) {
333   return "\033[1m";
334 }
335
336 const char *Process::OutputReverse() {
337   return "\033[7m";
338 }
339
340 const char *Process::ResetColor() {
341   return "\033[0m";
342 }
343
344 #if !defined(HAVE_ARC4RANDOM)
345 static unsigned GetRandomNumberSeed() {
346   // Attempt to get the initial seed from /dev/urandom, if possible.
347   if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
348     unsigned seed;
349     int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
350     ::fclose(RandomSource);
351
352     // Return the seed if the read was successful.
353     if (count == 1)
354       return seed;
355   }
356
357   // Otherwise, swizzle the current time and the process ID to form a reasonable
358   // seed.
359   TimeValue Now = TimeValue::now();
360   return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
361 }
362 #endif
363
364 unsigned llvm::sys::Process::GetRandomNumber() {
365 #if defined(HAVE_ARC4RANDOM)
366   return arc4random();
367 #else
368   static int x = (::srand(GetRandomNumberSeed()), 0);
369   (void)x;
370   return ::rand();
371 #endif
372 }