1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
//===- Unix/Process.cpp - Unix Process Implementation --------- -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Reid Spencer and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides the generic Unix implementation of the Process class.
//
//===----------------------------------------------------------------------===//
#include "Unix.h"
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef HAVE_MALLOC_MALLOC_H
#include <malloc/malloc.h>
#endif
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only generic UNIX code that
//=== is guaranteed to work on *all* UNIX variants.
//===----------------------------------------------------------------------===//
using namespace llvm;
using namespace sys;
unsigned
Process::GetPageSize()
{
#if defined(HAVE_GETPAGESIZE)
static const int page_size = ::getpagesize();
#elif defined(HAVE_SYSCONF)
static long page_size = ::sysconf(_SC_PAGE_SIZE);
#else
#warning Cannot get the page size on this machine
#endif
return static_cast<unsigned>(page_size);
}
size_t Process::GetMallocUsage() {
#if defined(HAVE_MALLINFO)
struct mallinfo mi;
mi = ::mallinfo();
return mi.uordblks;
#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
malloc_statistics_t Stats;
malloc_zone_statistics(malloc_default_zone(), &Stats);
return Stats.size_in_use; // darwin
#elif defined(HAVE_SBRK)
// Note this is only an approximation and more closely resembles
// the value returned by mallinfo in the arena field.
static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
char *EndOfMemory = (char*)sbrk(0);
if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
return EndOfMemory - StartOfMemory;
else
return 0;
#else
#warning Cannot get malloc info on this platform
return 0;
#endif
}
size_t
Process::GetTotalMemoryUsage()
{
#if defined(HAVE_MALLINFO)
struct mallinfo mi = ::mallinfo();
return mi.uordblks + mi.hblkhd;
#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
malloc_statistics_t Stats;
malloc_zone_statistics(malloc_default_zone(), &Stats);
return Stats.size_allocated; // darwin
#elif defined(HAVE_GETRUSAGE)
struct rusage usage;
::getrusage(RUSAGE_SELF, &usage);
return usage.ru_maxrss;
#else
#warning Cannot get total memory size on this platform
return 0;
#endif
}
void
Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time,
TimeValue& sys_time)
{
elapsed = TimeValue::now();
#if defined(HAVE_GETRUSAGE)
struct rusage usage;
::getrusage(RUSAGE_SELF, &usage);
user_time = TimeValue(
static_cast<TimeValue::SecondsType>( usage.ru_utime.tv_sec ),
static_cast<TimeValue::NanoSecondsType>( usage.ru_utime.tv_usec *
TimeValue::NANOSECONDS_PER_MICROSECOND ) );
sys_time = TimeValue(
static_cast<TimeValue::SecondsType>( usage.ru_stime.tv_sec ),
static_cast<TimeValue::NanoSecondsType>( usage.ru_stime.tv_usec *
TimeValue::NANOSECONDS_PER_MICROSECOND ) );
#else
#warning Cannot get usage times on this platform
user_time.seconds(0);
user_time.microseconds(0);
sys_time.seconds(0);
sys_time.microseconds(0);
#endif
}
int Process::GetCurrentUserId() {
return getuid();
}
int Process::GetCurrentGroupId() {
return getgid();
}
#ifdef __APPLE__ // FIXME: Should be configurified.
#include <mach/mach.h>
#endif
// Some LLVM programs such as bugpoint produce core files as a normal part of
// their operation. To prevent the disk from filling up, this function
// does what's necessary to prevent their generation.
void Process::PreventCoreFiles() {
#if HAVE_SETRLIMIT
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = 0;
setrlimit(RLIMIT_CORE, &rlim);
#endif
#ifdef __APPLE__ // FIXME: Should be configurified.
// Disable crash reporting on Mac OS/X.
// get information about the original set of exception ports for the task
mach_msg_type_number_t Count = 0;
exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
exception_port_t OriginalPorts[EXC_TYPES_COUNT];
exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
kern_return_t err =
task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
&Count, OriginalPorts, OriginalBehaviors,
OriginalFlavors);
if (err == KERN_SUCCESS) {
// replace each with MACH_PORT_NULL.
for (unsigned i = 0; i != Count; ++i)
task_set_exception_ports(mach_task_self(), OriginalMasks[i],
MACH_PORT_NULL, OriginalBehaviors[i],
OriginalFlavors[i]);
}
#endif
}
bool Process::StandardInIsUserInput() {
#if HAVE_ISATTY
return isatty(0);
#endif
// If we don't have isatty, just return false.
return false;
}
bool Process::StandardOutIsDisplayed() {
#if HAVE_ISATTY
return isatty(1);
#endif
// If we don't have isatty, just return false.
return false;
}
bool Process::StandardErrIsDisplayed() {
#if HAVE_ISATTY
return isatty(2);
#endif
// If we don't have isatty, just return false.
return false;
}
|