OSDN Git Service

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