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 // Pull in the headers we found to go with the terminfo reading library (tinfo,
42 // curses, whatever it may be). We have to pull in the 'curses.h' header as the
43 // SysV spec only provides certain values and defines from that header even
44 // though we work hard to not link against all of the curses implementation
47 # if defined(HAVE_CURSES_H)
49 # elif defined(HAVE_NCURSES_H)
51 # elif defined(HAVE_NCURSESW_H)
52 # include <ncursesw.h>
53 # elif defined(HAVE_NCURSES_CURSES_H)
54 # include <ncurses/curses.h>
55 # elif defined(HAVE_NCURSESW_CURSES_H)
56 # include <ncursesw/curses.h>
58 # if defined(HAVE_TERM_H)
63 //===----------------------------------------------------------------------===//
64 //=== WARNING: Implementation here must contain only generic UNIX code that
65 //=== is guaranteed to work on *all* UNIX variants.
66 //===----------------------------------------------------------------------===//
72 process::id_type self_process::get_id() {
76 static std::pair<TimeValue, TimeValue> getRUsageTimes() {
77 #if defined(HAVE_GETRUSAGE)
79 ::getrusage(RUSAGE_SELF, &RU);
80 return std::make_pair(
82 static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec),
83 static_cast<TimeValue::NanoSecondsType>(
84 RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)),
86 static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec),
87 static_cast<TimeValue::NanoSecondsType>(
88 RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)));
90 #warning Cannot get usage times on this platform
91 return std::make_pair(TimeValue(), TimeValue());
95 TimeValue self_process::get_user_time() const {
96 #if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0
97 // Try to get a high resolution CPU timer.
99 if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0)
100 return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec),
101 static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec));
104 // Otherwise fall back to rusage based timing.
105 return getRUsageTimes().first;
108 TimeValue self_process::get_system_time() const {
109 // We can only collect system time by inspecting the results of getrusage.
110 return getRUsageTimes().second;
113 static unsigned getPageSize() {
114 #if defined(__CYGWIN__)
115 // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
116 // memory protection and mmap() is 4k.
117 // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
118 const int page_size = 0x1000;
119 #elif defined(HAVE_GETPAGESIZE)
120 const int page_size = ::getpagesize();
121 #elif defined(HAVE_SYSCONF)
122 long page_size = ::sysconf(_SC_PAGE_SIZE);
124 #warning Cannot get the page size on this machine
126 return static_cast<unsigned>(page_size);
129 // This constructor guaranteed to be run exactly once on a single thread, and
130 // sets up various process invariants that can be queried cheaply from then on.
131 self_process::self_process() : PageSize(getPageSize()) {
135 size_t Process::GetMallocUsage() {
136 #if defined(HAVE_MALLINFO)
140 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
141 malloc_statistics_t Stats;
142 malloc_zone_statistics(malloc_default_zone(), &Stats);
143 return Stats.size_in_use; // darwin
144 #elif defined(HAVE_SBRK)
145 // Note this is only an approximation and more closely resembles
146 // the value returned by mallinfo in the arena field.
147 static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
148 char *EndOfMemory = (char*)sbrk(0);
149 if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
150 return EndOfMemory - StartOfMemory;
154 #warning Cannot get malloc info on this platform
159 void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
160 TimeValue &sys_time) {
161 elapsed = TimeValue::now();
162 llvm::tie(user_time, sys_time) = getRUsageTimes();
165 int Process::GetCurrentUserId() {
169 int Process::GetCurrentGroupId() {
173 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
174 #include <mach/mach.h>
177 // Some LLVM programs such as bugpoint produce core files as a normal part of
178 // their operation. To prevent the disk from filling up, this function
179 // does what's necessary to prevent their generation.
180 void Process::PreventCoreFiles() {
183 rlim.rlim_cur = rlim.rlim_max = 0;
184 setrlimit(RLIMIT_CORE, &rlim);
187 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
188 // Disable crash reporting on Mac OS X 10.0-10.4
190 // get information about the original set of exception ports for the task
191 mach_msg_type_number_t Count = 0;
192 exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
193 exception_port_t OriginalPorts[EXC_TYPES_COUNT];
194 exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
195 thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
197 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
198 &Count, OriginalPorts, OriginalBehaviors,
200 if (err == KERN_SUCCESS) {
201 // replace each with MACH_PORT_NULL.
202 for (unsigned i = 0; i != Count; ++i)
203 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
204 MACH_PORT_NULL, OriginalBehaviors[i],
208 // Disable crash reporting on Mac OS X 10.5
209 signal(SIGABRT, _exit);
210 signal(SIGILL, _exit);
211 signal(SIGFPE, _exit);
212 signal(SIGSEGV, _exit);
213 signal(SIGBUS, _exit);
217 bool Process::StandardInIsUserInput() {
218 return FileDescriptorIsDisplayed(STDIN_FILENO);
221 bool Process::StandardOutIsDisplayed() {
222 return FileDescriptorIsDisplayed(STDOUT_FILENO);
225 bool Process::StandardErrIsDisplayed() {
226 return FileDescriptorIsDisplayed(STDERR_FILENO);
229 bool Process::FileDescriptorIsDisplayed(int fd) {
233 // If we don't have isatty, just return false.
238 static unsigned getColumns(int FileID) {
239 // If COLUMNS is defined in the environment, wrap to that many columns.
240 if (const char *ColumnsStr = std::getenv("COLUMNS")) {
241 int Columns = std::atoi(ColumnsStr);
246 unsigned Columns = 0;
248 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
249 // Try to determine the width of the terminal.
251 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
258 unsigned Process::StandardOutColumns() {
259 if (!StandardOutIsDisplayed())
262 return getColumns(1);
265 unsigned Process::StandardErrColumns() {
266 if (!StandardErrIsDisplayed())
269 return getColumns(2);
272 static bool terminalHasColors(int fd) {
274 // First, acquire a global lock because these C routines are thread hostile.
279 if (setupterm((char *)0, fd, &errret) != OK)
280 // Regardless of why, if we can't get terminfo, we shouldn't try to print
284 // Test whether the terminal as set up supports color output. How to do this
285 // isn't entirely obvious. We can use the curses routine 'has_colors' but it
286 // would be nice to avoid a dependency on curses proper when we can make do
287 // with a minimal terminfo parsing library. Also, we don't really care whether
288 // the terminal supports the curses-specific color changing routines, merely
289 // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
290 // strategy here is just to query the baseline colors capability and if it
291 // supports colors at all to assume it will translate the escape codes into
292 // whatever range of colors it does support. We can add more detailed tests
293 // here if users report them as necessary.
295 // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
296 // the terminfo says that no colors are supported.
297 if (tigetnum("colors") > 0)
301 // Otherwise, be conservative.
305 bool Process::FileDescriptorHasColors(int fd) {
306 // A file descriptor has colors if it is displayed and the terminal has
308 return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
311 bool Process::StandardOutHasColors() {
312 return FileDescriptorHasColors(STDOUT_FILENO);
315 bool Process::StandardErrHasColors() {
316 return FileDescriptorHasColors(STDERR_FILENO);
319 bool Process::ColorNeedsFlush() {
320 // No, we use ANSI escape sequences.
324 #define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
326 #define ALLCOLORS(FGBG,BOLD) {\
327 COLOR(FGBG, "0", BOLD),\
328 COLOR(FGBG, "1", BOLD),\
329 COLOR(FGBG, "2", BOLD),\
330 COLOR(FGBG, "3", BOLD),\
331 COLOR(FGBG, "4", BOLD),\
332 COLOR(FGBG, "5", BOLD),\
333 COLOR(FGBG, "6", BOLD),\
334 COLOR(FGBG, "7", BOLD)\
337 static const char colorcodes[2][2][8][10] = {
338 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
339 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
342 const char *Process::OutputColor(char code, bool bold, bool bg) {
343 return colorcodes[bg?1:0][bold?1:0][code&7];
346 const char *Process::OutputBold(bool bg) {
350 const char *Process::OutputReverse() {
354 const char *Process::ResetColor() {
358 #if !defined(HAVE_ARC4RANDOM)
359 static unsigned GetRandomNumberSeed() {
360 // Attempt to get the initial seed from /dev/urandom, if possible.
361 if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
363 int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
364 ::fclose(RandomSource);
366 // Return the seed if the read was successful.
371 // Otherwise, swizzle the current time and the process ID to form a reasonable
373 TimeValue Now = TimeValue::now();
374 return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
378 unsigned llvm::sys::Process::GetRandomNumber() {
379 #if defined(HAVE_ARC4RANDOM)
382 static int x = (::srand(GetRandomNumberSeed()), 0);