<commit_before>#ifndef LIBPORT_UTIME_HXX
# define LIBPORT_UTIME_HXX

namespace libport
{

  template <typename Unit>
  inline
  utime_t
  seconds_to_utime(Unit seconds)
  {
    return seconds * 1000 * 1000;
  }

  inline
  utime_t
  timeval_to_utime(const timeval& t)
  {
    return seconds_to_utime(t.tv_sec) + t.tv_usec;
  }

  inline
  timeval
  utime_to_timeval(utime_t t)
  {
    timeval res;
    res.tv_sec =  t / (1000 * 1000);
    res.tv_usec =  t % (1000 * 1000);
    return res;
  }

}

#endif
<commit_msg>Fix an overflow in seconds_to_utime.<commit_after>#ifndef LIBPORT_UTIME_HXX
# define LIBPORT_UTIME_HXX

namespace libport
{

  template <typename Unit>
  inline
  utime_t
  seconds_to_utime(Unit seconds)
  {
    return seconds * 1000LL * 1000LL;
  }

  inline
  utime_t
  timeval_to_utime(const timeval& t)
  {
    return seconds_to_utime(t.tv_sec) + t.tv_usec;
  }

  inline
  timeval
  utime_to_timeval(utime_t t)
  {
    timeval res;
    res.tv_sec =  t / (1000 * 1000);
    res.tv_usec =  t % (1000 * 1000);
    return res;
  }

}

#endif
<|endoftext|>


<commit_before>//===- PathProfileVerifier.cpp --------------------------------*- C++ -*---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This verifier derives an edge profile file from current path profile
// information
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "path-profile-verifier"

#include "llvm/Analysis/Passes.h"
#include "PathProfileInfo.h"
#include "ProfileInfoTypes.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <stdio.h>

using namespace llvm;

namespace {
  class PathProfileVerifier : public ModulePass {
  private:
    bool runOnModule(Module &M);

  public:
    static char ID; // Pass identification, replacement for typeid
    PathProfileVerifier() : ModulePass(ID) {
    }

    virtual const char *getPassName() const {
      return "Path Profiler Verifier";
    }

    // The verifier requires the path profile and edge profile.
    virtual void getAnalysisUsage(AnalysisUsage& AU) const;
  };
}

static cl::opt<std::string>
EdgeProfileFilename("path-profile-verifier-file",
  cl::init("edgefrompath.llvmprof.out"),
  cl::value_desc("filename"),
  cl::desc("Edge profile file generated by -path-profile-verifier"),
  cl::Hidden);

char PathProfileVerifier::ID = 0;
static RegisterPass<PathProfileVerifier> X("path-profile-verifier",
                "Compare the path profile derived edge profile against the "
                "edge profile.", true, true);

// The verifier requires the path profile and edge profile.
void PathProfileVerifier::getAnalysisUsage(AnalysisUsage& AU) const {
  AU.addRequired<PathProfileInfo>();
  AU.addPreserved<PathProfileInfo>();
}

typedef std::map<unsigned, unsigned> DuplicateToIndexMap;
typedef std::map<BasicBlock*,DuplicateToIndexMap> BlockToDuplicateMap;
typedef std::map<BasicBlock*,BlockToDuplicateMap> NestedBlockToIndexMap;

// the verifier iterates through each path to gather the total
// number of edge frequencies
bool PathProfileVerifier::runOnModule (Module &M) {
  PathProfileInfo& pathProfileInfo = getAnalysis<PathProfileInfo>();

  // setup a data structure to map path edges which index an
  // array of edge counters
  NestedBlockToIndexMap arrayMap;
  unsigned i = 0;
  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
    if (F->isDeclaration()) continue;

    arrayMap[(BasicBlock*)0][F->begin()][0] = i++;

    for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
      TerminatorInst *TI = BB->getTerminator();

      unsigned duplicate = 0;
      BasicBlock* prev = 0;
      for (unsigned s = 0, e = TI->getNumSuccessors(); s != e;
           prev = TI->getSuccessor(s), ++s) {
        if (prev == TI->getSuccessor(s))
          duplicate++;
        else duplicate = 0;

        arrayMap[BB][TI->getSuccessor(s)][duplicate] = i++;
      }
    }
  }

  std::vector<unsigned> edgeArray(i);

  // iterate through each path and increment the edge counters as needed
  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
    if (F->isDeclaration()) continue;

    pathProfileInfo.setCurrentFunction(F);

    DEBUG(dbgs() << "function '" << F->getName() << "' ran "
          << pathProfileInfo.pathsRun()
          << "/" << pathProfileInfo.getPotentialPathCount()
          << " potential paths\n");

    for( ProfilePathIterator nextPath = pathProfileInfo.pathBegin(),
           endPath = pathProfileInfo.pathEnd();
         nextPath != endPath; nextPath++ ) {
      ProfilePath* currentPath = nextPath->second;

      ProfilePathEdgeVector* pev = currentPath->getPathEdges();
      DEBUG(dbgs () << "path #" << currentPath->getNumber() << ": "
            << currentPath->getCount() << "\n");
      // setup the entry edge (normally path profiling doesn't care about this)
      if (currentPath->getFirstBlockInPath() == &F->getEntryBlock())
        edgeArray[arrayMap[(BasicBlock*)0][currentPath->getFirstBlockInPath()][0]]
          += currentPath->getCount();

      for( ProfilePathEdgeIterator nextEdge = pev->begin(),
             endEdge = pev->end(); nextEdge != endEdge; nextEdge++ ) {
        if (nextEdge != pev->begin())
          DEBUG(dbgs() << " :: ");

        BasicBlock* source = nextEdge->getSource();
        BasicBlock* target = nextEdge->getTarget();
        unsigned duplicateNumber = nextEdge->getDuplicateNumber();
        DEBUG(dbgs() << source->getName() << " --{" << duplicateNumber
                     << "}--> " << target->getName());

        // Ensure all the referenced edges exist
        // TODO: make this a separate function
        if( !arrayMap.count(source) ) {
          errs() << "  error [" << F->getName() << "()]: source '"
                 << source->getName()
                 << "' does not exist in the array map.\n";
        } else if( !arrayMap[source].count(target) ) {
          errs() << "  error [" << F->getName() << "()]: target '"
                 << target->getName()
                 << "' does not exist in the array map.\n";
        } else if( !arrayMap[source][target].count(duplicateNumber) ) {
          errs() << "  error [" << F->getName() << "()]: edge "
                 << source->getName() << " -> " << target->getName()
                 << " duplicate number " << duplicateNumber
                 << " does not exist in the array map.\n";
        } else {
          edgeArray[arrayMap[source][target][duplicateNumber]]
            += currentPath->getCount();
        }
      }

      DEBUG(errs() << "\n");

      delete pev;
    }
  }

  std::string filename = EdgeProfileFilename;

  // Open a handle to the file
  FILE* edgeFile = fopen(filename.c_str(),"wb");

  if (!edgeFile) {
    errs() << "error: unable to open file '" << filename << "' for output.\n";
    return false;
  }

  errs() << "Generating edge profile '" << filename << "' ...\n";

  // write argument info
  unsigned type = ArgumentInfo;
  unsigned num = pathProfileInfo.argList.size();
  int zeros = 0;

  fwrite(&type,sizeof(unsigned),1,edgeFile);
  fwrite(&num,sizeof(unsigned),1,edgeFile);
  fwrite(pathProfileInfo.argList.c_str(),1,num,edgeFile);
  if (num&3)
    fwrite(&zeros, 1, 4-(num&3), edgeFile);

  type = EdgeInfo;
  num = edgeArray.size();
  fwrite(&type,sizeof(unsigned),1,edgeFile);
  fwrite(&num,sizeof(unsigned),1,edgeFile);

  // write each edge to the file
  for( std::vector<unsigned>::iterator s = edgeArray.begin(),
         e = edgeArray.end(); s != e; s++)
    fwrite(&*s, sizeof (unsigned), 1, edgeFile);

  fclose (edgeFile);

  return true;
}
<commit_msg>Output to debug instead of error stream<commit_after>//===- PathProfileVerifier.cpp --------------------------------*- C++ -*---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This verifier derives an edge profile file from current path profile
// information
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "path-profile-verifier"

#include "llvm/Analysis/Passes.h"
#include "PathProfileInfo.h"
#include "ProfileInfoTypes.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <stdio.h>

using namespace llvm;

namespace {
  class PathProfileVerifier : public ModulePass {
  private:
    bool runOnModule(Module &M);

  public:
    static char ID; // Pass identification, replacement for typeid
    PathProfileVerifier() : ModulePass(ID) {
    }

    virtual const char *getPassName() const {
      return "Path Profiler Verifier";
    }

    // The verifier requires the path profile and edge profile.
    virtual void getAnalysisUsage(AnalysisUsage& AU) const;
  };
}

static cl::opt<std::string>
EdgeProfileFilename("path-profile-verifier-file",
  cl::init("edgefrompath.llvmprof.out"),
  cl::value_desc("filename"),
  cl::desc("Edge profile file generated by -path-profile-verifier"),
  cl::Hidden);

char PathProfileVerifier::ID = 0;
static RegisterPass<PathProfileVerifier> X("path-profile-verifier",
                "Compare the path profile derived edge profile against the "
                "edge profile.", true, true);

// The verifier requires the path profile and edge profile.
void PathProfileVerifier::getAnalysisUsage(AnalysisUsage& AU) const {
  AU.addRequired<PathProfileInfo>();
  AU.addPreserved<PathProfileInfo>();
}

typedef std::map<unsigned, unsigned> DuplicateToIndexMap;
typedef std::map<BasicBlock*,DuplicateToIndexMap> BlockToDuplicateMap;
typedef std::map<BasicBlock*,BlockToDuplicateMap> NestedBlockToIndexMap;

