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 GetCurrentProcessId(); 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(KernelTime); 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