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 #include "llvm/ADT/Hashing.h"
16 #include "llvm/Support/Mutex.h"
17 #include "llvm/Support/MutexGuard.h"
18 #include "llvm/Support/TimeValue.h"
19 #ifdef HAVE_SYS_TIME_H
22 #ifdef HAVE_SYS_RESOURCE_H
23 #include <sys/resource.h>
25 // DragonFlyBSD, OpenBSD, and Bitrig have deprecated <malloc.h> for
26 // <stdlib.h> instead. Unix.h includes this for us already.
27 #if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \
28 !defined(__OpenBSD__) && !defined(__Bitrig__)
31 #ifdef HAVE_MALLOC_MALLOC_H
32 #include <malloc/malloc.h>
34 #ifdef HAVE_SYS_IOCTL_H
35 # include <sys/ioctl.h>
41 //===----------------------------------------------------------------------===//
42 //=== WARNING: Implementation here must contain only generic UNIX code that
43 //=== is guaranteed to work on *all* UNIX variants.
44 //===----------------------------------------------------------------------===//
50 process::id_type self_process::get_id() {
54 static std::pair<TimeValue, TimeValue> getRUsageTimes() {
55 #if defined(HAVE_GETRUSAGE)
57 ::getrusage(RUSAGE_SELF, &RU);
58 return std::make_pair(
60 static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec),
61 static_cast<TimeValue::NanoSecondsType>(
62 RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)),
64 static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec),
65 static_cast<TimeValue::NanoSecondsType>(
66 RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)));
68 #warning Cannot get usage times on this platform
69 return std::make_pair(TimeValue(), TimeValue());
73 TimeValue self_process::get_user_time() const {
74 #if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0
75 // Try to get a high resolution CPU timer.
77 if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0)
78 return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec),
79 static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec));
82 // Otherwise fall back to rusage based timing.
83 return getRUsageTimes().first;
86 TimeValue self_process::get_system_time() const {
87 // We can only collect system time by inspecting the results of getrusage.
88 return getRUsageTimes().second;
91 static unsigned getPageSize() {
92 #if defined(__CYGWIN__)
93 // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
94 // memory protection and mmap() is 4k.
95 // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
96 const int page_size = 0x1000;
97 #elif defined(HAVE_GETPAGESIZE)
98 const int page_size = ::getpagesize();
99 #elif defined(HAVE_SYSCONF)
100 long page_size = ::sysconf(_SC_PAGE_SIZE);
102 #warning Cannot get the page size on this machine
104 return static_cast<unsigned>(page_size);
107 // This constructor guaranteed to be run exactly once on a single thread, and
108 // sets up various process invariants that can be queried cheaply from then on.
109 self_process::self_process() : PageSize(getPageSize()) {
113 size_t Process::GetMallocUsage() {
114 #if defined(HAVE_MALLINFO)
118 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
119 malloc_statistics_t Stats;
120 malloc_zone_statistics(malloc_default_zone(), &Stats);
121 return Stats.size_in_use; // darwin
122 #elif defined(HAVE_SBRK)
123 // Note this is only an approximation and more closely resembles
124 // the value returned by mallinfo in the arena field.
125 static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
126 char *EndOfMemory = (char*)sbrk(0);
127 if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
128 return EndOfMemory - StartOfMemory;
132 #warning Cannot get malloc info on this platform
137 void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
138 TimeValue &sys_time) {
139 elapsed = TimeValue::now();
140 llvm::tie(user_time, sys_time) = getRUsageTimes();
143 int Process::GetCurrentUserId() {
147 int Process::GetCurrentGroupId() {
151 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
152 #include <mach/mach.h>
155 // Some LLVM programs such as bugpoint produce core files as a normal part of
156 // their operation. To prevent the disk from filling up, this function
157 // does what's necessary to prevent their generation.
158 void Process::PreventCoreFiles() {
161 rlim.rlim_cur = rlim.rlim_max = 0;
162 setrlimit(RLIMIT_CORE, &rlim);
165 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
166 // Disable crash reporting on Mac OS X 10.0-10.4
168 // get information about the original set of exception ports for the task
169 mach_msg_type_number_t Count = 0;
170 exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
171 exception_port_t OriginalPorts[EXC_TYPES_COUNT];
172 exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
173 thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
175 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
176 &Count, OriginalPorts, OriginalBehaviors,
178 if (err == KERN_SUCCESS) {
179 // replace each with MACH_PORT_NULL.
180 for (unsigned i = 0; i != Count; ++i)
181 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
182 MACH_PORT_NULL, OriginalBehaviors[i],
186 // Disable crash reporting on Mac OS X 10.5
187 signal(SIGABRT, _exit);
188 signal(SIGILL, _exit);
189 signal(SIGFPE, _exit);
190 signal(SIGSEGV, _exit);
191 signal(SIGBUS, _exit);
195 bool Process::StandardInIsUserInput() {
196 return FileDescriptorIsDisplayed(STDIN_FILENO);
199 bool Process::StandardOutIsDisplayed() {
200 return FileDescriptorIsDisplayed(STDOUT_FILENO);
203 bool Process::StandardErrIsDisplayed() {
204 return FileDescriptorIsDisplayed(STDERR_FILENO);
207 bool Process::FileDescriptorIsDisplayed(int fd) {
211 // If we don't have isatty, just return false.
216 static unsigned getColumns(int FileID) {
217 // If COLUMNS is defined in the environment, wrap to that many columns.
218 if (const char *ColumnsStr = std::getenv("COLUMNS")) {
219 int Columns = std::atoi(ColumnsStr);
224 unsigned Columns = 0;
226 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
227 // Try to determine the width of the terminal.
229 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
236 unsigned Process::StandardOutColumns() {
237 if (!StandardOutIsDisplayed())
240 return getColumns(1);
243 unsigned Process::StandardErrColumns() {
244 if (!StandardErrIsDisplayed())
247 return getColumns(2);
251 // We manually declare these two extern functions because finding the correct
252 // headers from various terminfo, curses, or other sources is harder than
253 // writing their specs down.
254 extern "C" int setupterm(char *term, int filedes, int *errret);
255 extern "C" int tigetnum(char *capname);
258 static bool terminalHasColors(int fd) {
260 // First, acquire a global lock because these C routines are thread hostile.
265 if (setupterm((char *)0, fd, &errret) != 0)
266 // Regardless of why, if we can't get terminfo, we shouldn't try to print
270 // Test whether the terminal as set up supports color output. How to do this
271 // isn't entirely obvious. We can use the curses routine 'has_colors' but it
272 // would be nice to avoid a dependency on curses proper when we can make do
273 // with a minimal terminfo parsing library. Also, we don't really care whether
274 // the terminal supports the curses-specific color changing routines, merely
275 // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
276 // strategy here is just to query the baseline colors capability and if it
277 // supports colors at all to assume it will translate the escape codes into
278 // whatever range of colors it does support. We can add more detailed tests
279 // here if users report them as necessary.
281 // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
282 // the terminfo says that no colors are supported.
283 if (tigetnum((char *)"colors") > 0)
287 // Otherwise, be conservative.
291 bool Process::FileDescriptorHasColors(int fd) {
292 // A file descriptor has colors if it is displayed and the terminal has
294 return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
297 bool Process::StandardOutHasColors() {
298 return FileDescriptorHasColors(STDOUT_FILENO);
301 bool Process::StandardErrHasColors() {
302 return FileDescriptorHasColors(STDERR_FILENO);
305 bool Process::ColorNeedsFlush() {
306 // No, we use ANSI escape sequences.
310 #define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
312 #define ALLCOLORS(FGBG,BOLD) {\
313 COLOR(FGBG, "0", BOLD),\
314 COLOR(FGBG, "1", BOLD),\
315 COLOR(FGBG, "2", BOLD),\
316 COLOR(FGBG, "3", BOLD),\
317 COLOR(FGBG, "4", BOLD),\
318 COLOR(FGBG, "5", BOLD),\
319 COLOR(FGBG, "6", BOLD),\
320 COLOR(FGBG, "7", BOLD)\
323 static const char colorcodes[2][2][8][10] = {
324 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
325 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
328 const char *Process::OutputColor(char code, bool bold, bool bg) {
329 return colorcodes[bg?1:0][bold?1:0][code&7];
332 const char *Process::OutputBold(bool bg) {
336 const char *Process::OutputReverse() {
340 const char *Process::ResetColor() {
344 #if !defined(HAVE_ARC4RANDOM)
345 static unsigned GetRandomNumberSeed() {
346 // Attempt to get the initial seed from /dev/urandom, if possible.
347 if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
349 int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
350 ::fclose(RandomSource);
352 // Return the seed if the read was successful.
357 // Otherwise, swizzle the current time and the process ID to form a reasonable
359 TimeValue Now = TimeValue::now();
360 return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
364 unsigned llvm::sys::Process::GetRandomNumber() {
365 #if defined(HAVE_ARC4RANDOM)
368 static int x = (::srand(GetRandomNumberSeed()), 0);