summaryrefslogtreecommitdiff
path: root/lib/System/Unix/Process.inc
blob: addfef358f9b224336caabe7c2850e1470cc6f02 (plain)
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 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 HAVE_MACH_MACH_H
#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 HAVE_MACH_MACH_H
  // 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;
}