Unix/Process.inc: Revert r72332, "Work around a page size issue on Cygwin."
[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 // On Cygwin, getpagesize() returns 64k and offset in mmap(3) should be
92 // aligned to its pagesize.
93 static unsigned getPageSize() {
94 #if defined(HAVE_GETPAGESIZE)
95   const int page_size = ::getpagesize();
96 #elif defined(HAVE_SYSCONF)
97   long page_size = ::sysconf(_SC_PAGE_SIZE);
98 #else
99 #warning Cannot get the page size on this machine
100 #endif
101   return static_cast<unsigned>(page_size);
102 }
103
104 // This constructor guaranteed to be run exactly once on a single thread, and
105 // sets up various process invariants that can be queried cheaply from then on.
106 self_process::self_process() : PageSize(getPageSize()) {
107 }
108
109
110 size_t Process::GetMallocUsage() {
111 #if defined(HAVE_MALLINFO)
112   struct mallinfo mi;
113   mi = ::mallinfo();
114   return mi.uordblks;
115 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
116   malloc_statistics_t Stats;
117   malloc_zone_statistics(malloc_default_zone(), &Stats);
118   return Stats.size_in_use;   // darwin
119 #elif defined(HAVE_SBRK)
120   // Note this is only an approximation and more closely resembles
121   // the value returned by mallinfo in the arena field.
122   static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
123   char *EndOfMemory = (char*)sbrk(0);
124   if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
125     return EndOfMemory - StartOfMemory;
126   else
127     return 0;
128 #else
129 #warning Cannot get malloc info on this platform
130   return 0;
131 #endif
132 }
133
134 void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
135                            TimeValue &sys_time) {
136   elapsed = TimeValue::now();
137   llvm::tie(user_time, sys_time) = getRUsageTimes();
138 }
139
140 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
141 #include <mach/mach.h>
142 #endif
143
144 // Some LLVM programs such as bugpoint produce core files as a normal part of
145 // their operation. To prevent the disk from filling up, this function
146 // does what's necessary to prevent their generation.
147 void Process::PreventCoreFiles() {
148 #if HAVE_SETRLIMIT
149   struct rlimit rlim;
150   rlim.rlim_cur = rlim.rlim_max = 0;
151   setrlimit(RLIMIT_CORE, &rlim);
152 #endif
153
154 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
155   // Disable crash reporting on Mac OS X 10.0-10.4
156
157   // get information about the original set of exception ports for the task
158   mach_msg_type_number_t Count = 0;
159   exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
160   exception_port_t OriginalPorts[EXC_TYPES_COUNT];
161   exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
162   thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
163   kern_return_t err =
164     task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
165                              &Count, OriginalPorts, OriginalBehaviors,
166                              OriginalFlavors);
167   if (err == KERN_SUCCESS) {
168     // replace each with MACH_PORT_NULL.
169     for (unsigned i = 0; i != Count; ++i)
170       task_set_exception_ports(mach_task_self(), OriginalMasks[i],
171                                MACH_PORT_NULL, OriginalBehaviors[i],
172                                OriginalFlavors[i]);
173   }
174
175   // Disable crash reporting on Mac OS X 10.5
176   signal(SIGABRT, _exit);
177   signal(SIGILL,  _exit);
178   signal(SIGFPE,  _exit);
179   signal(SIGSEGV, _exit);
180   signal(SIGBUS,  _exit);
181 #endif
182 }
183
184 bool Process::StandardInIsUserInput() {
185   return FileDescriptorIsDisplayed(STDIN_FILENO);
186 }
187
188 bool Process::StandardOutIsDisplayed() {
189   return FileDescriptorIsDisplayed(STDOUT_FILENO);
190 }
191
192 bool Process::StandardErrIsDisplayed() {
193   return FileDescriptorIsDisplayed(STDERR_FILENO);
194 }
195
196 bool Process::FileDescriptorIsDisplayed(int fd) {
197 #if HAVE_ISATTY
198   return isatty(fd);
199 #else
200   // If we don't have isatty, just return false.
201   return false;
202 #endif
203 }
204
205 static unsigned getColumns(int FileID) {
206   // If COLUMNS is defined in the environment, wrap to that many columns.
207   if (const char *ColumnsStr = std::getenv("COLUMNS")) {
208     int Columns = std::atoi(ColumnsStr);
209     if (Columns > 0)
210       return Columns;
211   }
212
213   unsigned Columns = 0;
214
215 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
216   // Try to determine the width of the terminal.
217   struct winsize ws;
218   if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
219     Columns = ws.ws_col;
220 #endif
221
222   return Columns;
223 }
224
225 unsigned Process::StandardOutColumns() {
226   if (!StandardOutIsDisplayed())
227     return 0;
228
229   return getColumns(1);
230 }
231
232 unsigned Process::StandardErrColumns() {
233   if (!StandardErrIsDisplayed())
234     return 0;
235
236   return getColumns(2);
237 }
238
239 #ifdef HAVE_TERMINFO
240 // We manually declare these extern functions because finding the correct
241 // headers from various terminfo, curses, or other sources is harder than
242 // writing their specs down.
243 extern "C" int setupterm(char *term, int filedes, int *errret);
244 extern "C" struct term *set_curterm(struct term *termp);
245 extern "C" int del_curterm(struct term *termp);
246 extern "C" int tigetnum(char *capname);
247 #endif
248
249 static bool terminalHasColors(int fd) {
250 #ifdef HAVE_TERMINFO
251   // First, acquire a global lock because these C routines are thread hostile.
252   static sys::Mutex M;
253   MutexGuard G(M);
254
255   int errret = 0;
256   if (setupterm((char *)0, fd, &errret) != 0)
257     // Regardless of why, if we can't get terminfo, we shouldn't try to print
258     // colors.
259     return false;
260
261   // Test whether the terminal as set up supports color output. How to do this
262   // isn't entirely obvious. We can use the curses routine 'has_colors' but it
263   // would be nice to avoid a dependency on curses proper when we can make do
264   // with a minimal terminfo parsing library. Also, we don't really care whether
265   // the terminal supports the curses-specific color changing routines, merely
266   // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
267   // strategy here is just to query the baseline colors capability and if it
268   // supports colors at all to assume it will translate the escape codes into
269   // whatever range of colors it does support. We can add more detailed tests
270   // here if users report them as necessary.
271   //
272   // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
273   // the terminfo says that no colors are supported.
274   bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
275
276   // Now extract the structure allocated by setupterm and free its memory
277   // through a really silly dance.
278   struct term *termp = set_curterm((struct term *)0);
279   (void)del_curterm(termp); // Drop any errors here.
280
281   // Return true if we found a color capabilities for the current terminal.
282   if (HasColors)
283     return true;
284 #endif
285
286   // Otherwise, be conservative.
287   return false;
288 }
289
290 bool Process::FileDescriptorHasColors(int fd) {
291   // A file descriptor has colors if it is displayed and the terminal has
292   // colors.
293   return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
294 }
295
296 bool Process::StandardOutHasColors() {
297   return FileDescriptorHasColors(STDOUT_FILENO);
298 }
299
300 bool Process::StandardErrHasColors() {
301   return FileDescriptorHasColors(STDERR_FILENO);
302 }
303
304 bool Process::ColorNeedsFlush() {
305   // No, we use ANSI escape sequences.
306   return false;
307 }
308
309 #define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
310
311 #define ALLCOLORS(FGBG,BOLD) {\
312     COLOR(FGBG, "0", BOLD),\
313     COLOR(FGBG, "1", BOLD),\
314     COLOR(FGBG, "2", BOLD),\
315     COLOR(FGBG, "3", BOLD),\
316     COLOR(FGBG, "4", BOLD),\
317     COLOR(FGBG, "5", BOLD),\
318     COLOR(FGBG, "6", BOLD),\
319     COLOR(FGBG, "7", BOLD)\
320   }
321
322 static const char colorcodes[2][2][8][10] = {
323  { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
324  { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
325 };
326
327 const char *Process::OutputColor(char code, bool bold, bool bg) {
328   return colorcodes[bg?1:0][bold?1:0][code&7];
329 }
330
331 const char *Process::OutputBold(bool bg) {
332   return "\033[1m";
333 }
334
335 const char *Process::OutputReverse() {
336   return "\033[7m";
337 }
338
339 const char *Process::ResetColor() {
340   return "\033[0m";
341 }
342
343 #if !defined(HAVE_ARC4RANDOM)
344 static unsigned GetRandomNumberSeed() {
345   // Attempt to get the initial seed from /dev/urandom, if possible.
346   if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
347     unsigned seed;
348     int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
349     ::fclose(RandomSource);
350
351     // Return the seed if the read was successful.
352     if (count == 1)
353       return seed;
354   }
355
356   // Otherwise, swizzle the current time and the process ID to form a reasonable
357   // seed.
358   TimeValue Now = TimeValue::now();
359   return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
360 }
361 #endif
362
363 unsigned llvm::sys::Process::GetRandomNumber() {
364 #if defined(HAVE_ARC4RANDOM)
365   return arc4random();
366 #else
367   static int x = (::srand(GetRandomNumberSeed()), 0);
368   (void)x;
369   return ::rand();
370 #endif
371 }