// the verifier iterates through each path to gather the total
// number of edge frequencies
bool PathProfileVerifier::runOnModule (Module &M) {
  PathProfileInfo& pathProfileInfo = getAnalysis<PathProfileInfo>();

  // setup a data structure to map path edges which index an
  // array of edge counters
  NestedBlockToIndexMap arrayMap;
  unsigned i = 0;
  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
    if (F->isDeclaration()) continue;

    arrayMap[(BasicBlock*)0][F->begin()][0] = i++;

    for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
      TerminatorInst *TI = BB->getTerminator();

      unsigned duplicate = 0;
      BasicBlock* prev = 0;
      for (unsigned s = 0, e = TI->getNumSuccessors(); s != e;
           prev = TI->getSuccessor(s), ++s) {
        if (prev == TI->getSuccessor(s))
          duplicate++;
        else duplicate = 0;

        arrayMap[BB][TI->getSuccessor(s)][duplicate] = i++;
      }
    }
  }

  std::vector<unsigned> edgeArray(i);

  // iterate through each path and increment the edge counters as needed
  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
    if (F->isDeclaration()) continue;

    pathProfileInfo.setCurrentFunction(F);

    DEBUG(dbgs() << "function '" << F->getName() << "' ran "
          << pathProfileInfo.pathsRun()
          << "/" << pathProfileInfo.getPotentialPathCount()
          << " potential paths\n");

    for( ProfilePathIterator nextPath = pathProfileInfo.pathBegin(),
           endPath = pathProfileInfo.pathEnd();
         nextPath != endPath; nextPath++ ) {
      ProfilePath* currentPath = nextPath->second;

      ProfilePathEdgeVector* pev = currentPath->getPathEdges();
      DEBUG(dbgs () << "path #" << currentPath->getNumber() << ": "
            << currentPath->getCount() << "\n");
      // setup the entry edge (normally path profiling doesn't care about this)
      if (currentPath->getFirstBlockInPath() == &F->getEntryBlock())
        edgeArray[arrayMap[(BasicBlock*)0][currentPath->getFirstBlockInPath()][0]]
          += currentPath->getCount();

      for( ProfilePathEdgeIterator nextEdge = pev->begin(),
             endEdge = pev->end(); nextEdge != endEdge; nextEdge++ ) {
        if (nextEdge != pev->begin())
          DEBUG(dbgs() << " :: ");

        BasicBlock* source = nextEdge->getSource();
        BasicBlock* target = nextEdge->getTarget();
        unsigned duplicateNumber = nextEdge->getDuplicateNumber();
        DEBUG(dbgs() << source->getName() << " --{" << duplicateNumber
                     << "}--> " << target->getName());

        // Ensure all the referenced edges exist
        // TODO: make this a separate function
        if( !arrayMap.count(source) ) {
          errs() << "  error [" << F->getName() << "()]: source '"
                 << source->getName()
                 << "' does not exist in the array map.\n";
        } else if( !arrayMap[source].count(target) ) {
          errs() << "  error [" << F->getName() << "()]: target '"
                 << target->getName()
                 << "' does not exist in the array map.\n";
        } else if( !arrayMap[source][target].count(duplicateNumber) ) {
          errs() << "  error [" << F->getName() << "()]: edge "
                 << source->getName() << " -> " << target->getName()
                 << " duplicate number " << duplicateNumber
                 << " does not exist in the array map.\n";
        } else {
          edgeArray[arrayMap[source][target][duplicateNumber]]
            += currentPath->getCount();
        }
      }

      DEBUG(errs() << "\n");

      delete pev;
    }
  }

  std::string filename = EdgeProfileFilename;

  // Open a handle to the file
  FILE* edgeFile = fopen(filename.c_str(),"wb");

  if (!edgeFile) {
    errs() << "error: unable to open file '" << filename << "' for output.\n";
    return false;
  }

  dbgs() << "Generating edge profile '" << filename << "' ...\n";

  // write argument info
  unsigned type = ArgumentInfo;
  unsigned num = pathProfileInfo.argList.size();
  int zeros = 0;

  fwrite(&type,sizeof(unsigned),1,edgeFile);
  fwrite(&num,sizeof(unsigned),1,edgeFile);
  fwrite(pathProfileInfo.argList.c_str(),1,num,edgeFile);
  if (num&3)
    fwrite(&zeros, 1, 4-(num&3), edgeFile);

  type = EdgeInfo;
  num = edgeArray.size();
  fwrite(&type,sizeof(unsigned),1,edgeFile);
  fwrite(&num,sizeof(unsigned),1,edgeFile);

  // write each edge to the file
  for( std::vector<unsigned>::iterator s = edgeArray.begin(),
         e = edgeArray.end(); s != e; s++)
    fwrite(&*s, sizeof (unsigned), 1, edgeFile);

  fclose (edgeFile);

  return true;
}
<|endoftext|>


<commit_before>#include "box.hpp"

Box::Box() :
    Box::Shape(),
    min_{0.0,0.0,0.0},
    max_{0.0,0.0,0.0} {
        // std::cout << "Default-Konstruktor-Aufruf fuer Box: " << name() << "\n";
    }

Box::Box(glm::vec3 const& minimum, glm::vec3 const& maximum) :
    Box::Shape(),
    min_{minimum},
    max_{maximum} {
        // std::cout << "Konstruktor-Aufruf fuer Box: " << name() << "\n";
    }

Box::Box(glm::vec3 const& minimum, glm::vec3 const& maximum, std::string n, Material const& m) :
    Box::Shape(n,m),
    min_{minimum},
    max_{maximum} {
        // std::cout << "Konstruktor-Aufruf fuer Box: " << name() << "\n";
    }

Box::~Box() {
        // std::cout << "Destruktor-Aufruf fuer Box: " << name() << "\n";
    }

glm::vec3 const& Box::min() const {
    return min_;
}

glm::vec3 const& Box::max() const {
    return max_;
}

/* virtual */ float Box::area() const {
    float width = abs(max_.x - min_.x);
    float length = abs(max_.y - min_.y);
    float height = abs(max_.z - min_.z);
    return (2 * width * length + 2 * width * height + 2 * length * height);
}

/* virtual */ float Box::volume() const {
    float width = abs(max_.x - min_.x);
    float length = abs(max_.y - min_.y);
    float height = abs(max_.z - min_.z);
    return (width * length * height);
}

/* virtual */ std::ostream& Box::print(std::ostream& os) const {
    os << "Box: \n";
    Shape::print(os);
    os << "Minimum: (" << min().x << "," << min().y << "," << min().z << ") \n";
    os << "Maximum: (" << max().x << "," << max().y << "," << max().z << ") \n";
    os << "Flaecheninhalt: " << area() << "\n";
    os << "Volumen: " << volume() << "\n\n";
    return os;
}

Hit Box::intersect(Ray const& ray) {

    float t1 = (max_.x - ray.origin_.x) * ray.inv_direction_.x;
    float t2 = (min_.x - ray.origin_.x) * ray.inv_direction_.x;
    float t3 = (max_.y - ray.origin_.y) * ray.inv_direction_.y;
    float t4 = (min_.y - ray.origin_.y) * ray.inv_direction_.y;
    float t5 = (max_.z - ray.origin_.z) * ray.inv_direction_.z;
    float t6 = (min_.z - ray.origin_.z) * ray.inv_direction_.z;

    //Range on x-Ebene for possible intersection
    float tmax = std::max(t1,t2);
    float tmin = std::min(t1,t2);
    //Range on y-Ebene for possible intersection after looking on x-Ebene
    tmax = std::min(std::max(t3,t4),tmax);
    tmin = std::max(std::min(t3,t4),tmin);
    //Range on z-Ebene for possible intersection after looking on x and y
    tmax = std::min(std::max(t5,t6),tmax);
    tmin = std::max(std::min(t5,t6),tmin);

    /*if (ray.direction_.x != 0)  //Schnittpunkte mit der x-Ebene
    {
        t1 = (std::min(min_.x - ray.origin_.x , max_.x - ray.origin_.x )) / ray.direction_.x;
        t2 = (std::max(min_.x - ray.origin_.x , max_.x - ray.origin_.x )) / ray.direction_.x;
    }

    if (ray.direction_.y != 0)  //Schnittpunkte mit der y-Ebene
    {
        t3 = (std::min(min_.y - ray.origin_.y , max_.y - ray.origin_.y )) / ray.direction_.y;
        t4 = (std::max(min_.y - ray.origin_.y , max_.y - ray.origin_.y )) / ray.direction_.y;
    }

    if (ray.direction_.z != 0)  //Schnittpunkte mit der x-Ebene
    {
        t5 = (std::min(min_.z - ray.origin_.z , max_.z - ray.origin_.z )) / ray.direction_.z;
        t6 = (std::max(min_.z - ray.origin_.z , max_.z - ray.origin_.z )) / ray.direction_.z;
    }*/

    Hit hit;

    glm::vec3 normal;

    //getting the right normal for an intersection
    if (abs(hit.intersection_.x - max_.x) < 0.000001) {
        normal = glm::vec3{1.0, 0.0, 0.0};
    } else if (abs(hit.intersection_.x - min_.x) < 0.000001) {
        normal = glm::vec3{-1.0, 0.0, 0.0};
    } else if (abs(hit.intersection_.y - max_.y) < 0.000001) {
        normal = glm::vec3{0.0, 1.0, 0.0};
    } else if (abs(hit.intersection_.y - min_.y) < 0.000001) {
        normal = glm::vec3{0.0, -1.0, 0.0};
    } else if (abs(hit.intersection_.z - max_.z) < 0.000001) {
        normal = glm::vec3{0.0, 0.0, -1.0};
    } else if (abs(hit.intersection_.z - min_.z) < 0.000001) {
        normal = glm::vec3{0.0, 0.0, 1.0};
    }

    if (tmax > std::max(0.0, tmin)) {
        hit.distance_ = sqrt(tmin * tmin *
                             (ray.direction_.x * ray.direction_.x +
                              ray.direction_.y * ray.direction_.y +
                              ray.direction_.z * ray.direction_.z)
                            );

        hit.intersection_ = glm::vec3{
            tmin * ray.direction_.x,
            tmin * ray.direction_.y,
            tmin * ray.direction_.z
        };
        hit.normal_ = normal;
        hit.sptr_ = std::make_shared<Box>(*this);
        hit.hit_ = true;
    }

/*    float inp = std::max(       //Eintrittspunkt
                    std::max( std::min(t1,t2), std::min(t3,t4) ),
                    std::min(t5,t6)
                    );

    float outp = std::min(      //Austrittspunkt
                    std::min( std::max(t1,t2), std::max(t3,t4) ),
                    std::max(t5,t6)
                    );

    if (outp < std::max(0.0f, inp))
    {
        return {};
    }

    //  distance = std::sqrt( ((ray.origin_.x * ray.origin_.x) + (ray.origin_.y * ray.origin_.y) + (ray.origin_.z * ray.origin_.z)) - () )
    distance = std::sqrt(
        (ray.direction_.x * (outp - inp) * ray.direction_.x * (outp - inp)) +
        (ray.direction_.y * (outp - inp) * ray.direction_.y * (outp - inp)) +
        (ray.direction_.z * (outp - inp) * ray.direction_.z * (outp - inp))
        );

    return {};

}*/

    return hit;
}
<commit_msg>updating intersect<commit_after>#include "box.hpp"

