blob: 94e4c1bde25c2ad46d4939272516838bf16fca7c [file] [log] [blame]
Reid Spencer27dafe12004-09-11 04:56:56 +00001//===- Unix/Process.cpp - Unix Process Implementation --------- -*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer27dafe12004-09-11 04:56:56 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file provides the generic Unix implementation of the Process class.
11//
12//===----------------------------------------------------------------------===//
13
Reid Spencer721d9aa2004-12-20 00:59:28 +000014#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
Chris Lattner513a9542005-11-14 07:00:29 +000024#ifdef HAVE_MALLOC_MALLOC_H
25#include <malloc/malloc.h>
26#endif
Douglas Gregor01746742009-05-11 18:05:52 +000027#ifdef HAVE_SYS_IOCTL_H
28# include <sys/ioctl.h>
29#endif
Douglas Gregor071d73d2009-05-18 17:21:34 +000030#ifdef HAVE_TERMIOS_H
31# include <termios.h>
32#endif
Reid Spencer27dafe12004-09-11 04:56:56 +000033
34//===----------------------------------------------------------------------===//
35//=== WARNING: Implementation here must contain only generic UNIX code that
36//=== is guaranteed to work on *all* UNIX variants.
37//===----------------------------------------------------------------------===//
38
Chris Lattner26b6c0b2006-09-14 06:01:41 +000039using namespace llvm;
Reid Spencer27dafe12004-09-11 04:56:56 +000040using namespace sys;
41
42unsigned
Reid Spencer721d9aa2004-12-20 00:59:28 +000043Process::GetPageSize()
44{
Jay Foada14be3b2009-05-23 17:57:59 +000045#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
Owen Anderson0d1ea252009-08-19 21:48:34 +000049 const int page_size = 0x1000;
Jay Foada14be3b2009-05-23 17:57:59 +000050#elif defined(HAVE_GETPAGESIZE)
Owen Anderson0d1ea252009-08-19 21:48:34 +000051 const int page_size = ::getpagesize();
Reid Spencer721d9aa2004-12-20 00:59:28 +000052#elif defined(HAVE_SYSCONF)
Owen Anderson0d1ea252009-08-19 21:48:34 +000053 long page_size = ::sysconf(_SC_PAGE_SIZE);
Reid Spencer721d9aa2004-12-20 00:59:28 +000054#else
55#warning Cannot get the page size on this machine
56#endif
Reid Spencer27dafe12004-09-11 04:56:56 +000057 return static_cast<unsigned>(page_size);
58}
59
Chris Lattner513a9542005-11-14 07:00:29 +000060size_t Process::GetMallocUsage() {
Reid Spencerbc1ee842004-12-20 16:06:44 +000061#if defined(HAVE_MALLINFO)
Reid Spencer721d9aa2004-12-20 00:59:28 +000062 struct mallinfo mi;
63 mi = ::mallinfo();
64 return mi.uordblks;
Chris Lattnerc590e9a2005-11-14 07:27:56 +000065#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
Reid Spencerbc1ee842004-12-20 16:06:44 +000069#elif defined(HAVE_SBRK)
Reid Spencer721d9aa2004-12-20 00:59:28 +000070 // Note this is only an approximation and more closely resembles
71 // the value returned by mallinfo in the arena field.
Chris Lattner513a9542005-11-14 07:00:29 +000072 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;
Reid Spencer721d9aa2004-12-20 00:59:28 +000076 else
77 return 0;
78#else
79#warning Cannot get malloc info on this platform
80 return 0;
81#endif
82}
83
Jeff Cohene269a1a2005-01-08 20:15:57 +000084size_t
Reid Spencer721d9aa2004-12-20 00:59:28 +000085Process::GetTotalMemoryUsage()
86{
Reid Spencerbc1ee842004-12-20 16:06:44 +000087#if defined(HAVE_MALLINFO)
Reid Spencer721d9aa2004-12-20 00:59:28 +000088 struct mallinfo mi = ::mallinfo();
89 return mi.uordblks + mi.hblkhd;
Chris Lattnerc590e9a2005-11-14 07:27:56 +000090#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
Edward O'Callaghandf406642009-10-12 04:57:20 +000094#elif defined(HAVE_GETRUSAGE) && !defined(__HAIKU__)
Reid Spencered5e7bf2004-12-20 16:33:37 +000095 struct rusage usage;
96 ::getrusage(RUSAGE_SELF, &usage);
97 return usage.ru_maxrss;
Reid Spencer721d9aa2004-12-20 00:59:28 +000098#else
99#warning Cannot get total memory size on this platform
100 return 0;
101#endif
102}
103
104void
105Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time,
106 TimeValue& sys_time)
107{
108 elapsed = TimeValue::now();
Chris Lattner095cc372006-05-12 18:20:39 +0000109#if defined(HAVE_GETRUSAGE)
Reid Spencer721d9aa2004-12-20 00:59:28 +0000110 struct rusage usage;
111 ::getrusage(RUSAGE_SELF, &usage);
Reid Spencer8b662892004-12-20 21:43:33 +0000112 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 ) );
Reid Spencer721d9aa2004-12-20 00:59:28 +0000120#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
127}
128
Chris Lattner26b6c0b2006-09-14 06:01:41 +0000129int Process::GetCurrentUserId() {
Reid Spencer93b34732005-04-21 16:12:57 +0000130 return getuid();
131}
132
Chris Lattner26b6c0b2006-09-14 06:01:41 +0000133int Process::GetCurrentGroupId() {
Reid Spencer93b34732005-04-21 16:12:57 +0000134 return getgid();
135}
136
Nate Begemane9563982008-04-12 00:47:46 +0000137#ifdef HAVE_MACH_MACH_H
138#include <mach/mach.h>
139#endif
140
Reid Spencer68fdcc12004-12-27 06:17:27 +0000141// 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.
144void Process::PreventCoreFiles() {
145#if HAVE_SETRLIMIT
146 struct rlimit rlim;
147 rlim.rlim_cur = rlim.rlim_max = 0;
Chris Lattner505f9c82006-05-14 18:53:09 +0000148 setrlimit(RLIMIT_CORE, &rlim);
Reid Spencer68fdcc12004-12-27 06:17:27 +0000149#endif
Chris Lattner26b6c0b2006-09-14 06:01:41 +0000150
Chris Lattner5f1d0132006-09-14 06:21:59 +0000151#ifdef HAVE_MACH_MACH_H
Nate Begemane9563982008-04-12 00:47:46 +0000152 // Disable crash reporting on Mac OS X 10.0-10.4
153
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 }
171
172 // Disable crash reporting on Mac OS X 10.5
Nate Begeman82b53cd2008-03-31 22:19:25 +0000173 signal(SIGABRT, _exit);
174 signal(SIGILL, _exit);
175 signal(SIGFPE, _exit);
176 signal(SIGSEGV, _exit);
177 signal(SIGBUS, _exit);
Chris Lattner26b6c0b2006-09-14 06:01:41 +0000178#endif
Reid Spencer68fdcc12004-12-27 06:17:27 +0000179}
Reid Spencer721d9aa2004-12-20 00:59:28 +0000180
Reid Spencera01aade2005-01-01 22:29:26 +0000181bool Process::StandardInIsUserInput() {
Dan Gohmanec080462009-09-11 20:46:33 +0000182 return FileDescriptorIsDisplayed(STDIN_FILENO);
Reid Spencera01aade2005-01-01 22:29:26 +0000183}
184
185bool Process::StandardOutIsDisplayed() {
Dan Gohmanec080462009-09-11 20:46:33 +0000186 return FileDescriptorIsDisplayed(STDOUT_FILENO);
Reid Spencera01aade2005-01-01 22:29:26 +0000187}
188
189bool Process::StandardErrIsDisplayed() {
Dan Gohmanec080462009-09-11 20:46:33 +0000190 return FileDescriptorIsDisplayed(STDERR_FILENO);
191}
192
193bool Process::FileDescriptorIsDisplayed(int fd) {
Reid Spencera01aade2005-01-01 22:29:26 +0000194#if HAVE_ISATTY
Dan Gohmanec080462009-09-11 20:46:33 +0000195 return isatty(fd);
Duncan Sands740eb532009-09-06 10:53:22 +0000196#else
Reid Spencera01aade2005-01-01 22:29:26 +0000197 // If we don't have isatty, just return false.
198 return false;
Duncan Sands740eb532009-09-06 10:53:22 +0000199#endif
Reid Spencera01aade2005-01-01 22:29:26 +0000200}
Douglas Gregor01746742009-05-11 18:05:52 +0000201
202static 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 }
209
210 unsigned Columns = 0;
211
Douglas Gregor071d73d2009-05-18 17:21:34 +0000212#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
Douglas Gregor01746742009-05-11 18:05:52 +0000213 // 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
218
219 return Columns;
220}
221
222unsigned Process::StandardOutColumns() {
223 if (!StandardOutIsDisplayed())
224 return 0;
225
226 return getColumns(1);
227}
228
229unsigned Process::StandardErrColumns() {
230 if (!StandardErrIsDisplayed())
231 return 0;
232
233 return getColumns(2);
234}
Torok Edwine8ebb0f2009-06-04 07:09:50 +0000235
236static 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;
246}
247
248bool Process::StandardOutHasColors() {
249 if (!StandardOutIsDisplayed())
250 return false;
251 return terminalHasColors();
252}
253
254bool Process::StandardErrHasColors() {
255 if (!StandardErrIsDisplayed())
256 return false;
257 return terminalHasColors();
258}
259
260bool Process::ColorNeedsFlush() {
261 // No, we use ANSI escape sequences.
262 return false;
263}
264
265#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
266
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 }
277
278static const char* colorcodes[2][2][8] = {
279 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
280 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
281};
282
283const char *Process::OutputColor(char code, bool bold, bool bg) {
284 return colorcodes[bg?1:0][bold?1:0][code&7];
285}
286
287const char *Process::OutputBold(bool bg) {
288 return "\033[1m";
289}
290
291const char *Process::ResetColor() {
292 return "\033[0m";
293}