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
/* ClamAV: we don't link with -lmalloc */
64
size_t Process::GetMallocUsage() {
65
#if defined(HAVE_MALLINFO)
69
#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
70
malloc_statistics_t Stats;
71
malloc_zone_statistics(malloc_default_zone(), &Stats);
72
return Stats.size_in_use; // darwin
73
#elif defined(HAVE_SBRK)
74
// Note this is only an approximation and more closely resembles
75
// the value returned by mallinfo in the arena field.
76
static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
77
char *EndOfMemory = (char*)sbrk(0);
78
if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
79
return EndOfMemory - StartOfMemory;
83
#warning Cannot get malloc info on this platform
89
Process::GetTotalMemoryUsage()
91
#if defined(HAVE_MALLINFO)
92
struct mallinfo mi = ::mallinfo();
93
return mi.uordblks + mi.hblkhd;
94
#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
95
malloc_statistics_t Stats;
96
malloc_zone_statistics(malloc_default_zone(), &Stats);
97
return Stats.size_allocated; // darwin
98
#elif defined(HAVE_GETRUSAGE) && !defined(__HAIKU__)
100
::getrusage(RUSAGE_SELF, &usage);
101
return usage.ru_maxrss;
103
#warning Cannot get total memory size on this platform
109
Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time,
112
elapsed = TimeValue::now();
113
#if defined(HAVE_GETRUSAGE)
115
::getrusage(RUSAGE_SELF, &usage);
116
user_time = TimeValue(
117
static_cast<TimeValue::SecondsType>( usage.ru_utime.tv_sec ),
118
static_cast<TimeValue::NanoSecondsType>( usage.ru_utime.tv_usec *
119
TimeValue::NANOSECONDS_PER_MICROSECOND ) );
120
sys_time = TimeValue(
121
static_cast<TimeValue::SecondsType>( usage.ru_stime.tv_sec ),
122
static_cast<TimeValue::NanoSecondsType>( usage.ru_stime.tv_usec *
123
TimeValue::NANOSECONDS_PER_MICROSECOND ) );
125
#warning Cannot get usage times on this platform
126
user_time.seconds(0);
127
user_time.microseconds(0);
129
sys_time.microseconds(0);
133
int Process::GetCurrentUserId() {
137
int Process::GetCurrentGroupId() {
141
#ifdef HAVE_MACH_MACH_H
142
#include <mach/mach.h>
145
// Some LLVM programs such as bugpoint produce core files as a normal part of
146
// their operation. To prevent the disk from filling up, this function
147
// does what's necessary to prevent their generation.
148
void Process::PreventCoreFiles() {
151
rlim.rlim_cur = rlim.rlim_max = 0;
152
setrlimit(RLIMIT_CORE, &rlim);
155
#ifdef HAVE_MACH_MACH_H
156
// Disable crash reporting on Mac OS X 10.0-10.4
158
// get information about the original set of exception ports for the task
159
mach_msg_type_number_t Count = 0;
160
exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
161
exception_port_t OriginalPorts[EXC_TYPES_COUNT];
162
exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
163
thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
165
task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
166
&Count, OriginalPorts, OriginalBehaviors,
168
if (err == KERN_SUCCESS) {
169
// replace each with MACH_PORT_NULL.
170
for (unsigned i = 0; i != Count; ++i)
171
task_set_exception_ports(mach_task_self(), OriginalMasks[i],
172
MACH_PORT_NULL, OriginalBehaviors[i],
176
// Disable crash reporting on Mac OS X 10.5
177
signal(SIGABRT, _exit);
178
signal(SIGILL, _exit);
179
signal(SIGFPE, _exit);
180
signal(SIGSEGV, _exit);
181
signal(SIGBUS, _exit);
185
bool Process::StandardInIsUserInput() {
186
return FileDescriptorIsDisplayed(STDIN_FILENO);
189
bool Process::StandardOutIsDisplayed() {
190
return FileDescriptorIsDisplayed(STDOUT_FILENO);
193
bool Process::StandardErrIsDisplayed() {
194
return FileDescriptorIsDisplayed(STDERR_FILENO);
197
bool Process::FileDescriptorIsDisplayed(int fd) {
201
// If we don't have isatty, just return false.
206
static unsigned getColumns(int FileID) {
207
// If COLUMNS is defined in the environment, wrap to that many columns.
208
if (const char *ColumnsStr = std::getenv("COLUMNS")) {
209
int Columns = std::atoi(ColumnsStr);
214
unsigned Columns = 0;
216
#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
217
// Try to determine the width of the terminal.
219
if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
226
unsigned Process::StandardOutColumns() {
227
if (!StandardOutIsDisplayed())
230
return getColumns(1);
233
unsigned Process::StandardErrColumns() {
234
if (!StandardErrIsDisplayed())
237
return getColumns(2);
240
static bool terminalHasColors() {
241
if (const char *term = std::getenv("TERM")) {
242
// Most modern terminals support ANSI escape sequences for colors.
243
// We could check terminfo, or have a list of known terms that support
244
// colors, but that would be overkill.
245
// The user can always ask for no colors by setting TERM to dumb, or
246
// using a commandline flag.
247
return strcmp(term, "dumb") != 0;
252
bool Process::StandardOutHasColors() {
253
if (!StandardOutIsDisplayed())
255
return terminalHasColors();
258
bool Process::StandardErrHasColors() {
259
if (!StandardErrIsDisplayed())
261
return terminalHasColors();
264
bool Process::ColorNeedsFlush() {
265
// No, we use ANSI escape sequences.
269
#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
271
#define ALLCOLORS(FGBG,BOLD) {\
272
COLOR(FGBG, "0", BOLD),\
273
COLOR(FGBG, "1", BOLD),\
274
COLOR(FGBG, "2", BOLD),\
275
COLOR(FGBG, "3", BOLD),\
276
COLOR(FGBG, "4", BOLD),\
277
COLOR(FGBG, "5", BOLD),\
278
COLOR(FGBG, "6", BOLD),\
279
COLOR(FGBG, "7", BOLD)\
282
static const char colorcodes[2][2][8][10] = {
283
{ ALLCOLORS("3",""), ALLCOLORS("3","1;") },
284
{ ALLCOLORS("4",""), ALLCOLORS("4","1;") }
287
const char *Process::OutputColor(char code, bool bold, bool bg) {
288
return colorcodes[bg?1:0][bold?1:0][code&7];
291
const char *Process::OutputBold(bool bg) {
295
const char *Process::ResetColor() {