Box::Box() :
    Box::Shape(),
    min_{0.0,0.0,0.0},
    max_{0.0,0.0,0.0} {
        // std::cout << "Default-Konstruktor-Aufruf fuer Box: " << name() << "\n";
    }

Box::Box(glm::vec3 const& minimum, glm::vec3 const& maximum) :
    Box::Shape(),
    min_{minimum},
    max_{maximum} {
        // std::cout << "Konstruktor-Aufruf fuer Box: " << name() << "\n";
    }

Box::Box(glm::vec3 const& minimum, glm::vec3 const& maximum, std::string n, Material const& m) :
    Box::Shape(n,m),
    min_{minimum},
    max_{maximum} {
        // std::cout << "Konstruktor-Aufruf fuer Box: " << name() << "\n";
    }

Box::~Box() {
        // std::cout << "Destruktor-Aufruf fuer Box: " << name() << "\n";
    }

glm::vec3 const& Box::min() const {
    return min_;
}

glm::vec3 const& Box::max() const {
    return max_;
}

/* virtual */ float Box::area() const {
    float width = abs(max_.x - min_.x);
    float length = abs(max_.y - min_.y);
    float height = abs(max_.z - min_.z);
    return (2 * width * length + 2 * width * height + 2 * length * height);
}

/* virtual */ float Box::volume() const {
    float width = abs(max_.x - min_.x);
    float length = abs(max_.y - min_.y);
    float height = abs(max_.z - min_.z);
    return (width * length * height);
}

/* virtual */ std::ostream& Box::print(std::ostream& os) const {
    os << "Box: \n";
    Shape::print(os);
    os << "Minimum: (" << min().x << "," << min().y << "," << min().z << ") \n";
    os << "Maximum: (" << max().x << "," << max().y << "," << max().z << ") \n";
    os << "Flaecheninhalt: " << area() << "\n";
    os << "Volumen: " << volume() << "\n\n";
    return os;
}

Hit Box::intersect(Ray const& ray) {

    float t1 = (max_.x - ray.origin_.x) * ray.inv_direction_.x;
    float t2 = (min_.x - ray.origin_.x) * ray.inv_direction_.x;
    float t3 = (max_.y - ray.origin_.y) * ray.inv_direction_.y;
    float t4 = (min_.y - ray.origin_.y) * ray.inv_direction_.y;
    float t5 = (max_.z - ray.origin_.z) * ray.inv_direction_.z;
    float t6 = (min_.z - ray.origin_.z) * ray.inv_direction_.z;

    //Range on x-Ebene for possible intersection
    float tmax = std::max(t1,t2);
    float tmin = std::min(t1,t2);
    //Range on y-Ebene for possible intersection after looking on x-Ebene
    tmax = std::min(std::max(t3,t4),tmax);
    tmin = std::max(std::min(t3,t4),tmin);
    //Range on z-Ebene for possible intersection after looking on x and y
    tmax = std::min(std::max(t5,t6),tmax);
    tmin = std::max(std::min(t5,t6),tmin);

    /*if (ray.direction_.x != 0)  //Schnittpunkte mit der x-Ebene
    {
        t1 = (std::min(min_.x - ray.origin_.x , max_.x - ray.origin_.x )) / ray.direction_.x;
        t2 = (std::max(min_.x - ray.origin_.x , max_.x - ray.origin_.x )) / ray.direction_.x;
    }

    if (ray.direction_.y != 0)  //Schnittpunkte mit der y-Ebene
    {
        t3 = (std::min(min_.y - ray.origin_.y , max_.y - ray.origin_.y )) / ray.direction_.y;
        t4 = (std::max(min_.y - ray.origin_.y , max_.y - ray.origin_.y )) / ray.direction_.y;
    }

    if (ray.direction_.z != 0)  //Schnittpunkte mit der x-Ebene
    {
        t5 = (std::min(min_.z - ray.origin_.z , max_.z - ray.origin_.z )) / ray.direction_.z;
        t6 = (std::max(min_.z - ray.origin_.z , max_.z - ray.origin_.z )) / ray.direction_.z;
    }*/

    Hit hit;

    glm::vec3 normal{INFINITY,INFINITY,INFINITY};

    //getting the normal vec on the side of the intersection
    if (abs(hit.intersection_.x - max_.x) < 0.000001) {
        normal = glm::vec3{1.0, 0.0, 0.0};
    } else if (abs(hit.intersection_.x - min_.x) < 0.000001) {
        normal = glm::vec3{-1.0, 0.0, 0.0};
    } else if (abs(hit.intersection_.y - max_.y) < 0.000001) {
        normal = glm::vec3{0.0, 1.0, 0.0};
    } else if (abs(hit.intersection_.y - min_.y) < 0.000001) {
        normal = glm::vec3{0.0, -1.0, 0.0};
    } else if (abs(hit.intersection_.z - max_.z) < 0.000001) {
        normal = glm::vec3{0.0, 0.0, -1.0};
    } else if (abs(hit.intersection_.z - min_.z) < 0.000001) {
        normal = glm::vec3{0.0, 0.0, 1.0};
    }

    if (tmax > std::max(0.0f, tmin)) {
        hit.distance_ = sqrt(tmin * tmin *
                             (ray.direction_.x * ray.direction_.x +
                              ray.direction_.y * ray.direction_.y +
                              ray.direction_.z * ray.direction_.z)
                            );

        hit.intersection_ = glm::vec3{
            tmin * ray.direction_.x,
            tmin * ray.direction_.y,
            tmin * ray.direction_.z
        };
        hit.normal_ = normal;
        hit.sptr_ = std::make_shared<Box>(*this);
        hit.hit_ = true;
    }

/*    float inp = std::max(       //Eintrittspunkt
                    std::max( std::min(t1,t2), std::min(t3,t4) ),
                    std::min(t5,t6)
                    );

    float outp = std::min(      //Austrittspunkt
                    std::min( std::max(t1,t2), std::max(t3,t4) ),
                    std::max(t5,t6)
                    );

    if (outp < std::max(0.0f, inp))
    {
        return {};
    }

    //  distance = std::sqrt( ((ray.origin_.x * ray.origin_.x) + (ray.origin_.y * ray.origin_.y) + (ray.origin_.z * ray.origin_.z)) - () )
    distance = std::sqrt(
        (ray.direction_.x * (outp - inp) * ray.direction_.x * (outp - inp)) +
        (ray.direction_.y * (outp - inp) * ray.direction_.y * (outp - inp)) +
        (ray.direction_.z * (outp - inp) * ray.direction_.z * (outp - inp))
        );

    return {};

}*/

    return hit;
}
<|endoftext|>


<commit_before>#include "PocketsphinxWrapper.h"

#include <string>
#include <boost/filesystem.hpp>

#include "pocketsphinx/pocketsphinx.h"
#include "Logger.h"

#ifdef IBM
#define POCKETSPHINX_LOGFN "nul"
#else
#define POCKETSPHINX_LOGFN "/dev/null"
#endif

using namespace xcopilot;

boost::filesystem::path getPocketsphinxDataPathForResource(const std::string& resource)
{
    return boost::filesystem::absolute("pocketsphinx-data/xp-XP/" + resource);
}

void Pocketsphinx::start()
{
    Logger::getInstance()->debug("Starting pocketsphinx");
    auto hmm = getPocketsphinxDataPathForResource("acoustic-model").generic_string();
    auto lm = getPocketsphinxDataPathForResource("language-model.lm").generic_string();
    auto jsgf = getPocketsphinxDataPathForResource("grammar.jsgf").generic_string();
    auto dict = getPocketsphinxDataPathForResource("pronounciation-dictionary.dic").generic_string();
    cmd_ln_t* config = cmd_ln_init(NULL, ps_args(), TRUE,       // Load the configuration structure - ps_args() passes the default values
    "-hmm", hmm.c_str(),  // path to the standard english language model
//    "-lm", lm.c_str(),
    "-jsgf", lm.c_str(),
    "-dict", dict.c_str(),
    "-logfn", POCKETSPHINX_LOGFN,                                      // suppress log info from being sent to screen
    NULL);
    ps = ps_init(config);

    ps_start_utt(ps);
    Logger::getInstance()->debug("Pocketsphinx successfuly");
}

void Pocketsphinx::stop() { ps_end_utt(ps); }

void Pocketsphinx::process(const short* rawData, unsigned long frameCount)
{
    ps_process_raw(ps, rawData, frameCount, FALSE, FALSE);
}

std::string Pocketsphinx::decode()
{
    ps_end_utt(ps);
    std::string result = ps_get_hyp(ps, NULL);
    ps_start_utt(ps);
    return result;
}

bool Pocketsphinx::isSpeaking() const { return ps_get_in_speech(ps); }
<commit_msg>fix wrong jsgf variable reference<commit_after>#include "PocketsphinxWrapper.h"

#include <string>
#include <boost/filesystem.hpp>

#include "pocketsphinx/pocketsphinx.h"
#include "Logger.h"

#ifdef IBM
#define POCKETSPHINX_LOGFN "nul"
#else
#define POCKETSPHINX_LOGFN "/dev/null"
#endif

using namespace xcopilot;

boost::filesystem::path getPocketsphinxDataPathForResource(const std::string& resource)
{
    return boost::filesystem::absolute("pocketsphinx-data/xp-XP/" + resource);
}

void Pocketsphinx::start()
{
    Logger::getInstance()->debug("Starting pocketsphinx");
    auto hmm = getPocketsphinxDataPathForResource("acoustic-model").generic_string();
    auto lm = getPocketsphinxDataPathForResource("language-model.lm").generic_string();
    auto jsgf = getPocketsphinxDataPathForResource("grammar.jsgf").generic_string();
    auto dict = getPocketsphinxDataPathForResource("pronounciation-dictionary.dic").generic_string();
    cmd_ln_t* config = cmd_ln_init(NULL, ps_args(), TRUE,       // Load the configuration structure - ps_args() passes the default values
    "-hmm", hmm.c_str(),  // path to the standard english language model
//    "-lm", lm.c_str(),
    "-jsgf", jsgf.c_str(),
    "-dict", dict.c_str(),
    "-logfn", POCKETSPHINX_LOGFN,                                      // suppress log info from being sent to screen
    NULL);
    ps = ps_init(config);

    ps_start_utt(ps);
    Logger::getInstance()->debug("Pocketsphinx successfuly");
}

