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() {