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 // On Cygwin, getpagesize() returns 64k and offset in mmap(3) should be
92 // aligned to its pagesize.
93 static unsigned getPageSize() {
94 #if defined(HAVE_GETPAGESIZE)
95 const int page_size = ::getpagesize();
96 #elif defined(HAVE_SYSCONF)
97 long page_size = ::sysconf(_SC_PAGE_SIZE);
99 #warning Cannot get the page size on this machine
101 return static_cast<unsigned>(page_size);
104 // This constructor guaranteed to be run exactly once on a single thread, and
105 // sets up various process invariants that can be queried cheaply from then on.
106 self_process::self_process() : PageSize(getPageSize()) {
110 size_t Process::GetMallocUsage() {
111 #if defined(HAVE_MALLINFO)
115 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
116 malloc_statistics_t Stats;
117 malloc_zone_statistics(malloc_default_zone(), &Stats);
118 return Stats.size_in_use; // darwin
119 #elif defined(HAVE_SBRK)
120 // Note this is only an approximation and more closely resembles
121 // the value returned by mallinfo in the arena field.
122 static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
123 char *EndOfMemory = (char*)sbrk(0);
124 if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
125 return EndOfMemory - StartOfMemory;
129 #warning Cannot get malloc info on this platform
134 void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
135 TimeValue &sys_time) {
136 elapsed = TimeValue::now();
137 llvm::tie(user_time, sys_time) = getRUsageTimes();
140 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
141 #include <mach/mach.h>
144 // Some LLVM programs such as bugpoint produce core files as a normal part of
145 // their operation. To prevent the disk from filling up, this function
146 // does what's necessary to prevent their generation.
147 void Process::PreventCoreFiles() {
150 rlim.rlim_cur = rlim.rlim_max = 0;
151 setrlimit(RLIMIT_CORE, &rlim);
154 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
155 // Disable crash reporting on Mac OS X 10.0-10.4
157 // get information about the original set of exception ports for the task
158 mach_msg_type_number_t Count = 0;
159 exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
160 exception_port_t OriginalPorts[EXC_TYPES_COUNT];
161 exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
162 thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
164 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
165 &Count, OriginalPorts, OriginalBehaviors,
167 if (err == KERN_SUCCESS) {
168 // replace each with MACH_PORT_NULL.
169 for (unsigned i = 0; i != Count; ++i)
170 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
171 MACH_PORT_NULL, OriginalBehaviors[i],
175 // Disable crash reporting on Mac OS X 10.5
176 signal(SIGABRT, _exit);
177 signal(SIGILL, _exit);
178 signal(SIGFPE, _exit);
179 signal(SIGSEGV, _exit);
180 signal(SIGBUS, _exit);
184 bool Process::StandardInIsUserInput() {
185 return FileDescriptorIsDisplayed(STDIN_FILENO);
188 bool Process::StandardOutIsDisplayed() {
189 return FileDescriptorIsDisplayed(STDOUT_FILENO);
192 bool Process::StandardErrIsDisplayed() {
193 return FileDescriptorIsDisplayed(STDERR_FILENO);
196 bool Process::FileDescriptorIsDisplayed(int fd) {
200 // If we don't have isatty, just return false.
205 static unsigned getColumns(int FileID) {
206 // If COLUMNS is defined in the environment, wrap to that many columns.
207 if (const char *ColumnsStr = std::getenv("COLUMNS")) {
208 int Columns = std::atoi(ColumnsStr);
213 unsigned Columns = 0;
215 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
216 // Try to determine the width of the terminal.
218 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
225 unsigned Process::StandardOutColumns() {
226 if (!StandardOutIsDisplayed())
229 return getColumns(1);
232 unsigned Process::StandardErrColumns() {
233 if (!StandardErrIsDisplayed())
236 return getColumns(2);
240 // We manually declare these extern functions because finding the correct
241 // headers from various terminfo, curses, or other sources is harder than
242 // writing their specs down.
243 extern "C" int setupterm(char *term, int filedes, int *errret);
244 extern "C" struct term *set_curterm(struct term *termp);
245 extern "C" int del_curterm(struct term *termp);
246 extern "C" int tigetnum(char *capname);
249 static bool terminalHasColors(int fd) {
251 // First, acquire a global lock because these C routines are thread hostile.
256 if (setupterm((char *)0, fd, &errret) != 0)
257 // Regardless of why, if we can't get terminfo, we shouldn't try to print
261 // Test whether the terminal as set up supports color output. How to do this
262 // isn't entirely obvious. We can use the curses routine 'has_colors' but it
263 // would be nice to avoid a dependency on curses proper when we can make do
264 // with a minimal terminfo parsing library. Also, we don't really care whether
265 // the terminal supports the curses-specific color changing routines, merely
266 // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
267 // strategy here is just to query the baseline colors capability and if it
268 // supports colors at all to assume it will translate the escape codes into
269 // whatever range of colors it does support. We can add more detailed tests
270 // here if users report them as necessary.
272 // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
273 // the terminfo says that no colors are supported.
274 bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
276 // Now extract the structure allocated by setupterm and free its memory
277 // through a really silly dance.
278 struct term *termp = set_curterm((struct term *)0);
279 (void)del_curterm(termp); // Drop any errors here.
281 // Return true if we found a color capabilities for the current terminal.
286 // Otherwise, be conservative.
290 bool Process::FileDescriptorHasColors(int fd) {
291 // A file descriptor has colors if it is displayed and the terminal has
293 return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
296 bool Process::StandardOutHasColors() {
297 return FileDescriptorHasColors(STDOUT_FILENO);
300 bool Process::StandardErrHasColors() {
301 return FileDescriptorHasColors(STDERR_FILENO);
304 bool Process::ColorNeedsFlush() {
305 // No, we use ANSI escape sequences.
309 #define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
311 #define ALLCOLORS(FGBG,BOLD) {\
312 COLOR(FGBG, "0", BOLD),\
313 COLOR(FGBG, "1", BOLD),\
314 COLOR(FGBG, "2", BOLD),\
315 COLOR(FGBG, "3", BOLD),\
316 COLOR(FGBG, "4", BOLD),\
317 COLOR(FGBG, "5", BOLD),\
318 COLOR(FGBG, "6", BOLD),\
319 COLOR(FGBG, "7", BOLD)\
322 static const char colorcodes[2][2][8][10] = {
323 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
324 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
327 const char *Process::OutputColor(char code, bool bold, bool bg) {
328 return colorcodes[bg?1:0][bold?1:0][code&7];
331 const char *Process::OutputBold(bool bg) {
335 const char *Process::OutputReverse() {
339 const char *Process::ResetColor() {
343 #if !defined(HAVE_ARC4RANDOM)
344 static unsigned GetRandomNumberSeed() {
345 // Attempt to get the initial seed from /dev/urandom, if possible.
346 if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
348 int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
349 ::fclose(RandomSource);
351 // Return the seed if the read was successful.
356 // Otherwise, swizzle the current time and the process ID to form a reasonable
358 TimeValue Now = TimeValue::now();
359 return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
363 unsigned llvm::sys::Process::GetRandomNumber() {
364 #if defined(HAVE_ARC4RANDOM)
367 static int x = (::srand(GetRandomNumberSeed()), 0);