void Pocketsphinx::stop() { ps_end_utt(ps); }

void Pocketsphinx::process(const short* rawData, unsigned long frameCount)
{
    ps_process_raw(ps, rawData, frameCount, FALSE, FALSE);
}

std::string Pocketsphinx::decode()
{
    ps_end_utt(ps);
    std::string result = ps_get_hyp(ps, NULL);
    ps_start_utt(ps);
    return result;
}

bool Pocketsphinx::isSpeaking() const { return ps_get_in_speech(ps); }
<|endoftext|>


<commit_before>/*
 * Copyright 2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#if defined(_WIN32)
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <log4cxx/nt/nteventlogappender.h>
#include "../appenderskeletontestcase.h"
#include <apr_time.h>
#include "windows.h"
#include <log4cxx/logger.h>
#include <log4cxx/spi/loggingevent.h>
#include <log4cxx/patternlayout.h>
#include "../insertwide.h"

using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace log4cxx::nt;
using namespace log4cxx::spi;

/**
   Unit tests of log4cxx::nt::NTEventLogAppender
 */
class NTEventLogAppenderTestCase : public AppenderSkeletonTestCase
{
   CPPUNIT_TEST_SUITE(NTEventLogAppenderTestCase);
                //
                //    tests inherited from AppenderSkeletonTestCase
                //
                CPPUNIT_TEST(testDefaultThreshold);
                CPPUNIT_TEST(testSetOptionThreshold);
                CPPUNIT_TEST(testHelloWorld);

   CPPUNIT_TEST_SUITE_END();

public:

        AppenderSkeleton* createAppenderSkeleton() const {
          return new log4cxx::nt::NTEventLogAppender();
        }

        void testHelloWorld() {
           DWORD expectedCount = 1;
           HANDLE hEventLog = ::OpenEventLogW(NULL, L"log4cxx_test");
           if (hEventLog != NULL) {
               BOOL stat = GetNumberOfEventLogRecords(hEventLog, &expectedCount);
               CPPUNIT_ASSERT(stat);
               CloseEventLog(hEventLog);
               expectedCount++;
           }

            Pool p;
            DWORD expectedTime = apr_time_sec(apr_time_now());
            {
                NTEventLogAppenderPtr appender(new NTEventLogAppender());
                appender->setSource(LOG4CXX_STR("log4cxx_test"));
                LayoutPtr layout(new PatternLayout(LOG4CXX_STR("%c - %m%n")));
                appender->setLayout(layout);
                appender->activateOptions(p);
                LoggerPtr logger(Logger::getLogger(L"org.foobar"));

                LoggingEventPtr event(new LoggingEvent(
                    logger, Level::INFO, LOG4CXX_STR("Hello,  World"), LOG4CXX_LOCATION));
                appender->doAppend(event, p);
            }
            hEventLog = ::OpenEventLogW(NULL, L"log4cxx_test");
            CPPUNIT_ASSERT(hEventLog != NULL);
            DWORD actualCount;
            BOOL stat = GetNumberOfEventLogRecords(hEventLog, &actualCount);
            CloseEventLog(hEventLog);
            CPPUNIT_ASSERT(stat);
            CPPUNIT_ASSERT_EQUAL(expectedCount, actualCount);
        }
};

CPPUNIT_TEST_SUITE_REGISTRATION(NTEventLogAppenderTestCase);
#endif
<commit_msg>LOGCXX-67: Tweaked NTAppenderTestCase for full event logs<commit_after>/*
 * Copyright 2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#if defined(_WIN32)
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <log4cxx/nt/nteventlogappender.h>
#include "../appenderskeletontestcase.h"
#include <apr_time.h>
#include "windows.h"
#include <log4cxx/logger.h>
#include <log4cxx/spi/loggingevent.h>
#include <log4cxx/patternlayout.h>
#include "../insertwide.h"

using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace log4cxx::nt;
using namespace log4cxx::spi;

/**
   Unit tests of log4cxx::nt::NTEventLogAppender
 */
class NTEventLogAppenderTestCase : public AppenderSkeletonTestCase
{
   CPPUNIT_TEST_SUITE(NTEventLogAppenderTestCase);
                //
                //    tests inherited from AppenderSkeletonTestCase
                //
                CPPUNIT_TEST(testDefaultThreshold);
                CPPUNIT_TEST(testSetOptionThreshold);
                CPPUNIT_TEST(testHelloWorld);

   CPPUNIT_TEST_SUITE_END();

public:

        AppenderSkeleton* createAppenderSkeleton() const {
          return new log4cxx::nt::NTEventLogAppender();
        }

        void testHelloWorld() {
           DWORD expectedId = 1;
           HANDLE hEventLog = ::OpenEventLogW(NULL, L"log4cxx_test");
           if (hEventLog != NULL) {
               BOOL stat = GetNumberOfEventLogRecords(hEventLog, &expectedId);
               DWORD oldest;
               if(stat) stat = GetOldestEventLogRecord(hEventLog, &oldest);
               CloseEventLog(hEventLog);
               CPPUNIT_ASSERT(stat);
               expectedId += oldest;
           }

            Pool p;
            DWORD expectedTime = apr_time_sec(apr_time_now());
            {
                NTEventLogAppenderPtr appender(new NTEventLogAppender());
                appender->setSource(LOG4CXX_STR("log4cxx_test"));
                LayoutPtr layout(new PatternLayout(LOG4CXX_STR("%c - %m%n")));
                appender->setLayout(layout);
                appender->activateOptions(p);
                LoggerPtr logger(Logger::getLogger(L"org.foobar"));

                LoggingEventPtr event(new LoggingEvent(
                    logger, Level::INFO, LOG4CXX_STR("Hello,  World"), LOG4CXX_LOCATION));
                appender->doAppend(event, p);
            }
            hEventLog = ::OpenEventLogW(NULL, L"log4cxx_test");
            CPPUNIT_ASSERT(hEventLog != NULL);
            DWORD actualId;
            BOOL stat = GetNumberOfEventLogRecords(hEventLog, &actualId);
            DWORD oldest;
            if (stat) stat = GetOldestEventLogRecord(hEventLog, &oldest);
            actualId += oldest;
            actualId--;
            CloseEventLog(hEventLog);
            CPPUNIT_ASSERT(stat);
            CPPUNIT_ASSERT_EQUAL(expectedId, actualId);
        }
};

CPPUNIT_TEST_SUITE_REGISTRATION(NTEventLogAppenderTestCase);
#endif
<|endoftext|>


<commit_before>#include <chrono>
#include <iostream>
#include <numeric>
#include <vector>

#include "tensorflow/cc/ops/array_ops.h"
#include "tensorflow/cc/ops/const_op.h"
#include "tensorflow/cc/ops/image_ops.h"
#include "tensorflow/cc/saved_model/loader.h"
#include "tensorflow/compiler/tf2tensorrt/trt_convert_api.h"
#include "tensorflow/core/common_runtime/device_mgr.h"
#include "tensorflow/core/framework/graph.pb.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/graph/default_device.h"
#include "tensorflow/core/platform/init_main.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/public/session.h"
#include "tensorflow/core/util/command_line_flags.h"

using tensorflow::Flag;
using tensorflow::Status;
using tensorflow::string;
using tensorflow::Tensor;

#define TFTRT_ENSURE_OK(x)                                                 \
  do {                                                                     \
    Status s = x;                                                          \
    if (!s.ok()) {                                                         \
      std::cerr << __FILE__ << ":" << __LINE__ << " " << s.error_message() \
                << std::endl;                                              \
      return 1;                                                            \
    }                                                                      \
  } while (0)

// Get the GPU and its default context.
Status GetDevice(std::unique_ptr<tensorflow::Session>& session,
                 tensorflow::Device** device,
                 tensorflow::DeviceContext** device_context) {
  const tensorflow::DeviceMgr* mgr;
  TF_RETURN_IF_ERROR(session->LocalDeviceManager(&mgr));
  std::vector<tensorflow::Device*> devices = mgr->ListDevices();
  for (const auto& d : devices) {
    if (d->device_type() == "GPU" || d->device_type() == "gpu") {
      auto* device_info = d->tensorflow_gpu_device_info();
      *device_context = device_info->default_context;
      *device = d;
    }
  }
  return Status::OK();
}

// Returns info for nodes listed in the signature definition.
std::vector<tensorflow::TensorInfo> GetNodeInfo(
    const google::protobuf::Map<string, tensorflow::TensorInfo>& signature) {
  std::vector<tensorflow::TensorInfo> info;
  for (const auto& item : signature) {
    info.push_back(item.second);
  }
  return info;
}

// Load the `SavedModel` located at `model_dir`.
Status LoadModel(const string& model_dir, const string& signature_key,
                 tensorflow::SavedModelBundle* bundle,
                 std::vector<tensorflow::TensorInfo>* input_info,
                 std::vector<tensorflow::TensorInfo>* output_info) {
  tensorflow::RunOptions run_options;
  tensorflow::SessionOptions sess_options;
  sess_options.config.mutable_gpu_options()->force_gpu_compatible();
  TF_RETURN_IF_ERROR(tensorflow::LoadSavedModel(sess_options, run_options,
                                                model_dir, {"serve"}, bundle));

  // Get input and output names
  auto signature_map = bundle->GetSignatures();
  const tensorflow::SignatureDef& signature = signature_map[signature_key];
  *input_info = GetNodeInfo(signature.inputs());
  *output_info = GetNodeInfo(signature.outputs());

  return Status::OK();
}

// Create arbitrary inputs matching `input_info` and load them on the device.
Status SetupInputs(tensorflow::Device* device,
                   tensorflow::DeviceContext* device_context,
                   int32_t batch_size,
                   std::vector<tensorflow::TensorInfo>& input_info,
                   std::vector<Tensor>* inputs) {
  tensorflow::AllocatorAttributes attr;
  tensorflow::Allocator* allocator = device->GetAllocator(attr);

  std::vector<Tensor> inputs_device;
  for (const auto& info : input_info) {
    // Set input batch size
    auto shape = info.tensor_shape();
    shape.mutable_dim(0)->set_size(batch_size);

    // Allocate memory and fill host tensor
    Tensor input_host(info.dtype(), shape);
    Tensor input_device(allocator, info.dtype(), shape);
    std::fill_n((uint8_t*)input_host.data(), input_host.AllocatedBytes(), 1);

    // Copy from host to device
    TF_RETURN_IF_ERROR(device_context->CopyCPUTensorToDeviceSync(
        &input_host, device, &input_device));
    inputs_device.push_back(input_device);
  }
  *inputs = inputs_device;
  return Status::OK();
}

