1cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//===-- Process.cpp - Implement OS Process Concept --------------*- C++ -*-===//
2f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha Brukman//
3cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//                     The LLVM Compiler Infrastructure
4cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
7f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha Brukman//
8cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//===----------------------------------------------------------------------===//
9cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//
10cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//  This file implements the operating system Process concept.
11cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//
12cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//===----------------------------------------------------------------------===//
13cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer
14cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/ADT/StringExtras.h"
150098e64da7d0b2c47128bac96aa839b2525bfbcaReid Spencer#include "llvm/Config/config.h"
160184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth#include "llvm/Support/ErrorHandling.h"
17cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/Support/FileSystem.h"
1858a2cbef4aac9ee7d530dfb690c78d6fc11a2371Chandler Carruth#include "llvm/Support/Process.h"
19cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/Support/Program.h"
20cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer
219b4aba85a89f9347212e00f80953f2a685ffeb36Chandler Carruthusing namespace llvm;
22cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencerusing namespace sys;
23cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer
24cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//===----------------------------------------------------------------------===//
25cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//=== WARNING: Implementation here must contain only TRULY operating system
26f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha Brukman//===          independent code.
27cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//===----------------------------------------------------------------------===//
28cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer
290184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth// Empty virtual destructor to anchor the vtable for the process class.
300184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruthprocess::~process() {}
310184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth
320184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruthself_process *process::get_self() {
330184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth  // Use a function local static for thread safe initialization and allocate it
340184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth  // as a raw pointer to ensure it is never destroyed.
350184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth  static self_process *SP = new self_process();
360184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth
370184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth  return SP;
380184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth}
390184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth
400184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth// The destructor for the self_process subclass must never actually be
410184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth// executed. There should be at most one instance of this class, and that
420184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth// instance should live until the process terminates to avoid the potential for
430184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth// racy accesses during shutdown.
440184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruthself_process::~self_process() {
450184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth  llvm_unreachable("This destructor must never be executed!");
460184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth}
470184a841d3914bb78c7c6fa87ce9da86a2d5992aChandler Carruth
4873c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth/// \brief A helper function to compute the elapsed wall-time since the program
4973c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth/// started.
5073c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth///
5173c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth/// Note that this routine actually computes the elapsed wall time since the
5273c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth/// first time it was called. However, we arrange to have it called during the
5373c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth/// startup of the process to get approximately correct results.
5473c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruthstatic TimeValue getElapsedWallTime() {
5573c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth  static TimeValue &StartTime = *new TimeValue(TimeValue::now());
5673c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth  return TimeValue::now() - StartTime;
5773c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth}
5873c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth
5973c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth/// \brief A special global variable to ensure we call \c getElapsedWallTime
6073c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth/// during global initialization of the program.
6173c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth///
6273c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth/// Note that this variable is never referenced elsewhere. Doing so could
6373c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth/// create race conditions during program startup or shutdown.
6473c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruthstatic volatile TimeValue DummyTimeValue = getElapsedWallTime();
6573c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth
6673c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth// Implement this routine by using the static helpers above. They're already
6773c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth// portable.
6873c35d86b9d5236be5b3f49bc8df11008b96636eChandler CarruthTimeValue self_process::get_wall_time() const {
6973c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth  return getElapsedWallTime();
7073c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth}
7173c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth
72cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesOptional<std::string> Process::FindInEnvPath(const std::string& EnvName,
73cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                             const std::string& FileName)
74cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines{
75cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  Optional<std::string> FoundPath;
76cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  Optional<std::string> OptPath = Process::GetEnv(EnvName);
77cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (!OptPath.hasValue())
78cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return FoundPath;
79cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
80cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  const char EnvPathSeparatorStr[] = {EnvPathSeparator, '\0'};
81cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SmallVector<StringRef, 8> Dirs;
82cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SplitString(OptPath.getValue(), Dirs, EnvPathSeparatorStr);
83cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
84cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (const auto &Dir : Dirs) {
85cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (Dir.empty())
86cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      continue;
87cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
88cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    SmallString<128> FilePath(Dir);
89cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    path::append(FilePath, FileName);
90cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (fs::exists(Twine(FilePath))) {
91cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      FoundPath = FilePath.str();
92cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      break;
93cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
94cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
95cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
96cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return FoundPath;
97cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
98cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
9973c35d86b9d5236be5b3f49bc8df11008b96636eChandler Carruth
10044a61bde15d456527156ee2080f0964344b939feNico Rieck#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
10144a61bde15d456527156ee2080f0964344b939feNico Rieck
10244a61bde15d456527156ee2080f0964344b939feNico Rieck#define ALLCOLORS(FGBG,BOLD) {\
10344a61bde15d456527156ee2080f0964344b939feNico Rieck    COLOR(FGBG, "0", BOLD),\
10444a61bde15d456527156ee2080f0964344b939feNico Rieck    COLOR(FGBG, "1", BOLD),\
10544a61bde15d456527156ee2080f0964344b939feNico Rieck    COLOR(FGBG, "2", BOLD),\
10644a61bde15d456527156ee2080f0964344b939feNico Rieck    COLOR(FGBG, "3", BOLD),\
10744a61bde15d456527156ee2080f0964344b939feNico Rieck    COLOR(FGBG, "4", BOLD),\
10844a61bde15d456527156ee2080f0964344b939feNico Rieck    COLOR(FGBG, "5", BOLD),\
10944a61bde15d456527156ee2080f0964344b939feNico Rieck    COLOR(FGBG, "6", BOLD),\
11044a61bde15d456527156ee2080f0964344b939feNico Rieck    COLOR(FGBG, "7", BOLD)\
11144a61bde15d456527156ee2080f0964344b939feNico Rieck  }
11244a61bde15d456527156ee2080f0964344b939feNico Rieck
11344a61bde15d456527156ee2080f0964344b939feNico Rieckstatic const char colorcodes[2][2][8][10] = {
11444a61bde15d456527156ee2080f0964344b939feNico Rieck { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
11544a61bde15d456527156ee2080f0964344b939feNico Rieck { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
11644a61bde15d456527156ee2080f0964344b939feNico Rieck};
11744a61bde15d456527156ee2080f0964344b939feNico Rieck
118cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer// Include the platform-specific parts of this class.
1190098e64da7d0b2c47128bac96aa839b2525bfbcaReid Spencer#ifdef LLVM_ON_UNIX
120bccc8abc79338d1cfdd5ea20f7288452ddf75b84Reid Spencer#include "Unix/Process.inc"
1210098e64da7d0b2c47128bac96aa839b2525bfbcaReid Spencer#endif
1220098e64da7d0b2c47128bac96aa839b2525bfbcaReid Spencer#ifdef LLVM_ON_WIN32
1231f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "Windows/Process.inc"
1240098e64da7d0b2c47128bac96aa839b2525bfbcaReid Spencer#endif
125