Process.inc revision 73c35d86b9d5236be5b3f49bc8df11008b96636e
1//===- Win32/Process.cpp - Win32 Process Implementation ------- -*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file provides the Win32 specific implementation of the Process class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Windows.h"
15#include <direct.h>
16#include <io.h>
17#include <malloc.h>
18#include <psapi.h>
19
20#ifdef __MINGW32__
21 #if (HAVE_LIBPSAPI != 1)
22  #error "libpsapi.a should be present"
23 #endif
24#else
25 #pragma comment(lib, "psapi.lib")
26#endif
27
28//===----------------------------------------------------------------------===//
29//=== WARNING: Implementation here must contain only Win32 specific code
30//===          and must not be UNIX code
31//===----------------------------------------------------------------------===//
32
33#ifdef __MINGW32__
34// This ban should be lifted when MinGW 1.0+ has defined this value.
35#  define _HEAPOK (-2)
36#endif
37
38using namespace llvm;
39using namespace sys;
40
41
42process::id_type self_process::get_id() {
43  return GetCurrentProcess();
44}
45
46static TimeValue getTimeValueFromFILETIME(FILETIME Time) {
47  ULARGE_INTEGER TimeInteger;
48  TimeInteger.LowPart = Time.dwLowDateTime;
49  TimeInteger.HighPart = Time.dwHighDateTime;
50
51  // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
52  return TimeValue(
53      static_cast<TimeValue::SecondsType>(TimeInteger.QuadPart / 10000000),
54      static_cast<TimeValue::NanoSecondsType>(
55          (TimeInteger.QuadPart % 10000000) * 100));
56}
57
58TimeValue self_process::get_user_time() const {
59  FILETIME ProcCreate, ProcExit, KernelTime, UserTime;
60  if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime,
61                      &UserTime) == 0)
62    return TimeValue();
63
64  return getTimeValueFromFILETIME(UserTime);
65}
66
67TimeValue self_process::get_system_time() const {
68  FILETIME ProcCreate, ProcExit, KernelTime, UserTime;
69  if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime,
70                      &UserTime) == 0)
71    return TimeValue();
72
73  return getTimeValueFromFILETIME(KernelTime);
74}
75
76// This function retrieves the page size using GetSystemInfo and is present
77// solely so it can be called once to initialize the self_process member below.
78static unsigned getPageSize() {
79  // NOTE: A 32-bit application running under WOW64 is supposed to use
80  // GetNativeSystemInfo.  However, this interface is not present prior
81  // to Windows XP so to use it requires dynamic linking.  It is not clear
82  // how this affects the reported page size, if at all.  One could argue
83  // that LLVM ought to run as 64-bits on a 64-bit system, anyway.
84  SYSTEM_INFO info;
85  GetSystemInfo(&info);
86  return static_cast<unsigned>(info.dwPageSize);
87}
88
89// This constructor guaranteed to be run exactly once on a single thread, and
90// sets up various process invariants that can be queried cheaply from then on.
91self_process::self_process() : PageSize(getPageSize()) {
92}
93
94
95size_t
96Process::GetMallocUsage()
97{
98  _HEAPINFO hinfo;
99  hinfo._pentry = NULL;
100
101  size_t size = 0;
102
103  while (_heapwalk(&hinfo) == _HEAPOK)
104    size += hinfo._size;
105
106  return size;
107}
108
109void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
110                           TimeValue &sys_time) {
111  elapsed = TimeValue::now();
112
113  FILETIME ProcCreate, ProcExit, KernelTime, UserTime;
114  if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime,
115                      &UserTime) == 0)
116    return;
117
118  user_time = getTimeValueFromFILETIME(UserTime);
119  sys_time = getTimeValueFromFILETIME(SystemTime);
120}
121
122int Process::GetCurrentUserId()
123{
124  return 65536;
125}
126
127int Process::GetCurrentGroupId()
128{
129  return 65536;
130}
131
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 configuration item
134// does what's necessary to prevent their generation.
135void Process::PreventCoreFiles() {
136  // Windows doesn't do core files, but it does do modal pop-up message
137  // boxes.  As this method is used by bugpoint, preventing these pop-ups
138  // is the moral equivalent of suppressing core files.
139  SetErrorMode(SEM_FAILCRITICALERRORS |
140               SEM_NOGPFAULTERRORBOX |
141               SEM_NOOPENFILEERRORBOX);
142}
143
144bool Process::StandardInIsUserInput() {
145  return FileDescriptorIsDisplayed(0);
146}
147
148bool Process::StandardOutIsDisplayed() {
149  return FileDescriptorIsDisplayed(1);
150}
151
152bool Process::StandardErrIsDisplayed() {
153  return FileDescriptorIsDisplayed(2);
154}
155
156bool Process::FileDescriptorIsDisplayed(int fd) {
157  DWORD Mode;  // Unused
158  return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0);
159}
160
161unsigned Process::StandardOutColumns() {
162  unsigned Columns = 0;
163  CONSOLE_SCREEN_BUFFER_INFO csbi;
164  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
165    Columns = csbi.dwSize.X;
166  return Columns;
167}
168
169unsigned Process::StandardErrColumns() {
170  unsigned Columns = 0;
171  CONSOLE_SCREEN_BUFFER_INFO csbi;
172  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi))
173    Columns = csbi.dwSize.X;
174  return Columns;
175}
176
177// The terminal always has colors.
178bool Process::FileDescriptorHasColors(int fd) {
179  return FileDescriptorIsDisplayed(fd);
180}
181
182bool Process::StandardOutHasColors() {
183  return FileDescriptorHasColors(1);
184}
185
186bool Process::StandardErrHasColors() {
187  return FileDescriptorHasColors(2);
188}
189
190namespace {
191class DefaultColors
192{
193  private:
194    WORD defaultColor;
195  public:
196    DefaultColors()
197     :defaultColor(GetCurrentColor()) {}
198    static unsigned GetCurrentColor() {
199      CONSOLE_SCREEN_BUFFER_INFO csbi;
200      if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
201        return csbi.wAttributes;
202      return 0;
203    }
204    WORD operator()() const { return defaultColor; }
205};
206
207DefaultColors defaultColors;
208}
209
210bool Process::ColorNeedsFlush() {
211  return true;
212}
213
214const char *Process::OutputBold(bool bg) {
215  WORD colors = DefaultColors::GetCurrentColor();
216  if (bg)
217    colors |= BACKGROUND_INTENSITY;
218  else
219    colors |= FOREGROUND_INTENSITY;
220  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
221  return 0;
222}
223
224const char *Process::OutputColor(char code, bool bold, bool bg) {
225  WORD colors;
226  if (bg) {
227    colors = ((code&1) ? BACKGROUND_RED : 0) |
228      ((code&2) ? BACKGROUND_GREEN : 0 ) |
229      ((code&4) ? BACKGROUND_BLUE : 0);
230    if (bold)
231      colors |= BACKGROUND_INTENSITY;
232  } else {
233    colors = ((code&1) ? FOREGROUND_RED : 0) |
234      ((code&2) ? FOREGROUND_GREEN : 0 ) |
235      ((code&4) ? FOREGROUND_BLUE : 0);
236    if (bold)
237      colors |= FOREGROUND_INTENSITY;
238  }
239  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
240  return 0;
241}
242
243static WORD GetConsoleTextAttribute(HANDLE hConsoleOutput) {
244  CONSOLE_SCREEN_BUFFER_INFO info;
245  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
246  return info.wAttributes;
247}
248
249const char *Process::OutputReverse() {
250  const WORD attributes
251   = GetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE));
252
253  const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN |
254    FOREGROUND_RED | FOREGROUND_INTENSITY;
255  const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN |
256    BACKGROUND_RED | BACKGROUND_INTENSITY;
257  const WORD color_mask = foreground_mask | background_mask;
258
259  WORD new_attributes =
260    ((attributes & FOREGROUND_BLUE     )?BACKGROUND_BLUE     :0) |
261    ((attributes & FOREGROUND_GREEN    )?BACKGROUND_GREEN    :0) |
262    ((attributes & FOREGROUND_RED      )?BACKGROUND_RED      :0) |
263    ((attributes & FOREGROUND_INTENSITY)?BACKGROUND_INTENSITY:0) |
264    ((attributes & BACKGROUND_BLUE     )?FOREGROUND_BLUE     :0) |
265    ((attributes & BACKGROUND_GREEN    )?FOREGROUND_GREEN    :0) |
266    ((attributes & BACKGROUND_RED      )?FOREGROUND_RED      :0) |
267    ((attributes & BACKGROUND_INTENSITY)?FOREGROUND_INTENSITY:0) |
268    0;
269  new_attributes = (attributes & ~color_mask) | (new_attributes & color_mask);
270
271  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), new_attributes);
272  return 0;
273}
274
275const char *Process::ResetColor() {
276  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors());
277  return 0;
278}
279