// Configure a `CallableHandle` that feeds from and fetches to a device.
Status SetupCallable(std::unique_ptr<tensorflow::Session>& session,
                     std::vector<tensorflow::TensorInfo>& input_info,
                     std::vector<tensorflow::TensorInfo>& output_info,
                     const string& device_name,
                     tensorflow::Session::CallableHandle* handle) {
  tensorflow::CallableOptions opts;
  for (const auto& info : input_info) {
    const string& name = info.name();
    opts.add_feed(name);
    opts.mutable_feed_devices()->insert({name, device_name});
  }
  for (const auto& info : output_info) {
    const string& name = info.name();
    opts.add_fetch(name);
    opts.mutable_fetch_devices()->insert({name, device_name});
  }
  opts.set_fetch_skip_sync(true);
  return session->MakeCallable(opts, handle);
}

int main(int argc, char* argv[]) {
  // Parse arguments
  string model_path = "/path/to/model/";
  string signature_key = "serving_default";
  int32_t batch_size = 64;
  int32_t warmup_iters = 50;
  int32_t eval_iters = 1000;
  std::vector<Flag> flag_list = {
      Flag("model_path", &model_path, "graph to be executed"),
      Flag("signature_key", &signature_key, "the serving signature to use"),
      Flag("batch_size", &batch_size, "batch size to use for inference"),
      Flag("warmup_iters", &warmup_iters, "number of warmup iterations to run"),
      Flag("eval_iters", &eval_iters, "number of timed iterations to run"),
  };
  string usage = tensorflow::Flags::Usage(argv[0], flag_list);
  const bool parse_result = tensorflow::Flags::Parse(&argc, argv, flag_list);
  if (!parse_result) {
    LOG(ERROR) << usage;
    return -1;
  }

  // We need to call this to set up global state for TensorFlow.
  tensorflow::port::InitMain(argv[0], &argc, &argv);
  if (argc > 1) {
    LOG(ERROR) << "Unknown argument " << argv[1] << "\n" << usage;
    return -1;
  }

  // Setup session
  tensorflow::SavedModelBundle bundle;
  std::vector<tensorflow::TensorInfo> input_info;
  std::vector<tensorflow::TensorInfo> output_info;
  TFTRT_ENSURE_OK(
      LoadModel(model_path, signature_key, &bundle, &input_info, &output_info));

  // TODO: Convert model w/ TRT and add flag for this behavior

  // Get device
  tensorflow::Device* device;
  tensorflow::DeviceContext* device_context;
  TFTRT_ENSURE_OK(GetDevice(bundle.session, &device, &device_context));

  // Create inputs and move to device
  // TODO: Measure H2D times over repeated calls and report metrics
  std::vector<Tensor> inputs_device;
  TFTRT_ENSURE_OK(SetupInputs(device, device_context, batch_size, input_info,
                              &inputs_device));

  // Configure to feed and fetch from device
  tensorflow::Session::CallableHandle handle;
  TFTRT_ENSURE_OK(SetupCallable(bundle.session, input_info, output_info,
                                device->name(), &handle));

  // Run benchmarking
  std::vector<Tensor> outputs;
  std::vector<double> infer_time;
  std::chrono::steady_clock::time_point eval_start_time;
  std::chrono::steady_clock::time_point start_time;
  std::chrono::steady_clock::time_point end_time;
  for (int i = 0; i < warmup_iters + eval_iters; i++) {
    if (i == warmup_iters) {
      LOG(INFO) << "Warmup done";
      eval_start_time = std::chrono::steady_clock::now();
    }

    start_time = std::chrono::steady_clock::now();
    TFTRT_ENSURE_OK(
        bundle.session->RunCallable(handle, inputs_device, &outputs, nullptr));
    // Sync, as `set_fetch_skip_sync(false)` is currently not implemented
    TFTRT_ENSURE_OK(device->Sync());
    end_time = std::chrono::steady_clock::now();

    double duration = (end_time - start_time).count() / 1e6;
    infer_time.push_back(duration);
  }
  TFTRT_ENSURE_OK(bundle.session->ReleaseCallable(handle));

  // Print results
  std::sort(infer_time.begin() + warmup_iters, infer_time.end());
  double total_compute_time =
      std::accumulate(infer_time.begin() + warmup_iters, infer_time.end(), 0.0);
  double total_wall_time = (end_time - eval_start_time).count() / 1e6;
  int32_t m = warmup_iters + eval_iters / 2;
  LOG(INFO) << "Total wall time (s): " << total_wall_time / 1e3;
  LOG(INFO) << "Total GPU compute time (s): " << total_compute_time / 1e3;
  LOG(INFO) << "Mean GPU compute time (ms): " << total_compute_time / eval_iters;
  LOG(INFO) << "Median GPU compute time (ms): " << (eval_iters % 2 ? infer_time[m]
                                                                   : (infer_time[m - 1] + infer_time[m]) / 2);
  // Note: Throughput using GPU inference time, rather than wall time
  LOG(INFO) << "Throughput (samples/s): " << 1e3 * eval_iters * batch_size / total_compute_time;
  LOG(INFO) << "Engine build time + first inference latency (ms): " << infer_time.front();

  return 0;
}<commit_msg>Add parameters to control input/output devices, set output device default to host to address int32 issue<commit_after>#include <chrono>
#include <iostream>
#include <numeric>
#include <vector>

#include "tensorflow/cc/ops/array_ops.h"
#include "tensorflow/cc/ops/const_op.h"
#include "tensorflow/cc/ops/image_ops.h"
#include "tensorflow/cc/saved_model/loader.h"
#include "tensorflow/compiler/tf2tensorrt/trt_convert_api.h"
#include "tensorflow/core/common_runtime/device_mgr.h"
#include "tensorflow/core/framework/graph.pb.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/graph/default_device.h"
#include "tensorflow/core/platform/init_main.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/public/session.h"
#include "tensorflow/core/util/command_line_flags.h"

using tensorflow::Flag;
using tensorflow::Status;
using tensorflow::string;
using tensorflow::Tensor;

#define TFTRT_ENSURE_OK(x)                                                 \
  do {                                                                     \
    Status s = x;                                                          \
    if (!s.ok()) {                                                         \
      std::cerr << __FILE__ << ":" << __LINE__ << " " << s.error_message() \
                << std::endl;                                              \
      return 1;                                                            \
    }                                                                      \
  } while (0)

// Get the GPU and its default context.
Status GetDevice(std::unique_ptr<tensorflow::Session>& session,
                 tensorflow::Device** device,
                 tensorflow::DeviceContext** device_context) {
  const tensorflow::DeviceMgr* mgr;
  TF_RETURN_IF_ERROR(session->LocalDeviceManager(&mgr));
  std::vector<tensorflow::Device*> devices = mgr->ListDevices();
  for (const auto& d : devices) {
    if (d->device_type() == "GPU" || d->device_type() == "gpu") {
      auto* device_info = d->tensorflow_gpu_device_info();
      *device_context = device_info->default_context;
      *device = d;
    }
  }
  return Status::OK();
}

// Returns info for nodes listed in the signature definition.
std::vector<tensorflow::TensorInfo> GetNodeInfo(
    const google::protobuf::Map<string, tensorflow::TensorInfo>& signature) {
  std::vector<tensorflow::TensorInfo> info;
  for (const auto& item : signature) {
    info.push_back(item.second);
  }
  return info;
}

// Load the `SavedModel` located at `model_dir`.
Status LoadModel(const string& model_dir, const string& signature_key,
                 tensorflow::SavedModelBundle* bundle,
                 std::vector<tensorflow::TensorInfo>* input_info,
                 std::vector<tensorflow::TensorInfo>* output_info) {
  tensorflow::RunOptions run_options;
  tensorflow::SessionOptions sess_options;
  sess_options.config.mutable_gpu_options()->force_gpu_compatible();
  TF_RETURN_IF_ERROR(tensorflow::LoadSavedModel(sess_options, run_options,
                                                model_dir, {"serve"}, bundle));

  // Get input and output names
  auto signature_map = bundle->GetSignatures();
  const tensorflow::SignatureDef& signature = signature_map[signature_key];
  *input_info = GetNodeInfo(signature.inputs());
  *output_info = GetNodeInfo(signature.outputs());

  return Status::OK();
}

// Create arbitrary inputs matching `input_info` and load them on the device.
Status SetupInputs(tensorflow::Device* device,
                   tensorflow::DeviceContext* device_context,
                   int32_t batch_size,
                   std::vector<tensorflow::TensorInfo>& input_info,
                   std::vector<Tensor>* inputs) {
  tensorflow::AllocatorAttributes attr;
  tensorflow::Allocator* allocator = device->GetAllocator(attr);

  std::vector<Tensor> inputs_device;
  for (const auto& info : input_info) {
    // Set input batch size
    auto shape = info.tensor_shape();
    shape.mutable_dim(0)->set_size(batch_size);

    // Allocate memory and fill host tensor
    Tensor input_host(info.dtype(), shape);
    Tensor input_device(allocator, info.dtype(), shape);
    std::fill_n((uint8_t*)input_host.data(), input_host.AllocatedBytes(), 1);

    // Copy from host to device
    TF_RETURN_IF_ERROR(device_context->CopyCPUTensorToDeviceSync(
        &input_host, device, &input_device));
    inputs_device.push_back(input_device);
  }
  *inputs = inputs_device;
  return Status::OK();
}

// Configure a `CallableHandle` that feeds from and fetches to a device.
Status SetupCallable(std::unique_ptr<tensorflow::Session>& session,
                     std::vector<tensorflow::TensorInfo>& input_info,
                     std::vector<tensorflow::TensorInfo>& output_info,
                     const string& device_name,
                     bool input_from_device,
                     bool output_to_host,
                     tensorflow::Session::CallableHandle* handle) {
  tensorflow::CallableOptions opts;
  for (const auto& info : input_info) {
    const string& name = info.name();
    opts.add_feed(name);
    if (input_from_device) {
      opts.mutable_feed_devices()->insert({name, device_name});
    }
  }
  for (const auto& info : output_info) {
    const string& name = info.name();
    opts.add_fetch(name);
    if (!output_to_host) {
      opts.mutable_fetch_devices()->insert({name, device_name});
    }
  }
  opts.set_fetch_skip_sync(true);
  return session->MakeCallable(opts, handle);
}

