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/TimeValue.h"
17 #ifdef HAVE_SYS_TIME_H
20 #ifdef HAVE_SYS_RESOURCE_H
21 #include <sys/resource.h>
23 // DragonFlyBSD, OpenBSD, and Bitrig have deprecated <malloc.h> for
24 // <stdlib.h> instead. Unix.h includes this for us already.
25 #if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \
26 !defined(__OpenBSD__) && !defined(__Bitrig__)
29 #ifdef HAVE_MALLOC_MALLOC_H
30 #include <malloc/malloc.h>
32 #ifdef HAVE_SYS_IOCTL_H
33 # include <sys/ioctl.h>
39 //===----------------------------------------------------------------------===//
40 //=== WARNING: Implementation here must contain only generic UNIX code that
41 //=== is guaranteed to work on *all* UNIX variants.
42 //===----------------------------------------------------------------------===//
48 process::id_type self_process::get_id() {
54 Process::GetPageSize()
56 #if defined(__CYGWIN__)
57 // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
58 // memory protection and mmap() is 4k.
59 // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
60 const int page_size = 0x1000;
61 #elif defined(HAVE_GETPAGESIZE)
62 const int page_size = ::getpagesize();
63 #elif defined(HAVE_SYSCONF)
64 long page_size = ::sysconf(_SC_PAGE_SIZE);
66 #warning Cannot get the page size on this machine
68 return static_cast<unsigned>(page_size);
71 size_t Process::GetMallocUsage() {
72 #if defined(HAVE_MALLINFO)
76 #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
77 malloc_statistics_t Stats;
78 malloc_zone_statistics(malloc_default_zone(), &Stats);
79 return Stats.size_in_use; // darwin
80 #elif defined(HAVE_SBRK)
81 // Note this is only an approximation and more closely resembles
82 // the value returned by mallinfo in the arena field.
83 static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
84 char *EndOfMemory = (char*)sbrk(0);
85 if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
86 return EndOfMemory - StartOfMemory;
90 #warning Cannot get malloc info on this platform
96 Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time,
99 elapsed = TimeValue::now();
100 #if defined(HAVE_GETRUSAGE)
102 ::getrusage(RUSAGE_SELF, &usage);
103 user_time = TimeValue(
104 static_cast<TimeValue::SecondsType>( usage.ru_utime.tv_sec ),
105 static_cast<TimeValue::NanoSecondsType>( usage.ru_utime.tv_usec *
106 TimeValue::NANOSECONDS_PER_MICROSECOND ) );
107 sys_time = TimeValue(
108 static_cast<TimeValue::SecondsType>( usage.ru_stime.tv_sec ),
109 static_cast<TimeValue::NanoSecondsType>( usage.ru_stime.tv_usec *
110 TimeValue::NANOSECONDS_PER_MICROSECOND ) );
112 #warning Cannot get usage times on this platform
113 user_time.seconds(0);
114 user_time.microseconds(0);
116 sys_time.microseconds(0);
120 int Process::GetCurrentUserId() {
124 int Process::GetCurrentGroupId() {
128 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
129 #include <mach/mach.h>
132 // Some LLVM programs such as bugpoint produce core files as a normal part of
133 // their operation. To prevent the disk from filling up, this function
134 // does what's necessary to prevent their generation.
135 void Process::PreventCoreFiles() {
138 rlim.rlim_cur = rlim.rlim_max = 0;
139 setrlimit(RLIMIT_CORE, &rlim);
142 #if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
143 // Disable crash reporting on Mac OS X 10.0-10.4
145 // get information about the original set of exception ports for the task
146 mach_msg_type_number_t Count = 0;
147 exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
148 exception_port_t OriginalPorts[EXC_TYPES_COUNT];
149 exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
150 thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
152 task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
153 &Count, OriginalPorts, OriginalBehaviors,
155 if (err == KERN_SUCCESS) {
156 // replace each with MACH_PORT_NULL.
157 for (unsigned i = 0; i != Count; ++i)
158 task_set_exception_ports(mach_task_self(), OriginalMasks[i],
159 MACH_PORT_NULL, OriginalBehaviors[i],
163 // Disable crash reporting on Mac OS X 10.5
164 signal(SIGABRT, _exit);
165 signal(SIGILL, _exit);
166 signal(SIGFPE, _exit);
167 signal(SIGSEGV, _exit);
168 signal(SIGBUS, _exit);
172 bool Process::StandardInIsUserInput() {
173 return FileDescriptorIsDisplayed(STDIN_FILENO);
176 bool Process::StandardOutIsDisplayed() {
177 return FileDescriptorIsDisplayed(STDOUT_FILENO);
180 bool Process::StandardErrIsDisplayed() {
181 return FileDescriptorIsDisplayed(STDERR_FILENO);
184 bool Process::FileDescriptorIsDisplayed(int fd) {
188 // If we don't have isatty, just return false.
193 static unsigned getColumns(int FileID) {
194 // If COLUMNS is defined in the environment, wrap to that many columns.
195 if (const char *ColumnsStr = std::getenv("COLUMNS")) {
196 int Columns = std::atoi(ColumnsStr);
201 unsigned Columns = 0;
203 #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
204 // Try to determine the width of the terminal.
206 if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
213 unsigned Process::StandardOutColumns() {
214 if (!StandardOutIsDisplayed())
217 return getColumns(1);
220 unsigned Process::StandardErrColumns() {
221 if (!StandardErrIsDisplayed())
224 return getColumns(2);
227 static bool terminalHasColors() {
228 if (const char *term = std::getenv("TERM")) {
229 // Most modern terminals support ANSI escape sequences for colors.
230 // We could check terminfo, or have a list of known terms that support
231 // colors, but that would be overkill.
232 // The user can always ask for no colors by setting TERM to dumb, or
233 // using a commandline flag.
234 return strcmp(term, "dumb") != 0;
239 bool Process::FileDescriptorHasColors(int fd) {
240 // A file descriptor has colors if it is displayed and the terminal has
242 return FileDescriptorIsDisplayed(fd) && terminalHasColors();
245 bool Process::StandardOutHasColors() {
246 return FileDescriptorHasColors(STDOUT_FILENO);
249 bool Process::StandardErrHasColors() {
250 return FileDescriptorHasColors(STDERR_FILENO);
253 bool Process::ColorNeedsFlush() {
254 // No, we use ANSI escape sequences.
258 #define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
260 #define ALLCOLORS(FGBG,BOLD) {\
261 COLOR(FGBG, "0", BOLD),\
262 COLOR(FGBG, "1", BOLD),\
263 COLOR(FGBG, "2", BOLD),\
264 COLOR(FGBG, "3", BOLD),\
265 COLOR(FGBG, "4", BOLD),\
266 COLOR(FGBG, "5", BOLD),\
267 COLOR(FGBG, "6", BOLD),\
268 COLOR(FGBG, "7", BOLD)\
271 static const char colorcodes[2][2][8][10] = {
272 { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
273 { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
276 const char *Process::OutputColor(char code, bool bold, bool bg) {
277 return colorcodes[bg?1:0][bold?1:0][code&7];
280 const char *Process::OutputBold(bool bg) {
284 const char *Process::OutputReverse() {
288 const char *Process::ResetColor() {
292 #if !defined(HAVE_ARC4RANDOM)
293 static unsigned GetRandomNumberSeed() {
294 // Attempt to get the initial seed from /dev/urandom, if possible.
295 if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
297 int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
298 ::fclose(RandomSource);
300 // Return the seed if the read was successful.
305 // Otherwise, swizzle the current time and the process ID to form a reasonable
307 TimeValue Now = TimeValue::now();
308 return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
312 unsigned llvm::sys::Process::GetRandomNumber() {
313 #if defined(HAVE_ARC4RANDOM)
316 static int x = (::srand(GetRandomNumberSeed()), 0);