1 //===- Unix/Process.cpp - Unix Process Implementation --------- -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file provides the generic Unix implementation of the Process class.
12 //===----------------------------------------------------------------------===//
15 #ifdef HAVE_SYS_TIME_H
18 #ifdef HAVE_SYS_RESOURCE_H
19 #include <sys/resource.h>
24 #ifdef HAVE_MALLOC_MALLOC_H
25 #include <malloc/malloc.h>
27 #ifdef HAVE_SYS_IOCTL_H
28 # include <sys/ioctl.h>
34 //===----------------------------------------------------------------------===//
35 //=== WARNING: Implementation here must contain only generic UNIX code that
36 //=== is guaranteed to work on *all* UNIX variants.
37 //===----------------------------------------------------------------------===//
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);
55 #warning Cannot get the page size on this machine
57 return static_cast<unsigned>(page_size);
60 size_t Process::GetMallocUsage() {
61 #if defined(HAVE_MALLINFO)
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;
79 #warning Cannot get malloc info on this platform
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)
96 ::getrusage(RUSAGE_SELF, &usage);
97 return usage.ru_maxrss;
99 #warning Cannot get total memory size on this platform
105 Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time,
108 elapsed = TimeValue::now();
109 #if defined(HAVE_GETRUSAGE)
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 ) );
121 #warning Cannot get usage times on this platform
122 user_time.seconds(0);
123 user_time.microseconds(0);
125 sys_time.microseconds(0);
129 int Process::GetCurrentUserId() {
133 int Process::GetCurrentGroupId() {
137 #ifdef HAVE_MACH_MACH_H
138 #include <mach/mach.h>
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() {
147 rlim.rlim_cur = rlim.rlim_max = 0;
148 setrlimit(RLIMIT_CORE, &rlim);
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];
161 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
162 &Count, OriginalPorts, OriginalBehaviors,
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],
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);
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) {
197 // If we don't have isatty, just return false.
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);
210 unsigned Columns = 0;
212 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
213 // Try to determine the width of the terminal.
215 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
222 unsigned Process::StandardOutColumns() {
223 if (!StandardOutIsDisplayed())
226 return getColumns(1);
229 unsigned Process::StandardErrColumns() {
230 if (!StandardErrIsDisplayed())
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;
248 bool Process::StandardOutHasColors() {
249 if (!StandardOutIsDisplayed())
251 return terminalHasColors();
254 bool Process::StandardErrHasColors() {
255 if (!StandardErrIsDisplayed())
257 return terminalHasColors();
260 bool Process::ColorNeedsFlush() {
261 // No, we use ANSI escape sequences.
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)\
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) {
291 const char *Process::ResetColor() {