int main(int argc, char* argv[]) {
  // Parse arguments
  string model_path = "/path/to/model/";
  string signature_key = "serving_default";
  int32_t batch_size = 64;
  int32_t warmup_iters = 50;
  int32_t eval_iters = 1000;
  bool input_from_device = true;
  bool output_to_host = true;
  std::vector<Flag> flag_list = {
      Flag("model_path", &model_path, "graph to be executed"),
      Flag("signature_key", &signature_key, "the serving signature to use"),
      Flag("batch_size", &batch_size, "batch size to use for inference"),
      Flag("warmup_iters", &warmup_iters, "number of warmup iterations to run"),
      Flag("eval_iters", &eval_iters, "number of timed iterations to run"),
      Flag("input_from_device", &input_from_device, "use inputs from device, rather than host"),
      Flag("output_to_host", &output_to_host, "copy outputs to host after inference"),
  };
  string usage = tensorflow::Flags::Usage(argv[0], flag_list);
  const bool parse_result = tensorflow::Flags::Parse(&argc, argv, flag_list);
  if (!parse_result) {
    LOG(ERROR) << usage;
    return -1;
  }

  // We need to call this to set up global state for TensorFlow.
  tensorflow::port::InitMain(argv[0], &argc, &argv);
  if (argc > 1) {
    LOG(ERROR) << "Unknown argument " << argv[1] << "\n" << usage;
    return -1;
  }

  // Setup session
  tensorflow::SavedModelBundle bundle;
  std::vector<tensorflow::TensorInfo> input_info;
  std::vector<tensorflow::TensorInfo> output_info;
  TFTRT_ENSURE_OK(
      LoadModel(model_path, signature_key, &bundle, &input_info, &output_info));

  // TODO: Convert model w/ TRT and add flag for this behavior

  // Get device
  tensorflow::Device* device;
  tensorflow::DeviceContext* device_context;
  TFTRT_ENSURE_OK(GetDevice(bundle.session, &device, &device_context));

  // Create inputs and move to device
  // TODO: Measure H2D times over repeated calls and report metrics
  std::vector<Tensor> inputs_device;
  TFTRT_ENSURE_OK(SetupInputs(device, device_context, batch_size, input_info,
                              &inputs_device));

  // Configure to feed and fetch from device
  tensorflow::Session::CallableHandle handle;
  TFTRT_ENSURE_OK(SetupCallable(bundle.session, input_info, output_info,
                                device->name(), input_from_device, output_to_host, &handle));

  // Run benchmarking
  std::vector<Tensor> outputs;
  std::vector<double> infer_time;
  std::chrono::steady_clock::time_point eval_start_time;
  std::chrono::steady_clock::time_point start_time;
  std::chrono::steady_clock::time_point end_time;
  for (int i = 0; i < warmup_iters + eval_iters; i++) {
    if (i == warmup_iters) {
      LOG(INFO) << "Warmup done";
      eval_start_time = std::chrono::steady_clock::now();
    }

    start_time = std::chrono::steady_clock::now();
    TFTRT_ENSURE_OK(
        bundle.session->RunCallable(handle, inputs_device, &outputs, nullptr));
    // Sync, as `set_fetch_skip_sync(false)` is currently not implemented
    TFTRT_ENSURE_OK(device->Sync());
    end_time = std::chrono::steady_clock::now();

    double duration = (end_time - start_time).count() / 1e6;
    infer_time.push_back(duration);
  }
  TFTRT_ENSURE_OK(bundle.session->ReleaseCallable(handle));

  // Print results
  std::sort(infer_time.begin() + warmup_iters, infer_time.end());
  double total_compute_time =
      std::accumulate(infer_time.begin() + warmup_iters, infer_time.end(), 0.0);
  double total_wall_time = (end_time - eval_start_time).count() / 1e6;
  int32_t m = warmup_iters + eval_iters / 2;
  LOG(INFO) << "Total wall time (s): " << total_wall_time / 1e3;
  LOG(INFO) << "Total GPU compute time (s): " << total_compute_time / 1e3;
  LOG(INFO) << "Mean GPU compute time (ms): " << total_compute_time / eval_iters;
  LOG(INFO) << "Median GPU compute time (ms): " << (eval_iters % 2 ? infer_time[m]
                                                                   : (infer_time[m - 1] + infer_time[m]) / 2);
  // Note: Throughput using GPU inference time, rather than wall time
  LOG(INFO) << "Throughput (samples/s): " << 1e3 * eval_iters * batch_size / total_compute_time;
  LOG(INFO) << "Engine build time + first inference latency (ms): " << infer_time.front();

  return 0;
}<|endoftext|>


<commit_before>#ifndef TEN_WORK_DEQUE
#define TEN_WORK_DEQUE
#include "ten/optional.hh"
#include <memory>
#include <atomic>
#include <cmath>

// Chase/Lev work-stealing deque
// from Dynamic Circular Work-Stealing Deque
// http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.170.1097&rep=rep1&type=pdf
// and
// Correct and Efﬁcient Work-Stealing for Weak Memory Models
// http://www.di.ens.fr/~zappa/readings/ppopp13.pdf

namespace ten {

template <typename T>
class work_deque {
private:
    static size_t const     cacheline_size = 64;
    typedef char            cacheline_pad_t [cacheline_size];
    struct array;

    cacheline_pad_t pad0_;
    std::atomic<size_t> _top;
    std::atomic<size_t> _bottom;
    std::atomic<array *> _array;
    cacheline_pad_t pad1_;
public:
    work_deque(size_t size) : _top{0}, _bottom{0} {
        _array.store(new array{(size_t)std::log(size)});
    }

    ~work_deque() {
        delete _array.load();
    }

    // push_back
    void push(T x) {
        size_t b = _bottom.load(std::memory_order_relaxed);
        size_t t = _top.load(std::memory_order_acquire);
        array *a = _array.load(std::memory_order_relaxed);
        if (b - t > a->size() - 1) {
            a = a->grow(t, b).release();
            size_t ss = a->size();
            std::unique_ptr<array> old{_array.exchange(a)};
            _bottom.store(b + ss);
        }
        a->put(b, x);
        std::atomic_thread_fence(std::memory_order_release);
        _bottom.store(b + 1, std::memory_order_relaxed);
    }

    // pop_back
    optional<T> take() {
        size_t b = _bottom.load(std::memory_order_relaxed) - 1;
        array *a = _array.load(std::memory_order_relaxed);
        _bottom.store(b, std::memory_order_relaxed);
        std::atomic_thread_fence(std::memory_order_seq_cst);
        size_t t = _top.load(std::memory_order_relaxed);
        optional<T> x;
        if (t <= b) {
            // non-empty queue
            x = a->get(b);
            if (t == b) {
                // last element in queue
                if (!_top.compare_exchange_strong(t, t + 1,
                            std::memory_order_seq_cst, std::memory_order_relaxed)) {
                    // failed race
                    x = nullopt;
                }
                _bottom.store(b + 1, std::memory_order_relaxed);
            }
        } else {
            // empty queue
            //x = nullptr;
            _bottom.store(b + 1, std::memory_order_relaxed);
        }
        return x;
    }

    // pop_front
    // pair of
    //  bool success? - false means try again
    //  optional<T> item
    std::pair<bool, optional<T> > steal() {
        optional<T> x;
        size_t t = _top.load(std::memory_order_acquire);
        std::atomic_thread_fence(std::memory_order_seq_cst);
        array *old_a = _array.load(std::memory_order_relaxed);
        size_t b = _bottom.load(std::memory_order_acquire);
        array *a = _array.load(std::memory_order_relaxed);
        ssize_t size = b - t;
        if (size <= 0) {
            // empty
            return std::make_pair(true, x);
        }
        if ((size % a->size()) == 0) {
            if (a == old_a && t == _top.load(std::memory_order_relaxed)) {
                // empty
                return std::make_pair(true, x);
            } else {
                // abort, failed race
                return std::make_pair(false, nullopt);
            }

        }
        // non empty
        x = a->get(t);
        if (!_top.compare_exchange_strong(t, t + 1,
                    std::memory_order_seq_cst, std::memory_order_relaxed)) {
            // failed race
            return std::make_pair(false, nullopt);
        }
        return std::make_pair(true, x);
    }

private:
    struct array {
        size_t _size;
        std::atomic<T> * _buffer;

        array(size_t size) {
            _size = size;
            _buffer = new std::atomic<T>[this->size()];
        }

        ~array() {
            delete[] _buffer;
        }

        size_t size() const {
            return 1<<_size;
        }

        void put(size_t i, T v) {
            _buffer[i % size()].store(v, std::memory_order_relaxed);
        }

        T get(size_t i) const {
            return _buffer[i % size()].load(std::memory_order_relaxed);
        }

        std::unique_ptr<array> grow(size_t top, size_t bottom) {
            std::unique_ptr<array> a{new array{_size+1}};
            for (size_t i=top; i<bottom; ++i) {
                a->put(i, get(i));
            }
            return a;
        }
    };
};

} // namespace ten

#endif // TEN_WORK_DEQUE
<commit_msg>use only memory_order_seq_cst. attempt to fix race in array grow.<commit_after>#ifndef TEN_WORK_DEQUE
#define TEN_WORK_DEQUE
#include "ten/optional.hh"
#include <memory>
#include <atomic>
#include <cmath>

// Chase/Lev work-stealing deque
// from Dynamic Circular Work-Stealing Deque
// http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.170.1097&rep=rep1&type=pdf
// and
// Correct and Efﬁcient Work-Stealing for Weak Memory Models
// http://www.di.ens.fr/~zappa/readings/ppopp13.pdf

namespace ten {

template <typename T>
class work_deque {
private:
    static size_t const     cacheline_size = 64;
    typedef char            cacheline_pad_t [cacheline_size];
    struct array;

    cacheline_pad_t pad0_;
    std::atomic<size_t> _top;
    std::atomic<size_t> _bottom;
    std::atomic<array *> _array;
    cacheline_pad_t pad1_;
public:
    work_deque(size_t size) : _top{0}, _bottom{0} {
        _array.store(new array{(size_t)std::log(size)}, std::memory_order_seq_cst);
    }

