add some missing quotes in debug output
[llvm/avr.git] / lib / System / Unix / Process.inc
blobd7155852bf2aa5de55ffc2b82c80b222d82252b1
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.
12 //===----------------------------------------------------------------------===//
14 #include "Unix.h"
15 #ifdef HAVE_SYS_TIME_H
16 #include <sys/time.h>
17 #endif
18 #ifdef HAVE_SYS_RESOURCE_H
19 #include <sys/resource.h>
20 #endif
21 #ifdef HAVE_MALLOC_H
22 #include <malloc.h>
23 #endif
24 #ifdef HAVE_MALLOC_MALLOC_H
25 #include <malloc/malloc.h>
26 #endif
27 #ifdef HAVE_SYS_IOCTL_H
28 #  include <sys/ioctl.h>
29 #endif
30 #ifdef HAVE_TERMIOS_H
31 #  include <termios.h>
32 #endif
34 //===----------------------------------------------------------------------===//
35 //=== WARNING: Implementation here must contain only generic UNIX code that
36 //===          is guaranteed to work on *all* UNIX variants.
37 //===----------------------------------------------------------------------===//
39 using namespace llvm;
40 using namespace sys;
42 unsigned 
43 Process::GetPageSize() 
45 #if defined(__CYGWIN__)
46   // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
47   // memory protection and mmap() is 4k.
48   // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
49   const int page_size = 0x1000;
50 #elif defined(HAVE_GETPAGESIZE)
51   const int page_size = ::getpagesize();
52 #elif defined(HAVE_SYSCONF)
53   long page_size = ::sysconf(_SC_PAGE_SIZE);
54 #else
55 #warning Cannot get the page size on this machine
56 #endif
57   return static_cast<unsigned>(page_size);
60 size_t Process::GetMallocUsage() {
61 #if defined(HAVE_MALLINFO)
62   struct mallinfo mi;
63   mi = ::mallinfo();
64   return mi.uordblks;
65 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
66   malloc_statistics_t Stats;
67   malloc_zone_statistics(malloc_default_zone(), &Stats);
68   return Stats.size_in_use;   // darwin
69 #elif defined(HAVE_SBRK)
70   // Note this is only an approximation and more closely resembles
71   // the value returned by mallinfo in the arena field.
72   static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
73   char *EndOfMemory = (char*)sbrk(0);
74   if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
75     return EndOfMemory - StartOfMemory;
76   else
77     return 0;
78 #else
79 #warning Cannot get malloc info on this platform
80   return 0;
81 #endif
84 size_t
85 Process::GetTotalMemoryUsage()
87 #if defined(HAVE_MALLINFO)
88   struct mallinfo mi = ::mallinfo();
89   return mi.uordblks + mi.hblkhd;
90 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
91   malloc_statistics_t Stats;
92   malloc_zone_statistics(malloc_default_zone(), &Stats);
93   return Stats.size_allocated;   // darwin
94 #elif defined(HAVE_GETRUSAGE)
95   struct rusage usage;
96   ::getrusage(RUSAGE_SELF, &usage);
97   return usage.ru_maxrss;
98 #else
99 #warning Cannot get total memory size on this platform
100   return 0;
101 #endif
104 void
105 Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time, 
106                       TimeValue& sys_time)
108   elapsed = TimeValue::now();
109 #if defined(HAVE_GETRUSAGE)
110   struct rusage usage;
111   ::getrusage(RUSAGE_SELF, &usage);
112   user_time = TimeValue( 
113     static_cast<TimeValue::SecondsType>( usage.ru_utime.tv_sec ), 
114     static_cast<TimeValue::NanoSecondsType>( usage.ru_utime.tv_usec * 
115       TimeValue::NANOSECONDS_PER_MICROSECOND ) );
116   sys_time = TimeValue( 
117     static_cast<TimeValue::SecondsType>( usage.ru_stime.tv_sec ), 
118     static_cast<TimeValue::NanoSecondsType>( usage.ru_stime.tv_usec * 
119       TimeValue::NANOSECONDS_PER_MICROSECOND ) );
120 #else
121 #warning Cannot get usage times on this platform
122   user_time.seconds(0);
123   user_time.microseconds(0);
124   sys_time.seconds(0);
125   sys_time.microseconds(0);
126 #endif
129 int Process::GetCurrentUserId() {
130   return getuid();
133 int Process::GetCurrentGroupId() {
134   return getgid();
137 #ifdef HAVE_MACH_MACH_H
138 #include <mach/mach.h>
139 #endif
141 // Some LLVM programs such as bugpoint produce core files as a normal part of
142 // their operation. To prevent the disk from filling up, this function
143 // does what's necessary to prevent their generation.
144 void Process::PreventCoreFiles() {
145 #if HAVE_SETRLIMIT
146   struct rlimit rlim;
147   rlim.rlim_cur = rlim.rlim_max = 0;
148   setrlimit(RLIMIT_CORE, &rlim);
149 #endif
151 #ifdef HAVE_MACH_MACH_H
152   // Disable crash reporting on Mac OS X 10.0-10.4
154   // get information about the original set of exception ports for the task
155   mach_msg_type_number_t Count = 0;
156   exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
157   exception_port_t OriginalPorts[EXC_TYPES_COUNT];
158   exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
159   thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
160   kern_return_t err = 
161     task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
162                              &Count, OriginalPorts, OriginalBehaviors,
163                              OriginalFlavors);
164   if (err == KERN_SUCCESS) {
165     // replace each with MACH_PORT_NULL.
166     for (unsigned i = 0; i != Count; ++i)
167       task_set_exception_ports(mach_task_self(), OriginalMasks[i], 
168                                MACH_PORT_NULL, OriginalBehaviors[i],
169                                OriginalFlavors[i]);
170   }
172   // Disable crash reporting on Mac OS X 10.5
173   signal(SIGABRT, _exit);
174   signal(SIGILL,  _exit);
175   signal(SIGFPE,  _exit);
176   signal(SIGSEGV, _exit);
177   signal(SIGBUS,  _exit);
178 #endif
181 bool Process::StandardInIsUserInput() {
182   return FileDescriptorIsDisplayed(STDIN_FILENO);
185 bool Process::StandardOutIsDisplayed() {
186   return FileDescriptorIsDisplayed(STDOUT_FILENO);
189 bool Process::StandardErrIsDisplayed() {
190   return FileDescriptorIsDisplayed(STDERR_FILENO);
193 bool Process::FileDescriptorIsDisplayed(int fd) {
194 #if HAVE_ISATTY
195   return isatty(fd);
196 #else
197   // If we don't have isatty, just return false.
198   return false;
199 #endif
202 static unsigned getColumns(int FileID) {
203   // If COLUMNS is defined in the environment, wrap to that many columns.
204   if (const char *ColumnsStr = std::getenv("COLUMNS")) {
205     int Columns = std::atoi(ColumnsStr);
206     if (Columns > 0)
207       return Columns;
208   }
210   unsigned Columns = 0;
212 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
213   // Try to determine the width of the terminal.
214   struct winsize ws;
215   if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
216     Columns = ws.ws_col;
217 #endif
219   return Columns;
222 unsigned Process::StandardOutColumns() {
223   if (!StandardOutIsDisplayed())
224     return 0;
226   return getColumns(1);
229 unsigned Process::StandardErrColumns() {
230   if (!StandardErrIsDisplayed())
231     return 0;
233   return getColumns(2);
236 static bool terminalHasColors() {
237   if (const char *term = std::getenv("TERM")) {
238     // Most modern terminals support ANSI escape sequences for colors.
239     // We could check terminfo, or have a list of known terms that support
240     // colors, but that would be overkill.
241     // The user can always ask for no colors by setting TERM to dumb, or
242     // using a commandline flag.
243     return strcmp(term, "dumb") != 0;
244   }
245   return false;
248 bool Process::StandardOutHasColors() {
249   if (!StandardOutIsDisplayed())
250     return false;
251   return terminalHasColors();
254 bool Process::StandardErrHasColors() {
255   if (!StandardErrIsDisplayed())
256     return false;
257   return terminalHasColors();
260 bool Process::ColorNeedsFlush() {
261   // No, we use ANSI escape sequences.
262   return false;
265 #define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
267 #define ALLCOLORS(FGBG,BOLD) {\
268     COLOR(FGBG, "0", BOLD),\
269     COLOR(FGBG, "1", BOLD),\
270     COLOR(FGBG, "2", BOLD),\
271     COLOR(FGBG, "3", BOLD),\
272     COLOR(FGBG, "4", BOLD),\
273     COLOR(FGBG, "5", BOLD),\
274     COLOR(FGBG, "6", BOLD),\
275     COLOR(FGBG, "7", BOLD)\
276   }
278 static const char* colorcodes[2][2][8] = {
279  { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
280  { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
283 const char *Process::OutputColor(char code, bool bold, bool bg) {
284   return colorcodes[bg?1:0][bold?1:0][code&7];
287 const char *Process::OutputBold(bool bg) {
288   return "\033[1m";
291 const char *Process::ResetColor() {
292   return "\033[0m";