Home | History | Annotate | Download | only in Windows
      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 <psapi.h>
     16 #include <malloc.h>
     17 #include <io.h>
     18 #include <direct.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 namespace llvm {
     39 using namespace sys;
     40 
     41 // This function retrieves the page size using GetSystemInfo and is present
     42 // solely so it can be called once in Process::GetPageSize to initialize the
     43 // static variable PageSize.
     44 inline unsigned GetPageSizeOnce() {
     45   // NOTE: A 32-bit application running under WOW64 is supposed to use
     46   // GetNativeSystemInfo.  However, this interface is not present prior
     47   // to Windows XP so to use it requires dynamic linking.  It is not clear
     48   // how this affects the reported page size, if at all.  One could argue
     49   // that LLVM ought to run as 64-bits on a 64-bit system, anyway.
     50   SYSTEM_INFO info;
     51   GetSystemInfo(&info);
     52   return static_cast<unsigned>(info.dwPageSize);
     53 }
     54 
     55 unsigned
     56 Process::GetPageSize() {
     57   static const unsigned PageSize = GetPageSizeOnce();
     58   return PageSize;
     59 }
     60 
     61 size_t
     62 Process::GetMallocUsage()
     63 {
     64   _HEAPINFO hinfo;
     65   hinfo._pentry = NULL;
     66 
     67   size_t size = 0;
     68 
     69   while (_heapwalk(&hinfo) == _HEAPOK)
     70     size += hinfo._size;
     71 
     72   return size;
     73 }
     74 
     75 size_t
     76 Process::GetTotalMemoryUsage()
     77 {
     78   PROCESS_MEMORY_COUNTERS pmc;
     79   GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
     80   return pmc.PagefileUsage;
     81 }
     82 
     83 void
     84 Process::GetTimeUsage(
     85   TimeValue& elapsed, TimeValue& user_time, TimeValue& sys_time)
     86 {
     87   elapsed = TimeValue::now();
     88 
     89   uint64_t ProcCreate, ProcExit, KernelTime, UserTime;
     90   GetProcessTimes(GetCurrentProcess(), (FILETIME*)&ProcCreate,
     91                   (FILETIME*)&ProcExit, (FILETIME*)&KernelTime,
     92                   (FILETIME*)&UserTime);
     93 
     94   // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
     95   user_time.seconds( UserTime / 10000000 );
     96   user_time.nanoseconds( unsigned(UserTime % 10000000) * 100 );
     97   sys_time.seconds( KernelTime / 10000000 );
     98   sys_time.nanoseconds( unsigned(KernelTime % 10000000) * 100 );
     99 }
    100 
    101 int Process::GetCurrentUserId()
    102 {
    103   return 65536;
    104 }
    105 
    106 int Process::GetCurrentGroupId()
    107 {
    108   return 65536;
    109 }
    110 
    111 // Some LLVM programs such as bugpoint produce core files as a normal part of
    112 // their operation. To prevent the disk from filling up, this configuration item
    113 // does what's necessary to prevent their generation.
    114 void Process::PreventCoreFiles() {
    115   // Windows doesn't do core files, but it does do modal pop-up message
    116   // boxes.  As this method is used by bugpoint, preventing these pop-ups
    117   // is the moral equivalent of suppressing core files.
    118   SetErrorMode(SEM_FAILCRITICALERRORS |
    119                SEM_NOGPFAULTERRORBOX |
    120                SEM_NOOPENFILEERRORBOX);
    121 }
    122 
    123 bool Process::StandardInIsUserInput() {
    124   return FileDescriptorIsDisplayed(0);
    125 }
    126 
    127 bool Process::StandardOutIsDisplayed() {
    128   return FileDescriptorIsDisplayed(1);
    129 }
    130 
    131 bool Process::StandardErrIsDisplayed() {
    132   return FileDescriptorIsDisplayed(2);
    133 }
    134 
    135 bool Process::FileDescriptorIsDisplayed(int fd) {
    136   DWORD Mode;	// Unused
    137   return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0);
    138 }
    139 
    140 unsigned Process::StandardOutColumns() {
    141   unsigned Columns = 0;
    142   CONSOLE_SCREEN_BUFFER_INFO csbi;
    143   if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
    144     Columns = csbi.dwSize.X;
    145   return Columns;
    146 }
    147 
    148 unsigned Process::StandardErrColumns() {
    149   unsigned Columns = 0;
    150   CONSOLE_SCREEN_BUFFER_INFO csbi;
    151   if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi))
    152     Columns = csbi.dwSize.X;
    153   return Columns;
    154 }
    155 
    156 // It always has colors.
    157 bool Process::StandardErrHasColors() {
    158   return StandardErrIsDisplayed();
    159 }
    160 
    161 bool Process::StandardOutHasColors() {
    162   return StandardOutIsDisplayed();
    163 }
    164 
    165 namespace {
    166 class DefaultColors
    167 {
    168   private:
    169     WORD defaultColor;
    170   public:
    171     DefaultColors()
    172      :defaultColor(GetCurrentColor()) {}
    173     static unsigned GetCurrentColor() {
    174       CONSOLE_SCREEN_BUFFER_INFO csbi;
    175       if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
    176         return csbi.wAttributes;
    177       return 0;
    178     }
    179     WORD operator()() const { return defaultColor; }
    180 };
    181 
    182 DefaultColors defaultColors;
    183 }
    184 
    185 bool Process::ColorNeedsFlush() {
    186   return true;
    187 }
    188 
    189 const char *Process::OutputBold(bool bg) {
    190   WORD colors = DefaultColors::GetCurrentColor();
    191   if (bg)
    192     colors |= BACKGROUND_INTENSITY;
    193   else
    194     colors |= FOREGROUND_INTENSITY;
    195   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
    196   return 0;
    197 }
    198 
    199 const char *Process::OutputColor(char code, bool bold, bool bg) {
    200   WORD colors;
    201   if (bg) {
    202     colors = ((code&1) ? BACKGROUND_RED : 0) |
    203       ((code&2) ? BACKGROUND_GREEN : 0 ) |
    204       ((code&4) ? BACKGROUND_BLUE : 0);
    205     if (bold)
    206       colors |= BACKGROUND_INTENSITY;
    207   } else {
    208     colors = ((code&1) ? FOREGROUND_RED : 0) |
    209       ((code&2) ? FOREGROUND_GREEN : 0 ) |
    210       ((code&4) ? FOREGROUND_BLUE : 0);
    211     if (bold)
    212       colors |= FOREGROUND_INTENSITY;
    213   }
    214   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
    215   return 0;
    216 }
    217 
    218 const char *Process::ResetColor() {
    219   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors());
    220   return 0;
    221 }
    222 
    223 void Process::SetWorkingDirectory(std::string Path) {
    224   ::_chdir(Path.c_str());
    225 }
    226 
    227 }
    228