Go through the really awkward dance required to delete the memory
[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 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
144 #include <mach/mach.h>
145 #endif
146
147 // Some LLVM programs such as bugpoint produce core files as a normal part of
148 // their operation. To prevent the disk from filling up, this function
149 // does what's necessary to prevent their generation.
150 void Process::PreventCoreFiles() {
151 #if HAVE_SETRLIMIT
152   struct rlimit rlim;
153   rlim.rlim_cur = rlim.rlim_max = 0;
154   setrlimit(RLIMIT_CORE, &rlim);
155 #endif
156
157 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
158   // Disable crash reporting on Mac OS X 10.0-10.4
159
160   // get information about the original set of exception ports for the task
161   mach_msg_type_number_t Count = 0;
162   exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
163   exception_port_t OriginalPorts[EXC_TYPES_COUNT];
164   exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
165   thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
166   kern_return_t err =
167     task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
168                              &Count, OriginalPorts, OriginalBehaviors,
169                              OriginalFlavors);
170   if (err == KERN_SUCCESS) {
171     // replace each with MACH_PORT_NULL.
172     for (unsigned i = 0; i != Count; ++i)
173       task_set_exception_ports(mach_task_self(), OriginalMasks[i],
174                                MACH_PORT_NULL, OriginalBehaviors[i],
175                                OriginalFlavors[i]);
176   }
177
178   // Disable crash reporting on Mac OS X 10.5
179   signal(SIGABRT, _exit);
180   signal(SIGILL,  _exit);
181   signal(SIGFPE,  _exit);
182   signal(SIGSEGV, _exit);
183   signal(SIGBUS,  _exit);
184 #endif
185 }
186
187 bool Process::StandardInIsUserInput() {
188   return FileDescriptorIsDisplayed(STDIN_FILENO);
189 }
190
191 bool Process::StandardOutIsDisplayed() {
192   return FileDescriptorIsDisplayed(STDOUT_FILENO);
193 }
194
195 bool Process::StandardErrIsDisplayed() {
196   return FileDescriptorIsDisplayed(STDERR_FILENO);
197 }
198
199 bool Process::FileDescriptorIsDisplayed(int fd) {
200 #if HAVE_ISATTY
201   return isatty(fd);
202 #else
203   // If we don't have isatty, just return false.
204   return false;
205 #endif
206 }
207
208 static unsigned getColumns(int FileID) {
209   // If COLUMNS is defined in the environment, wrap to that many columns.
210   if (const char *ColumnsStr = std::getenv("COLUMNS")) {
211     int Columns = std::atoi(ColumnsStr);
212     if (Columns > 0)
213       return Columns;
214   }
215
216   unsigned Columns = 0;
217
218 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
219   // Try to determine the width of the terminal.
220   struct winsize ws;
221   if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
222     Columns = ws.ws_col;
223 #endif
224
225   return Columns;
226 }
227
228 unsigned Process::StandardOutColumns() {
229   if (!StandardOutIsDisplayed())
230     return 0;
231
232   return getColumns(1);
233 }
234
235 unsigned Process::StandardErrColumns() {
236   if (!StandardErrIsDisplayed())
237     return 0;
238
239   return getColumns(2);
240 }
241
242 #ifdef HAVE_TERMINFO
243 // We manually declare these extern functions because finding the correct
244 // headers from various terminfo, curses, or other sources is harder than
245 // writing their specs down.
246 extern "C" int setupterm(char *term, int filedes, int *errret);
247 extern "C" struct term *set_curterm(struct term *termp);
248 extern "C" int del_curterm(struct term *termp);
249 extern "C" int tigetnum(char *capname);
250 #endif
251
252 static bool terminalHasColors(int fd) {
253 #ifdef HAVE_TERMINFO
254   // First, acquire a global lock because these C routines are thread hostile.
255   static sys::Mutex M;
256   MutexGuard G(M);
257
258   int errret = 0;
259   if (setupterm((char *)0, fd, &errret) != 0)
260     // Regardless of why, if we can't get terminfo, we shouldn't try to print
261     // colors.
262     return false;
263
264   // Test whether the terminal as set up supports color output. How to do this
265   // isn't entirely obvious. We can use the curses routine 'has_colors' but it
266   // would be nice to avoid a dependency on curses proper when we can make do
267   // with a minimal terminfo parsing library. Also, we don't really care whether
268   // the terminal supports the curses-specific color changing routines, merely
269   // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
270   // strategy here is just to query the baseline colors capability and if it
271   // supports colors at all to assume it will translate the escape codes into
272   // whatever range of colors it does support. We can add more detailed tests
273   // here if users report them as necessary.
274   //
275   // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
276   // the terminfo says that no colors are supported.
277   bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
278
279   // Now extract the structure allocated by setupterm and free its memory
280   // through a really silly dance.
281   struct term *termp = set_curterm((struct term *)0);
282   (void)del_curterm(termp); // Drop any errors here.
283
284   // Return true if we found a color capabilities for the current terminal.
285   if (HasColors)
286     return true;
287 #endif
288
289   // Otherwise, be conservative.
290   return false;
291 }
292
293 bool Process::FileDescriptorHasColors(int fd) {
294   // A file descriptor has colors if it is displayed and the terminal has
295   // colors.
296   return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
297 }
298
299 bool Process::StandardOutHasColors() {
300   return FileDescriptorHasColors(STDOUT_FILENO);
301 }
302
303 bool Process::StandardErrHasColors() {
304   return FileDescriptorHasColors(STDERR_FILENO);
305 }
306
307 bool Process::ColorNeedsFlush() {
308   // No, we use ANSI escape sequences.
309   return false;
310 }
311
312 #define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
313
314 #define ALLCOLORS(FGBG,BOLD) {\
315     COLOR(FGBG, "0", BOLD),\
316     COLOR(FGBG, "1", BOLD),\
317     COLOR(FGBG, "2", BOLD),\
318     COLOR(FGBG, "3", BOLD),\
319     COLOR(FGBG, "4", BOLD),\
320     COLOR(FGBG, "5", BOLD),\
321     COLOR(FGBG, "6", BOLD),\
322     COLOR(FGBG, "7", BOLD)\
323   }
324
325 static const char colorcodes[2][2][8][10] = {
326  { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
327  { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
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
366 unsigned llvm::sys::Process::GetRandomNumber() {
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 }