    ~work_deque() {
        delete _array.load(std::memory_order_seq_cst);
    }

    // push_back
    void push(T x) {
        size_t b = _bottom.load(std::memory_order_seq_cst);
        size_t t = _top.load(std::memory_order_seq_cst);
        array *a = _array.load(std::memory_order_seq_cst);
        if (b - t > a->size() - 1) {
            a = a->grow(t, b).release();
            size_t ss = a->size();
            std::unique_ptr<array> old{_array.exchange(a, std::memory_order_seq_cst)};
            _bottom.store(b + ss, std::memory_order_seq_cst);
            t = _top.load(std::memory_order_seq_cst);
            if (!_top.compare_exchange_strong(t, t + ss,
                        std::memory_order_seq_cst, std::memory_order_seq_cst)) {
                _bottom.store(b, std::memory_order_seq_cst);
            }
            b = _bottom.load(std::memory_order_seq_cst);

        }
        a->put(b, x);
        _bottom.store(b + 1, std::memory_order_seq_cst);
    }

    // pop_back
    optional<T> take() {
        size_t b = _bottom.load(std::memory_order_seq_cst) - 1;
        array *a = _array.load(std::memory_order_seq_cst);
        _bottom.store(b, std::memory_order_release);
        size_t t = _top.load(std::memory_order_seq_cst);
        optional<T> x;
        if (t <= b) {
            // non-empty queue
            x = a->get(b);
            if (t == b) {
                // last element in queue
                if (!_top.compare_exchange_strong(t, t + 1,
                            std::memory_order_seq_cst, std::memory_order_seq_cst)) {
                    // failed race
                    x = nullopt;
                }
                _bottom.store(b + 1, std::memory_order_seq_cst);
            }
        } else {
            // empty queue
            //x = nullptr;
            _bottom.store(b + 1, std::memory_order_seq_cst);
        }
        return x;
    }

    // pop_front
    // pair of
    //  bool success? - false means try again
    //  optional<T> item
    std::pair<bool, optional<T> > steal() {
        optional<T> x;
        size_t t = _top.load(std::memory_order_seq_cst);
        array *old_a = _array.load(std::memory_order_seq_cst);
        size_t b = _bottom.load(std::memory_order_seq_cst);
        array *a = _array.load(std::memory_order_seq_cst);
        ssize_t size = b - t;
        if (size <= 0) {
            // empty
            return std::make_pair(true, x);
        }
        if ((size % a->size()) == 0) {
            if (a == old_a && t == _top.load(std::memory_order_seq_cst)) {
                // empty
                return std::make_pair(true, x);
            } else {
                // abort, failed race
                return std::make_pair(false, nullopt);
            }

        }
        // non empty
        x = a->get(t);
        if (!_top.compare_exchange_strong(t, t + 1,
                    std::memory_order_seq_cst, std::memory_order_seq_cst)) {
            // failed race
            return std::make_pair(false, nullopt);
        }
        return std::make_pair(true, x);
    }

private:
    struct array {
        size_t _size;
        std::atomic<T> * _buffer;

        array(size_t size) :
            _size{size},
            _buffer{new std::atomic<T>[this->size()]}
        {
        }

        ~array() {
            delete[] _buffer;
        }

        size_t size() const {
            return 1<<_size;
        }

        void put(size_t i, T v) {
            _buffer[i % size()].store(v, std::memory_order_seq_cst);
        }

        T get(size_t i) const {
            return _buffer[i % size()].load(std::memory_order_seq_cst);
        }

        std::unique_ptr<array> grow(size_t top, size_t bottom) {
            std::unique_ptr<array> a{new array{_size+1}};
            for (size_t i=top; i<bottom; ++i) {
                a->put(i, get(i));
            }
            return a;
        }
    };
};

} // namespace ten

#endif // TEN_WORK_DEQUE
<|endoftext|>


<commit_before>// Copyright Joshua Boyce 2010-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// This file is part of HadesMem.
// <http://www.raptorfactor.com/> <raptorfactor@raptorfactor.com>

#include "hadesmem/call.hpp"

#define BOOST_TEST_MODULE call
#include "hadesmem/detail/warning_disable_prefix.hpp"
#include <boost/test/unit_test.hpp>
#include "hadesmem/detail/warning_disable_suffix.hpp"

#include "hadesmem/error.hpp"
#include "hadesmem/process.hpp"

// Boost.Test causes the following warning under GCC:
// error: base class 'struct boost::unit_test::ut_detail::nil_t' has a
// non-virtual destructor [-Werror=effc++]
#if defined(HADESMEM_GCC)
#pragma GCC diagnostic ignored "-Weffc++"
#endif // #if defined(HADESMEM_GCC)

DWORD_PTR TestCall(void const* a, void const* b, unsigned int c,
  unsigned int d, unsigned int e, unsigned int f)
{
  BOOST_CHECK_EQUAL(a, static_cast<PVOID>(nullptr));
  BOOST_CHECK_EQUAL(b, reinterpret_cast<PVOID>(-1));
  BOOST_CHECK_EQUAL(c, static_cast<unsigned int>('c'));
  BOOST_CHECK_EQUAL(d, static_cast<unsigned int>(42));
  BOOST_CHECK_EQUAL(e, static_cast<unsigned int>(0xDEAFBEEF));
  BOOST_CHECK_EQUAL(f, static_cast<unsigned int>(0xBAADF00D));

  SetLastError(5678);
  return 1234;
}

DWORD64 TestCall64Ret()
{
  return 0x123456787654321LL;
}

#if defined(_M_AMD64)
#elif defined(_M_IX86)
DWORD_PTR __fastcall TestFastCall(void const* a, void const* b,
  unsigned int c, unsigned int d, unsigned int e, unsigned int f)
{
  BOOST_CHECK_EQUAL(a, static_cast<PVOID>(nullptr));
  BOOST_CHECK_EQUAL(b, reinterpret_cast<PVOID>(-1));
  BOOST_CHECK_EQUAL(c, static_cast<unsigned int>('c'));
  BOOST_CHECK_EQUAL(d, static_cast<unsigned int>(42));
  BOOST_CHECK_EQUAL(e, static_cast<unsigned int>(0xDEAFBEEF));
  BOOST_CHECK_EQUAL(f, static_cast<unsigned int>(0xBAADF00D));

  SetLastError(5678);
  return 1234;
}

DWORD_PTR __stdcall TestStdCall(void const* a, void const* b, unsigned int c,
  unsigned int d, unsigned int e, unsigned int f)
{
  BOOST_CHECK_EQUAL(a, static_cast<PVOID>(nullptr));
  BOOST_CHECK_EQUAL(b, reinterpret_cast<PVOID>(-1));
  BOOST_CHECK_EQUAL(c, static_cast<unsigned int>('c'));
  BOOST_CHECK_EQUAL(d, static_cast<unsigned int>(42));
  BOOST_CHECK_EQUAL(e, static_cast<unsigned int>(0xDEAFBEEF));
  BOOST_CHECK_EQUAL(f, static_cast<unsigned int>(0xBAADF00D));

  SetLastError(5678);
  return 1234;
}
#else
#error "[HadesMem] Unsupported architecture."
#endif

BOOST_AUTO_TEST_CASE(call)
{
  hadesmem::Process const process(::GetCurrentProcessId());

  struct ImplicitConvTest
  {
    operator int() const
    {
      return 42;
    }
  };

  typedef DWORD_PTR (*TestFuncT)(void const*, void const*, unsigned int,
    unsigned int, unsigned int, unsigned int);
  hadesmem::RemoteFunctionRet const CallRet = hadesmem::Call<TestFuncT>(
    process, reinterpret_cast<PVOID>(reinterpret_cast<DWORD_PTR>(&TestCall)),
    hadesmem::CallConv::kDefault, nullptr, reinterpret_cast<PVOID>(-1),
    'c', ImplicitConvTest(), 0xDEAFBEEF, 0xBAADF00D);
  BOOST_CHECK_EQUAL(CallRet.GetReturnValue(), static_cast<DWORD_PTR>(1234));
  BOOST_CHECK_EQUAL(CallRet.GetLastError(), static_cast<DWORD>(5678));

#if defined(_M_AMD64)
#elif defined(_M_IX86)
  hadesmem::RemoteFunctionRet const CallRetFast =
    hadesmem::Call<TestFuncT>(process, reinterpret_cast<PVOID>(
    reinterpret_cast<DWORD_PTR>(&TestFastCall)),
    hadesmem::CallConv::kFastCall, nullptr, reinterpret_cast<PVOID>(-1),
    'c', ImplicitConvTest(), 0xDEAFBEEF, 0xBAADF00D);
  BOOST_CHECK_EQUAL(CallRetFast.GetReturnValue(), static_cast<DWORD_PTR>(
    1234));
  BOOST_CHECK_EQUAL(CallRetFast.GetLastError(), static_cast<DWORD>(5678));

  hadesmem::RemoteFunctionRet const CallRetStd =
    hadesmem::Call<TestFuncT>(process, reinterpret_cast<PVOID>(
    reinterpret_cast<DWORD_PTR>(&TestStdCall)), hadesmem::CallConv::kStdCall,
    nullptr, reinterpret_cast<PVOID>(-1), 'c', ImplicitConvTest(), 0xDEAFBEEF,
    0xBAADF00D);
  BOOST_CHECK_EQUAL(CallRetStd.GetReturnValue(), static_cast<DWORD_PTR>(
    1234));
  BOOST_CHECK_EQUAL(CallRetStd.GetLastError(), static_cast<DWORD>(5678));
#else
#error "[HadesMem] Unsupported architecture."
#endif

  hadesmem::RemoteFunctionRet const CallRet64 = hadesmem::Call<DWORD64 (*)()>(
    process, reinterpret_cast<PVOID>(reinterpret_cast<DWORD_PTR>(
    &TestCall64Ret)), hadesmem::CallConv::kDefault);
  BOOST_CHECK_EQUAL(CallRet64.GetReturnValue64(), static_cast<DWORD64>(
    0x123456787654321LL));
}
<commit_msg>* Call test improvements.<commit_after>// Copyright Joshua Boyce 2010-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// This file is part of HadesMem.
// <http://www.raptorfactor.com/> <raptorfactor@raptorfactor.com>

#include "hadesmem/call.hpp"

#define BOOST_TEST_MODULE call
#include "hadesmem/detail/warning_disable_prefix.hpp"
#include <boost/test/unit_test.hpp>
#include "hadesmem/detail/warning_disable_suffix.hpp"

