GCC warns about removing const with a c-style cast.
[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 //===----------------------------------------------------------------------===//
42 //=== WARNING: Implementation here must contain only generic UNIX code that
43 //===          is guaranteed to work on *all* UNIX variants.
44 //===----------------------------------------------------------------------===//
45
46 using namespace llvm;
47 using namespace sys;
48
49
50 process::id_type self_process::get_id() {
51   return getpid();
52 }
53
54 static std::pair<TimeValue, TimeValue> getRUsageTimes() {
55 #if defined(HAVE_GETRUSAGE)
56   struct rusage RU;
57   ::getrusage(RUSAGE_SELF, &RU);
58   return std::make_pair(
59       TimeValue(
60           static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec),
61           static_cast<TimeValue::NanoSecondsType>(
62               RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)),
63       TimeValue(
64           static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec),
65           static_cast<TimeValue::NanoSecondsType>(
66               RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)));
67 #else
68 #warning Cannot get usage times on this platform
69   return std::make_pair(TimeValue(), TimeValue());
70 #endif
71 }
72
73 TimeValue self_process::get_user_time() const {
74 #if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0
75   // Try to get a high resolution CPU timer.
76   struct timespec TS;
77   if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0)
78     return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec),
79                      static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec));
80 #endif
81
82   // Otherwise fall back to rusage based timing.
83   return getRUsageTimes().first;
84 }
85
86 TimeValue self_process::get_system_time() const {
87   // We can only collect system time by inspecting the results of getrusage.
88   return getRUsageTimes().second;
89 }
90
91 static unsigned getPageSize() {
92 #if defined(__CYGWIN__)
93   // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
94   // memory protection and mmap() is 4k.
95   // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
96   const int page_size = 0x1000;
97 #elif defined(HAVE_GETPAGESIZE)
98   const int page_size = ::getpagesize();
99 #elif defined(HAVE_SYSCONF)
100   long page_size = ::sysconf(_SC_PAGE_SIZE);
101 #else
102 #warning Cannot get the page size on this machine
103 #endif
104   return static_cast<unsigned>(page_size);
105 }
106
107 // This constructor guaranteed to be run exactly once on a single thread, and
108 // sets up various process invariants that can be queried cheaply from then on.
109 self_process::self_process() : PageSize(getPageSize()) {
110 }
111
112
113 size_t Process::GetMallocUsage() {
114 #if defined(HAVE_MALLINFO)
115   struct mallinfo mi;
116   mi = ::mallinfo();
117   return mi.uordblks;
118 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
119   malloc_statistics_t Stats;
120   malloc_zone_statistics(malloc_default_zone(), &Stats);
121   return Stats.size_in_use;   // darwin
122 #elif defined(HAVE_SBRK)
123   // Note this is only an approximation and more closely resembles
124   // the value returned by mallinfo in the arena field.
125   static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
126   char *EndOfMemory = (char*)sbrk(0);
127   if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
128     return EndOfMemory - StartOfMemory;
129   else
130     return 0;
131 #else
132 #warning Cannot get malloc info on this platform
133   return 0;
134 #endif
135 }
136
137 void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
138                            TimeValue &sys_time) {
139   elapsed = TimeValue::now();
140   llvm::tie(user_time, sys_time) = getRUsageTimes();
141 }
142
143 int Process::GetCurrentUserId() {
144   return getuid();
145 }
146
147 int Process::GetCurrentGroupId() {
148   return getgid();
149 }
150
151 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
152 #include <mach/mach.h>
153 #endif
154
155 // Some LLVM programs such as bugpoint produce core files as a normal part of
156 // their operation. To prevent the disk from filling up, this function
157 // does what's necessary to prevent their generation.
158 void Process::PreventCoreFiles() {
159 #if HAVE_SETRLIMIT
160   struct rlimit rlim;
161   rlim.rlim_cur = rlim.rlim_max = 0;
162   setrlimit(RLIMIT_CORE, &rlim);
163 #endif
164
165 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
166   // Disable crash reporting on Mac OS X 10.0-10.4
167
168   // get information about the original set of exception ports for the task
169   mach_msg_type_number_t Count = 0;
170   exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
171   exception_port_t OriginalPorts[EXC_TYPES_COUNT];
172   exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
173   thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
174   kern_return_t err =
175     task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
176                              &Count, OriginalPorts, OriginalBehaviors,
177                              OriginalFlavors);
178   if (err == KERN_SUCCESS) {
179     // replace each with MACH_PORT_NULL.
180     for (unsigned i = 0; i != Count; ++i)
181       task_set_exception_ports(mach_task_self(), OriginalMasks[i],
182                                MACH_PORT_NULL, OriginalBehaviors[i],
183                                OriginalFlavors[i]);
184   }
185
186   // Disable crash reporting on Mac OS X 10.5
187   signal(SIGABRT, _exit);
188   signal(SIGILL,  _exit);
189   signal(SIGFPE,  _exit);
190   signal(SIGSEGV, _exit);
191   signal(SIGBUS,  _exit);
192 #endif
193 }
194
195 bool Process::StandardInIsUserInput() {
196   return FileDescriptorIsDisplayed(STDIN_FILENO);
197 }
198
199 bool Process::StandardOutIsDisplayed() {
200   return FileDescriptorIsDisplayed(STDOUT_FILENO);
201 }
202
203 bool Process::StandardErrIsDisplayed() {
204   return FileDescriptorIsDisplayed(STDERR_FILENO);
205 }
206
207 bool Process::FileDescriptorIsDisplayed(int fd) {
208 #if HAVE_ISATTY
209   return isatty(fd);
210 #else
211   // If we don't have isatty, just return false.
212   return false;
213 #endif
214 }
215
216 static unsigned getColumns(int FileID) {
217   // If COLUMNS is defined in the environment, wrap to that many columns.
218   if (const char *ColumnsStr = std::getenv("COLUMNS")) {
219     int Columns = std::atoi(ColumnsStr);
220     if (Columns > 0)
221       return Columns;
222   }
223
224   unsigned Columns = 0;
225
226 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
227   // Try to determine the width of the terminal.
228   struct winsize ws;
229   if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
230     Columns = ws.ws_col;
231 #endif
232
233   return Columns;
234 }
235
236 unsigned Process::StandardOutColumns() {
237   if (!StandardOutIsDisplayed())
238     return 0;
239
240   return getColumns(1);
241 }
242
243 unsigned Process::StandardErrColumns() {
244   if (!StandardErrIsDisplayed())
245     return 0;
246
247   return getColumns(2);
248 }
249
250 #ifdef HAVE_TERMINFO
251 // We manually declare these two extern functions because finding the correct
252 // headers from various terminfo, curses, or other sources is harder than
253 // writing their specs down.
254 extern "C" int setupterm(char *term, int filedes, int *errret);
255 extern "C" int tigetnum(char *capname);
256 #endif
257
258 static bool terminalHasColors(int fd) {
259 #ifdef HAVE_TERMINFO
260   // First, acquire a global lock because these C routines are thread hostile.
261   static sys::Mutex M;
262   MutexGuard G(M);
263
264   int errret = 0;
265   if (setupterm((char *)0, fd, &errret) != 0)
266     // Regardless of why, if we can't get terminfo, we shouldn't try to print
267     // colors.
268     return false;
269
270   // Test whether the terminal as set up supports color output. How to do this
271   // isn't entirely obvious. We can use the curses routine 'has_colors' but it
272   // would be nice to avoid a dependency on curses proper when we can make do
273   // with a minimal terminfo parsing library. Also, we don't really care whether
274   // the terminal supports the curses-specific color changing routines, merely
275   // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
276   // strategy here is just to query the baseline colors capability and if it
277   // supports colors at all to assume it will translate the escape codes into
278   // whatever range of colors it does support. We can add more detailed tests
279   // here if users report them as necessary.
280   //
281   // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
282   // the terminfo says that no colors are supported.
283   if (tigetnum(const_cast<char *>("colors")) > 0)
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 }