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>
21 // DragonFly BSD has deprecated <malloc.h> for <stdlib.h> instead,
22 // Unix.h includes this for us already.
23 #if defined(HAVE_MALLOC_H) && !defined(__DragonFly__)
26 #ifdef HAVE_MALLOC_MALLOC_H
27 #include <malloc/malloc.h>
29 #ifdef HAVE_SYS_IOCTL_H
30 # include <sys/ioctl.h>
36 //===----------------------------------------------------------------------===//
37 //=== WARNING: Implementation here must contain only generic UNIX code that
38 //=== is guaranteed to work on *all* UNIX variants.
39 //===----------------------------------------------------------------------===//
45 Process::GetPageSize()
47 #if defined(__CYGWIN__)
48 // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
49 // memory protection and mmap() is 4k.
50 // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
51 const int page_size = 0x1000;
52 #elif defined(HAVE_GETPAGESIZE)
53 const int page_size = ::getpagesize();
54 #elif defined(HAVE_SYSCONF)
55 long page_size = ::sysconf(_SC_PAGE_SIZE);
57 #warning Cannot get the page size on this machine
59 return static_cast<unsigned>(page_size);
62 size_t Process::GetMallocUsage() {
63 #if defined(HAVE_MALLINFO)
67 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
68 malloc_statistics_t Stats;
69 malloc_zone_statistics(malloc_default_zone(), &Stats);
70 return Stats.size_in_use; // darwin
71 #elif defined(HAVE_SBRK)
72 // Note this is only an approximation and more closely resembles
73 // the value returned by mallinfo in the arena field.
74 static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
75 char *EndOfMemory = (char*)sbrk(0);
76 if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
77 return EndOfMemory - StartOfMemory;
81 #warning Cannot get malloc info on this platform
87 Process::GetTotalMemoryUsage()
89 #if defined(HAVE_MALLINFO)
90 struct mallinfo mi = ::mallinfo();
91 return mi.uordblks + mi.hblkhd;
92 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
93 malloc_statistics_t Stats;
94 malloc_zone_statistics(malloc_default_zone(), &Stats);
95 return Stats.size_allocated; // darwin
96 #elif defined(HAVE_GETRUSAGE) && !defined(__HAIKU__)
98 ::getrusage(RUSAGE_SELF, &usage);
99 return usage.ru_maxrss;
101 #warning Cannot get total memory size on this platform
107 Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time,
110 elapsed = TimeValue::now();
111 #if defined(HAVE_GETRUSAGE)
113 ::getrusage(RUSAGE_SELF, &usage);
114 user_time = TimeValue(
115 static_cast<TimeValue::SecondsType>( usage.ru_utime.tv_sec ),
116 static_cast<TimeValue::NanoSecondsType>( usage.ru_utime.tv_usec *
117 TimeValue::NANOSECONDS_PER_MICROSECOND ) );
118 sys_time = TimeValue(
119 static_cast<TimeValue::SecondsType>( usage.ru_stime.tv_sec ),
120 static_cast<TimeValue::NanoSecondsType>( usage.ru_stime.tv_usec *
121 TimeValue::NANOSECONDS_PER_MICROSECOND ) );
123 #warning Cannot get usage times on this platform
124 user_time.seconds(0);
125 user_time.microseconds(0);
127 sys_time.microseconds(0);
131 int Process::GetCurrentUserId() {
135 int Process::GetCurrentGroupId() {
139 #ifdef HAVE_MACH_MACH_H
140 #include <mach/mach.h>
143 // Some LLVM programs such as bugpoint produce core files as a normal part of
144 // their operation. To prevent the disk from filling up, this function
145 // does what's necessary to prevent their generation.
146 void Process::PreventCoreFiles() {
149 rlim.rlim_cur = rlim.rlim_max = 0;
150 setrlimit(RLIMIT_CORE, &rlim);
153 #ifdef HAVE_MACH_MACH_H
154 // Disable crash reporting on Mac OS X 10.0-10.4
156 // get information about the original set of exception ports for the task
157 mach_msg_type_number_t Count = 0;
158 exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
159 exception_port_t OriginalPorts[EXC_TYPES_COUNT];
160 exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
161 thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
163 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
164 &Count, OriginalPorts, OriginalBehaviors,
166 if (err == KERN_SUCCESS) {
167 // replace each with MACH_PORT_NULL.
168 for (unsigned i = 0; i != Count; ++i)
169 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
170 MACH_PORT_NULL, OriginalBehaviors[i],
174 // Disable crash reporting on Mac OS X 10.5
175 signal(SIGABRT, _exit);
176 signal(SIGILL, _exit);
177 signal(SIGFPE, _exit);
178 signal(SIGSEGV, _exit);
179 signal(SIGBUS, _exit);
183 bool Process::StandardInIsUserInput() {
184 return FileDescriptorIsDisplayed(STDIN_FILENO);
187 bool Process::StandardOutIsDisplayed() {
188 return FileDescriptorIsDisplayed(STDOUT_FILENO);
191 bool Process::StandardErrIsDisplayed() {
192 return FileDescriptorIsDisplayed(STDERR_FILENO);
195 bool Process::FileDescriptorIsDisplayed(int fd) {
199 // If we don't have isatty, just return false.
204 static unsigned getColumns(int FileID) {
205 // If COLUMNS is defined in the environment, wrap to that many columns.
206 if (const char *ColumnsStr = std::getenv("COLUMNS")) {
207 int Columns = std::atoi(ColumnsStr);
212 unsigned Columns = 0;
214 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
215 // Try to determine the width of the terminal.
217 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
224 unsigned Process::StandardOutColumns() {
225 if (!StandardOutIsDisplayed())
228 return getColumns(1);
231 unsigned Process::StandardErrColumns() {
232 if (!StandardErrIsDisplayed())
235 return getColumns(2);
238 static bool terminalHasColors() {
239 if (const char *term = std::getenv("TERM")) {
240 // Most modern terminals support ANSI escape sequences for colors.
241 // We could check terminfo, or have a list of known terms that support
242 // colors, but that would be overkill.
243 // The user can always ask for no colors by setting TERM to dumb, or
244 // using a commandline flag.
245 return strcmp(term, "dumb") != 0;
250 bool Process::StandardOutHasColors() {
251 if (!StandardOutIsDisplayed())
253 return terminalHasColors();
256 bool Process::StandardErrHasColors() {
257 if (!StandardErrIsDisplayed())
259 return terminalHasColors();
262 bool Process::ColorNeedsFlush() {
263 // No, we use ANSI escape sequences.
267 #define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
269 #define ALLCOLORS(FGBG,BOLD) {\
270 COLOR(FGBG, "0", BOLD),\
271 COLOR(FGBG, "1", BOLD),\
272 COLOR(FGBG, "2", BOLD),\
273 COLOR(FGBG, "3", BOLD),\
274 COLOR(FGBG, "4", BOLD),\
275 COLOR(FGBG, "5", BOLD),\
276 COLOR(FGBG, "6", BOLD),\
277 COLOR(FGBG, "7", BOLD)\
280 static const char colorcodes[2][2][8][10] = {
281 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
282 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
285 const char *Process::OutputColor(char code, bool bold, bool bg) {
286 return colorcodes[bg?1:0][bold?1:0][code&7];
289 const char *Process::OutputBold(bool bg) {
293 const char *Process::ResetColor() {