#include "hadesmem/error.hpp"
#include "hadesmem/process.hpp"

// Boost.Test causes the following warning under GCC:
// error: base class 'struct boost::unit_test::ut_detail::nil_t' has a
// non-virtual destructor [-Werror=effc++]
#if defined(HADESMEM_GCC)
#pragma GCC diagnostic ignored "-Weffc++"
#endif // #if defined(HADESMEM_GCC)

namespace
{

struct DummyType { };
DummyType dummy_glob;

}

DWORD_PTR TestCall(void const* a, DummyType const* b, char c,
  wchar_t d, int e, unsigned int f)
{
  BOOST_CHECK_EQUAL(a, static_cast<PVOID>(nullptr));
  BOOST_CHECK_EQUAL(b, &dummy_glob);
  BOOST_CHECK_EQUAL(c, 'c');
  BOOST_CHECK_EQUAL(d, L'd');
  BOOST_CHECK_EQUAL(e, -1234);
  BOOST_CHECK_EQUAL(f, static_cast<unsigned int>(0xDEAFBEEF));

  SetLastError(5678);
  return 1234;
}

DWORD64 TestCall64Ret()
{
  return 0x123456787654321LL;
}

#if defined(_M_AMD64)
#elif defined(_M_IX86)
DWORD_PTR __fastcall TestFastCall(void const* a, DummyType const* b, char c,
  wchar_t d, int e, unsigned int f)
{
  BOOST_CHECK_EQUAL(a, static_cast<PVOID>(nullptr));
  BOOST_CHECK_EQUAL(b, &dummy_glob);
  BOOST_CHECK_EQUAL(c, 'c');
  BOOST_CHECK_EQUAL(d, L'd');
  BOOST_CHECK_EQUAL(e, -1234);
  BOOST_CHECK_EQUAL(f, static_cast<unsigned int>(0xDEAFBEEF));

  SetLastError(5678);
  return 1234;
}

DWORD_PTR __stdcall TestStdCall(void const* a, DummyType const* b, char c,
  wchar_t d, int e, unsigned int f)
{
  BOOST_CHECK_EQUAL(a, static_cast<PVOID>(nullptr));
  BOOST_CHECK_EQUAL(b, &dummy_glob);
  BOOST_CHECK_EQUAL(c, 'c');
  BOOST_CHECK_EQUAL(d, L'd');
  BOOST_CHECK_EQUAL(e, -1234);
  BOOST_CHECK_EQUAL(f, static_cast<unsigned int>(0xDEAFBEEF));

  SetLastError(5678);
  return 1234;
}
#else
#error "[HadesMem] Unsupported architecture."
#endif

BOOST_AUTO_TEST_CASE(call)
{
  hadesmem::Process const process(::GetCurrentProcessId());

  struct ImplicitConvTest
  {
    operator int() const
    {
      return -1234;
    }
  };

  typedef DWORD_PTR (*TestFuncT)(void const* a, DummyType const* b, char c,
  wchar_t d, int e, unsigned int f);
  hadesmem::RemoteFunctionRet const CallRet = hadesmem::Call<TestFuncT>(
    process, reinterpret_cast<PVOID>(reinterpret_cast<DWORD_PTR>(&TestCall)),
    hadesmem::CallConv::kDefault, nullptr, &dummy_glob, 'c', L'd',
    ImplicitConvTest(), 0xDEAFBEEF);
  BOOST_CHECK_EQUAL(CallRet.GetReturnValue(), static_cast<DWORD_PTR>(1234));
  BOOST_CHECK_EQUAL(CallRet.GetLastError(), static_cast<DWORD>(5678));

#if defined(_M_AMD64)
#elif defined(_M_IX86)
  hadesmem::RemoteFunctionRet const CallRetFast =
    hadesmem::Call<TestFuncT>(process, reinterpret_cast<PVOID>(
    reinterpret_cast<DWORD_PTR>(&TestFastCall)),
    hadesmem::CallConv::kFastCall, nullptr, &dummy_glob, 'c', L'd',
    ImplicitConvTest(), 0xDEAFBEEF);
  BOOST_CHECK_EQUAL(CallRetFast.GetReturnValue(), static_cast<DWORD_PTR>(
    1234));
  BOOST_CHECK_EQUAL(CallRetFast.GetLastError(), static_cast<DWORD>(5678));

  hadesmem::RemoteFunctionRet const CallRetStd =
    hadesmem::Call<TestFuncT>(process, reinterpret_cast<PVOID>(
    reinterpret_cast<DWORD_PTR>(&TestStdCall)), hadesmem::CallConv::kStdCall,
    nullptr, &dummy_glob, 'c', L'd', ImplicitConvTest(), 0xDEAFBEEF);
  BOOST_CHECK_EQUAL(CallRetStd.GetReturnValue(), static_cast<DWORD_PTR>(
    1234));
  BOOST_CHECK_EQUAL(CallRetStd.GetLastError(), static_cast<DWORD>(5678));
#else
#error "[HadesMem] Unsupported architecture."
#endif

  hadesmem::RemoteFunctionRet const CallRet64 = hadesmem::Call<DWORD64 (*)()>(
    process, reinterpret_cast<PVOID>(reinterpret_cast<DWORD_PTR>(
    &TestCall64Ret)), hadesmem::CallConv::kDefault);
  BOOST_CHECK_EQUAL(CallRet64.GetReturnValue64(), static_cast<DWORD64>(
    0x123456787654321LL));
}
<|endoftext|>


<commit_before>// vim:cindent:cino=\:0:et:fenc=utf-8:ff=unix:sw=4:ts=4:

#include <sstream>
#include <string>
#include <stdexcept>
#include <QtGlobal>

#include <conveyor/address.h>
#include <conveyor/pipeaddress.h>
#include <conveyor/tcpaddress.h>
#include <conveyor/exceptions.h>

namespace
{
    conveyor::TcpAddress DefaultTcpAddress ("localhost", 9999);

    conveyor::PipeAddress DefaultPipeAddress
        ( "/var/run/conveyord/conveyord.socket"
        );

    static
    conveyor::Address *
    parseTcpAddress (std::string const & hostport)
    {
        std::string::size_type const colon (hostport.find (":"));
        if (std::string::npos == colon)
        {
            throw std::exception ();
        }
        else
        {
            std::string const host (hostport.substr (0, colon));
            std::istringstream stream (hostport.substr (colon + 1));
            int port;
            stream >> port;
            if (stream.bad () or stream.fail ())
            {
                throw std::runtime_error ("Error writing to string stream");
            }
            else
            {
                conveyor::Address * const address
                    ( new conveyor::TcpAddress (host, port)
                    );
                return address;
            }
        }
    }

    static
    conveyor::Address *
    parsePipeAddress (std::string const & path)
    {
        conveyor::Address * const address (new conveyor::PipeAddress (path));
        return address;
    }
}

namespace conveyor
{
    Address *
    Address::defaultAddress()
    {
#if defined (CONVEYOR_ADDRESS)
        return CONVEYOR_ADDRESS;
#elif defined (Q_OS_LINUX) || defined (Q_OS_MAC)
        return & DefaultPipeAddress;
#elif defined (Q_OS_WIN32)
        return & DefaultTcpAddress;
#else
# error No CONVEYOR_ADDRESS defined and no default location known for this platform
#endif
    }

    Address *
    Address::parse (std::string const & str)
    {
        try
        {
            Address * address;
            if ("tcp:" == str.substr (0, 4))
            {
                address = parseTcpAddress (str.substr (4));
            }
            else
            if (("pipe:" == str.substr (0, 5))
                or ("unix:" == str.substr (0, 5)))
            {
                address = parsePipeAddress (str.substr (5));
            }
            else
            {
                throw InvalidAddressError(str);
            }
            return address;
        }
        catch (std::out_of_range const & exception)
        {
            throw std::exception ();
        }
    }

    Address::~Address (void)
    {
    }
}
<commit_msg>Make location of unix domain socket consistent with the python default<commit_after>// vim:cindent:cino=\:0:et:fenc=utf-8:ff=unix:sw=4:ts=4:

#include <sstream>
#include <string>
#include <stdexcept>
#include <QtGlobal>

#include <conveyor/address.h>
#include <conveyor/pipeaddress.h>
#include <conveyor/tcpaddress.h>
#include <conveyor/exceptions.h>

namespace
{
    conveyor::TcpAddress DefaultTcpAddress ("localhost", 9999);

    conveyor::PipeAddress DefaultPipeAddress
        ( "/var/run/conveyor/conveyord.socket"
        );

    static
    conveyor::Address *
    parseTcpAddress (std::string const & hostport)
    {
        std::string::size_type const colon (hostport.find (":"));
        if (std::string::npos == colon)
        {
            throw std::exception ();
        }
        else
        {
            std::string const host (hostport.substr (0, colon));
            std::istringstream stream (hostport.substr (colon + 1));
            int port;
            stream >> port;
            if (stream.bad () or stream.fail ())
            {
                throw std::runtime_error ("Error writing to string stream");
            }
            else
            {
                conveyor::Address * const address
                    ( new conveyor::TcpAddress (host, port)
                    );
                return address;
            }
        }
    }

    static
    conveyor::Address *
    parsePipeAddress (std::string const & path)
    {
        conveyor::Address * const address (new conveyor::PipeAddress (path));
        return address;
    }
}

namespace conveyor
{
    Address *
    Address::defaultAddress()
    {
#if defined (CONVEYOR_ADDRESS)
        return CONVEYOR_ADDRESS;
#elif defined (Q_OS_LINUX) || defined (Q_OS_MAC)
        return & DefaultPipeAddress;
#elif defined (Q_OS_WIN32)
        return & DefaultTcpAddress;
#else
# error No CONVEYOR_ADDRESS defined and no default location known for this platform
#endif
    }

    Address *
    Address::parse (std::string const & str)
    {
        try
        {
            Address * address;
            if ("tcp:" == str.substr (0, 4))
            {
                address = parseTcpAddress (str.substr (4));
            }
            else
            if (("pipe:" == str.substr (0, 5))
                or ("unix:" == str.substr (0, 5)))
            {
                address = parsePipeAddress (str.substr (5));
            }
            else
            {
                throw InvalidAddressError(str);
            }
            return address;
        }
        catch (std::out_of_range const & exception)
        {
            throw std::exception ();
        }
    }

    Address::~Address (void)
    {
    }
}
<|endoftext|>