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 38 using namespace llvm; 39 using namespace sys; 40 41 42 process::id_type self_process::get_id() { 43 return GetCurrentProcessId(); 44 } 45 46 static 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 58 TimeValue 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 67 TimeValue 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. 78 static 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. 91 self_process::self_process() : PageSize(getPageSize()) { 92 } 93 94 95 size_t 96 Process::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 109 void 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 122 int Process::GetCurrentUserId() 123 { 124 return 65536; 125 } 126 127 int 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. 135 void 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 144 bool Process::StandardInIsUserInput() { 145 return FileDescriptorIsDisplayed(0); 146 } 147 148 bool Process::StandardOutIsDisplayed() { 149 return FileDescriptorIsDisplayed(1); 150 } 151 152 bool Process::StandardErrIsDisplayed() { 153 return FileDescriptorIsDisplayed(2); 154 } 155 156 bool Process::FileDescriptorIsDisplayed(int fd) { 157 DWORD Mode; // Unused 158 return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0); 159 } 160 161 unsigned 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 169 unsigned 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. 178 bool Process::FileDescriptorHasColors(int fd) { 179 return FileDescriptorIsDisplayed(fd); 180 } 181 182 bool Process::StandardOutHasColors() { 183 return FileDescriptorHasColors(1); 184 } 185 186 bool Process::StandardErrHasColors() { 187 return FileDescriptorHasColors(2); 188 } 189 190 namespace { 191 class 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 207 DefaultColors defaultColors; 208 } 209 210 bool Process::ColorNeedsFlush() { 211 return true; 212 } 213 214 const 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 224 const 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 243 static WORD GetConsoleTextAttribute(HANDLE hConsoleOutput) { 244 CONSOLE_SCREEN_BUFFER_INFO info; 245 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info); 246 return info.wAttributes; 247 } 248 249 const 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 275 const char *Process::ResetColor() { 276 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors()); 277 return 0; 278 } 279