1218885Sdim//===- Win32/Process.cpp - Win32 Process Implementation ------- -*- C++ -*-===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file provides the Win32 specific implementation of the Process class. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14218885Sdim#include "Windows.h" 15249423Sdim#include <direct.h> 16249423Sdim#include <io.h> 17249423Sdim#include <malloc.h> 18218885Sdim#include <psapi.h> 19218885Sdim 20218885Sdim#ifdef __MINGW32__ 21218885Sdim #if (HAVE_LIBPSAPI != 1) 22218885Sdim #error "libpsapi.a should be present" 23218885Sdim #endif 24218885Sdim#else 25218885Sdim #pragma comment(lib, "psapi.lib") 26218885Sdim#endif 27218885Sdim 28218885Sdim//===----------------------------------------------------------------------===// 29218885Sdim//=== WARNING: Implementation here must contain only Win32 specific code 30218885Sdim//=== and must not be UNIX code 31218885Sdim//===----------------------------------------------------------------------===// 32218885Sdim 33218885Sdim#ifdef __MINGW32__ 34218885Sdim// This ban should be lifted when MinGW 1.0+ has defined this value. 35218885Sdim# define _HEAPOK (-2) 36218885Sdim#endif 37218885Sdim 38249423Sdimusing namespace llvm; 39218885Sdimusing namespace sys; 40218885Sdim 41249423Sdim 42249423Sdimprocess::id_type self_process::get_id() { 43249423Sdim return GetCurrentProcess(); 44249423Sdim} 45249423Sdim 46249423Sdimstatic TimeValue getTimeValueFromFILETIME(FILETIME Time) { 47249423Sdim ULARGE_INTEGER TimeInteger; 48249423Sdim TimeInteger.LowPart = Time.dwLowDateTime; 49249423Sdim TimeInteger.HighPart = Time.dwHighDateTime; 50249423Sdim 51249423Sdim // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) 52249423Sdim return TimeValue( 53249423Sdim static_cast<TimeValue::SecondsType>(TimeInteger.QuadPart / 10000000), 54249423Sdim static_cast<TimeValue::NanoSecondsType>( 55249423Sdim (TimeInteger.QuadPart % 10000000) * 100)); 56249423Sdim} 57249423Sdim 58249423SdimTimeValue self_process::get_user_time() const { 59249423Sdim FILETIME ProcCreate, ProcExit, KernelTime, UserTime; 60249423Sdim if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, 61249423Sdim &UserTime) == 0) 62249423Sdim return TimeValue(); 63249423Sdim 64249423Sdim return getTimeValueFromFILETIME(UserTime); 65249423Sdim} 66249423Sdim 67249423SdimTimeValue self_process::get_system_time() const { 68249423Sdim FILETIME ProcCreate, ProcExit, KernelTime, UserTime; 69249423Sdim if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, 70249423Sdim &UserTime) == 0) 71249423Sdim return TimeValue(); 72249423Sdim 73249423Sdim return getTimeValueFromFILETIME(KernelTime); 74249423Sdim} 75249423Sdim 76218885Sdim// This function retrieves the page size using GetSystemInfo and is present 77249423Sdim// solely so it can be called once to initialize the self_process member below. 78249423Sdimstatic unsigned getPageSize() { 79218885Sdim // NOTE: A 32-bit application running under WOW64 is supposed to use 80218885Sdim // GetNativeSystemInfo. However, this interface is not present prior 81218885Sdim // to Windows XP so to use it requires dynamic linking. It is not clear 82218885Sdim // how this affects the reported page size, if at all. One could argue 83218885Sdim // that LLVM ought to run as 64-bits on a 64-bit system, anyway. 84218885Sdim SYSTEM_INFO info; 85218885Sdim GetSystemInfo(&info); 86218885Sdim return static_cast<unsigned>(info.dwPageSize); 87218885Sdim} 88218885Sdim 89249423Sdim// This constructor guaranteed to be run exactly once on a single thread, and 90249423Sdim// sets up various process invariants that can be queried cheaply from then on. 91249423Sdimself_process::self_process() : PageSize(getPageSize()) { 92218885Sdim} 93218885Sdim 94249423Sdim 95218885Sdimsize_t 96218885SdimProcess::GetMallocUsage() 97218885Sdim{ 98218885Sdim _HEAPINFO hinfo; 99218885Sdim hinfo._pentry = NULL; 100218885Sdim 101218885Sdim size_t size = 0; 102218885Sdim 103218885Sdim while (_heapwalk(&hinfo) == _HEAPOK) 104218885Sdim size += hinfo._size; 105218885Sdim 106218885Sdim return size; 107218885Sdim} 108218885Sdim 109249423Sdimvoid Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, 110249423Sdim TimeValue &sys_time) { 111218885Sdim elapsed = TimeValue::now(); 112218885Sdim 113249423Sdim FILETIME ProcCreate, ProcExit, KernelTime, UserTime; 114249423Sdim if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, 115249423Sdim &UserTime) == 0) 116249423Sdim return; 117218885Sdim 118249423Sdim user_time = getTimeValueFromFILETIME(UserTime); 119249423Sdim sys_time = getTimeValueFromFILETIME(KernelTime); 120218885Sdim} 121218885Sdim 122218885Sdimint Process::GetCurrentUserId() 123218885Sdim{ 124218885Sdim return 65536; 125218885Sdim} 126218885Sdim 127218885Sdimint Process::GetCurrentGroupId() 128218885Sdim{ 129218885Sdim return 65536; 130218885Sdim} 131218885Sdim 132218885Sdim// Some LLVM programs such as bugpoint produce core files as a normal part of 133218885Sdim// their operation. To prevent the disk from filling up, this configuration item 134218885Sdim// does what's necessary to prevent their generation. 135218885Sdimvoid Process::PreventCoreFiles() { 136218885Sdim // Windows doesn't do core files, but it does do modal pop-up message 137218885Sdim // boxes. As this method is used by bugpoint, preventing these pop-ups 138218885Sdim // is the moral equivalent of suppressing core files. 139218885Sdim SetErrorMode(SEM_FAILCRITICALERRORS | 140218885Sdim SEM_NOGPFAULTERRORBOX | 141218885Sdim SEM_NOOPENFILEERRORBOX); 142218885Sdim} 143218885Sdim 144218885Sdimbool Process::StandardInIsUserInput() { 145218885Sdim return FileDescriptorIsDisplayed(0); 146218885Sdim} 147218885Sdim 148218885Sdimbool Process::StandardOutIsDisplayed() { 149218885Sdim return FileDescriptorIsDisplayed(1); 150218885Sdim} 151218885Sdim 152218885Sdimbool Process::StandardErrIsDisplayed() { 153218885Sdim return FileDescriptorIsDisplayed(2); 154218885Sdim} 155218885Sdim 156218885Sdimbool Process::FileDescriptorIsDisplayed(int fd) { 157239462Sdim DWORD Mode; // Unused 158218885Sdim return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0); 159218885Sdim} 160218885Sdim 161218885Sdimunsigned Process::StandardOutColumns() { 162218885Sdim unsigned Columns = 0; 163218885Sdim CONSOLE_SCREEN_BUFFER_INFO csbi; 164218885Sdim if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) 165218885Sdim Columns = csbi.dwSize.X; 166218885Sdim return Columns; 167218885Sdim} 168218885Sdim 169218885Sdimunsigned Process::StandardErrColumns() { 170218885Sdim unsigned Columns = 0; 171218885Sdim CONSOLE_SCREEN_BUFFER_INFO csbi; 172218885Sdim if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi)) 173218885Sdim Columns = csbi.dwSize.X; 174218885Sdim return Columns; 175218885Sdim} 176218885Sdim 177239462Sdim// The terminal always has colors. 178239462Sdimbool Process::FileDescriptorHasColors(int fd) { 179239462Sdim return FileDescriptorIsDisplayed(fd); 180218885Sdim} 181218885Sdim 182218885Sdimbool Process::StandardOutHasColors() { 183239462Sdim return FileDescriptorHasColors(1); 184218885Sdim} 185218885Sdim 186239462Sdimbool Process::StandardErrHasColors() { 187239462Sdim return FileDescriptorHasColors(2); 188239462Sdim} 189239462Sdim 190218885Sdimnamespace { 191218885Sdimclass DefaultColors 192218885Sdim{ 193218885Sdim private: 194218885Sdim WORD defaultColor; 195218885Sdim public: 196218885Sdim DefaultColors() 197218885Sdim :defaultColor(GetCurrentColor()) {} 198218885Sdim static unsigned GetCurrentColor() { 199218885Sdim CONSOLE_SCREEN_BUFFER_INFO csbi; 200218885Sdim if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) 201218885Sdim return csbi.wAttributes; 202218885Sdim return 0; 203218885Sdim } 204218885Sdim WORD operator()() const { return defaultColor; } 205218885Sdim}; 206218885Sdim 207218885SdimDefaultColors defaultColors; 208218885Sdim} 209218885Sdim 210218885Sdimbool Process::ColorNeedsFlush() { 211218885Sdim return true; 212218885Sdim} 213218885Sdim 214218885Sdimconst char *Process::OutputBold(bool bg) { 215218885Sdim WORD colors = DefaultColors::GetCurrentColor(); 216218885Sdim if (bg) 217218885Sdim colors |= BACKGROUND_INTENSITY; 218218885Sdim else 219218885Sdim colors |= FOREGROUND_INTENSITY; 220218885Sdim SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors); 221218885Sdim return 0; 222218885Sdim} 223218885Sdim 224218885Sdimconst char *Process::OutputColor(char code, bool bold, bool bg) { 225218885Sdim WORD colors; 226218885Sdim if (bg) { 227218885Sdim colors = ((code&1) ? BACKGROUND_RED : 0) | 228218885Sdim ((code&2) ? BACKGROUND_GREEN : 0 ) | 229218885Sdim ((code&4) ? BACKGROUND_BLUE : 0); 230218885Sdim if (bold) 231218885Sdim colors |= BACKGROUND_INTENSITY; 232218885Sdim } else { 233218885Sdim colors = ((code&1) ? FOREGROUND_RED : 0) | 234218885Sdim ((code&2) ? FOREGROUND_GREEN : 0 ) | 235218885Sdim ((code&4) ? FOREGROUND_BLUE : 0); 236218885Sdim if (bold) 237218885Sdim colors |= FOREGROUND_INTENSITY; 238218885Sdim } 239218885Sdim SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors); 240218885Sdim return 0; 241218885Sdim} 242218885Sdim 243234982Sdimstatic WORD GetConsoleTextAttribute(HANDLE hConsoleOutput) { 244234982Sdim CONSOLE_SCREEN_BUFFER_INFO info; 245234982Sdim GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info); 246234982Sdim return info.wAttributes; 247234982Sdim} 248234982Sdim 249234982Sdimconst char *Process::OutputReverse() { 250234982Sdim const WORD attributes 251234982Sdim = GetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE)); 252234982Sdim 253234982Sdim const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN | 254234982Sdim FOREGROUND_RED | FOREGROUND_INTENSITY; 255234982Sdim const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN | 256234982Sdim BACKGROUND_RED | BACKGROUND_INTENSITY; 257234982Sdim const WORD color_mask = foreground_mask | background_mask; 258234982Sdim 259234982Sdim WORD new_attributes = 260234982Sdim ((attributes & FOREGROUND_BLUE )?BACKGROUND_BLUE :0) | 261234982Sdim ((attributes & FOREGROUND_GREEN )?BACKGROUND_GREEN :0) | 262234982Sdim ((attributes & FOREGROUND_RED )?BACKGROUND_RED :0) | 263234982Sdim ((attributes & FOREGROUND_INTENSITY)?BACKGROUND_INTENSITY:0) | 264234982Sdim ((attributes & BACKGROUND_BLUE )?FOREGROUND_BLUE :0) | 265234982Sdim ((attributes & BACKGROUND_GREEN )?FOREGROUND_GREEN :0) | 266234982Sdim ((attributes & BACKGROUND_RED )?FOREGROUND_RED :0) | 267234982Sdim ((attributes & BACKGROUND_INTENSITY)?FOREGROUND_INTENSITY:0) | 268234982Sdim 0; 269234982Sdim new_attributes = (attributes & ~color_mask) | (new_attributes & color_mask); 270234982Sdim 271234982Sdim SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), new_attributes); 272234982Sdim return 0; 273234982Sdim} 274234982Sdim 275218885Sdimconst char *Process::ResetColor() { 276218885Sdim SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors()); 277218885Sdim return 0; 278218885Sdim} 279