<commit_before>
#include <pthread.h>
#include <iostream>

struct subArys{
  int** ary11;
  int** ary12;
  int** ary21;
  int** ary22;
  int n;
};

struct multArgs{
  int** c;
  int** a;
  int** b;
  int n;

  public:
    multArgs(int** c_, int** a_, int** b_, int n_){
      c=c_;
      a=a_;
      b=b_;
      n=n_;
    }
};

struct addArgs{
  int**c;
  int**t;
  int n;

  public:
    addArgs(int** c_, int** t_, int n_){
      c=c_;
      t=t_;
      n=n_;
    }
};

void *multMtx(void*);
void *addMtx(void*);
int** newAry(int);
subArys* split(int**, int);
void printAry(int**, int);

void testSplit(int);
void testAdd();

using namespace std;

int main(){
  testSplit(4);
  testAdd();

    return 0;
}

void *multMtx(void* param){
	  multArgs* par = (multArgs*) param;
	  int ** tt = newAry(par->n); //create empty array
	if(par->n == 1){
	  par->c[0][0] = par->a[0][0] * par->b[0][0];
	  //need to bundle for return here
	}
	else{

	  subArys* a = split(par->a, par->n); //aplit arrays
	  subArys* b = split(par->b, par->n);
	  subArys* c = split(par->c, par->n);
	  subArys* t = split(tt, par->n);
	  //package all params
	  multArgs* param1 = new multArgs(c->ary11, a->ary11, b->ary11, t->n);
	  multArgs* param2 = new multArgs(c->ary12, a->ary11, b->ary12, t->n);
	  multArgs* param3 = new multArgs(c->ary21, a->ary21, b->ary11, t->n);
	  multArgs* param4 = new multArgs(c->ary22, a->ary21, b->ary12, t->n);
	  multArgs* param5 = new multArgs(t->ary11, a->ary12, b->ary22, t->n);
	  multArgs* param6 = new multArgs(t->ary12, a->ary12, b->ary22, t->n);
	  multArgs* param7 = new multArgs(t->ary21, a->ary22, b->ary21, t->n);
	  multArgs* param8 = new multArgs(t->ary22, a->ary22, b->ary22, t->n);
	  pthread_t m1, m2, m3, m4, m5, m6, m7, m8;
	  pthread_create(&m1, NULL, multMtx, (void*) param1);
	  //add and bundle for return here
	}

	delete tt;

}

void *addMtx(void* param) {
	addArgs* par = (addArgs*) param;

	if(par->n==1){
	  par->c[0][0]+=par->t[0][0];

	}
	else{
	  subArys* c = split(par->c, par->n);
	  subArys* t = split(par->t, par->n);

	  addArgs* param1 = new addArgs(c->ary11, t->ary11, t->n);
	  addArgs* param2 = new addArgs(c->ary12, t->ary12, t->n);
	  addArgs* param3 = new addArgs(c->ary21, t->ary21, t->n);
	  addArgs* param4 = new addArgs(c->ary22, t->ary22, t->n);
	  pthread_t m1,m2, m3, m4;
	  pthread_t threads[4]={m1, m2, m3, m4};

	  pthread_create(&m1, NULL, addMtx, (void*) param1);
	  pthread_create(&m2, NULL, addMtx, (void*) param2);
	  pthread_create(&m3, NULL, addMtx, (void*) param3);
	  pthread_create(&m4, NULL, addMtx, (void*) param4);

	  //thread syntax is all over the place and looks like a toddler threw up in my code
	  pthread_join(m1,NULL);
	  pthread_join(m2,NULL);
	  pthread_join(m3,NULL);
	  pthread_join(m4,NULL);
	}
}

int** newAry(int n){
  int** temp = new int*[n]; //outer array for poitners
  for(int i=0;i<n;++i){
   temp[i]=new int[n]; //inner 1d arrays of int*
   for(int j=0;j<n;++j){
     temp[i][j]= 0;
   }
  }
  return temp;
}

subArys* split(int** ary, int n){
 subArys* temp = new subArys;

 temp->ary11 = newAry(n/2); //define all initial vals
 temp->ary12 = newAry(n/2);
 temp->ary21 = newAry(n/2);
 temp->ary22 = newAry(n/2);
 temp->n = n/2;
 int shift=n/2;

 for(int i=0;i<n;++i){ //loop through original and push to correct quad

   if(i<n/2){
     temp->ary11[i]=&ary[i][0];
     temp->ary12[i]=&ary[i][n/shift];
   }
   else{
    temp->ary21[i%shift]=&ary[i][0];
    temp->ary22[i%shift]=&ary[i][n/shift];
   }
 }
  if(n==2){//shitty edge case
    temp->ary12[0]=&ary[0][1];
    temp->ary22[0]=&ary[1][1];
  }
   return temp;
}

void testSplit(int n){
  int** ptr=newAry(n);
  cout<<"*** Start Split Test ***\n";
  cout<<"parent matrix to be split\n";
  for(int i=0;i<n;++i){
    for(int j=0;j<n;++j){
      ptr[i][j]=(i*10)+j+1; //asign values to location pointed to
      cout<<ptr[i][j]<<" ";
    }
    cout<<endl;
  }
  cout<<endl;

  subArys* test=split(ptr, n);
  n=test->n;

  cout<<"top left quad, ary11\n";
  for(int i=0;i<n;++i){
    for(int j=0;j<n;++j){
      ptr[i][j]=(i*10)+j+1;
      cout<<test->ary11[i][j]<<" ";
    }
    cout<<endl;
  }

  cout<<"top right quad, ary12\n";
  for(int i=0;i<n;++i){
    for(int j=0;j<n;++j){
      ptr[i][j]=(i*10)+j+1;
      cout<<test->ary12[i][j]<<" ";
    }
    cout<<endl;
  }

  cout<<"bottom left quad, ary21\n";
  for(int i=0;i<n;++i){
    for(int j=0;j<n;++j){
      ptr[i][j]=(i*10)+j+1;
      cout<<test->ary21[i][j]<<" ";
    }
    cout<<endl;
  }

  cout<<"bottom right quad, ary22\n";
  for(int i=0;i<n;++i){
    for(int j=0;j<n;++j){
      ptr[i][j]=(i*10)+j+1;
      cout<<test->ary22[i][j]<<" ";
    }
    cout<<endl;
  }
  cout<<"*** End Split Test ***\n";
}

void testAdd(){
  int n=2;
  int** subA = newAry(n);
  int** subB = newAry(n);

  cout<<"*** Start Add Test ***\n";
  for(int i=0;i<n;++i){
      for(int j=0;j<n;++j){
	subA[i][j]=(i*2)+j;
	subB[i][j]=(i*2)+j;
      }
    }
  printAry(subA, n);
  printAry(subB, n);

  addArgs* package = new addArgs(subA, subB, n);

  addMtx((void*)package);

  printAry(subA, 2);
  printAry(subB, 2);

  cout<<"*** End Add Test ***\n";

}

void printAry(int ** ary, int n){
    for(int i=0;i<n;++i){
      for(int j=0;j<n;++j){
	cout<<ary[i][j]<<" ";
      }
      cout<<endl;
    }
    cout<<endl;
}
<commit_msg>fixed Mult seg fault<commit_after>
#include <pthread.h>
#include <iostream>

struct subArys{
  int** ary11;
  int** ary12;
  int** ary21;
  int** ary22;
  int n;
};

struct multArgs{
  int** c;
  int** a;
  int** b;
  int n;

  public:
    multArgs(int** c_, int** a_, int** b_, int n_){
      c=c_;
      a=a_;
      b=b_;
      n=n_;
    }
};

struct addArgs{
  int**c;
  int**t;
  int n;

  public:
    addArgs(int** c_, int** t_, int n_){
      c=c_;
      t=t_;
      n=n_;
    }
};

void *multMtx(void*);
void *addMtx(void*);
int** newAry(int);
subArys* split(int**, int);
void printAry(int**, int);

void testSplit(int);
void testAdd();
void testMult();

using namespace std;

int main(){
 // testSplit(4);
 // testAdd();
  testMult();

    return 0;
}

void *multMtx(void* param){
	  multArgs* par = (multArgs*) param;
	  int ** tt = newAry(par->n); //create empty array
	if(par->n == 1){
	  par->c[0][0] = par->a[0][0] * par->b[0][0];
	}
	else{

	  subArys* a = split(par->a, par->n); //aplit arrays
	  subArys* b = split(par->b, par->n);
	  subArys* c = split(par->c, par->n);
	  subArys* t = split(tt, par->n);
	  cout<<"par length: "<<par->n<<endl;
	  cout<<"a length: "<<a->n<<endl;
	  //package all params
	  multArgs* param1 = new multArgs(c->ary11, a->ary11, b->ary11, t->n);
	  multArgs* param2 = new multArgs(c->ary12, a->ary11, b->ary12, t->n);
	  multArgs* param3 = new multArgs(c->ary21, a->ary21, b->ary11, t->n);
	  multArgs* param4 = new multArgs(c->ary22, a->ary21, b->ary12, t->n);
	  multArgs* param5 = new multArgs(t->ary11, a->ary12, b->ary21, t->n);
	  multArgs* param6 = new multArgs(t->ary12, a->ary12, b->ary22, t->n);
	  multArgs* param7 = new multArgs(t->ary21, a->ary22, b->ary21, t->n);
	  multArgs* param8 = new multArgs(t->ary22, a->ary22, b->ary22, t->n);
	  pthread_t m1, m2, m3, m4, m5, m6, m7, m8;
	  //threads run rampent
	  pthread_create(&m1, NULL, multMtx, (void*) param1);
	  pthread_create(&m2, NULL, multMtx, (void*) param2);
	  pthread_create(&m3, NULL, multMtx, (void*) param3);
	  pthread_create(&m4, NULL, multMtx, (void*) param4);
	  pthread_create(&m5, NULL, multMtx, (void*) param5);
	  pthread_create(&m6, NULL, multMtx, (void*) param6);
	  pthread_create(&m7, NULL, multMtx, (void*) param7);
	  pthread_create(&m8, NULL, multMtx, (void*) param8);
	  //bring them home
	  pthread_join(m1,NULL);
	  pthread_join(m2,NULL);
	  pthread_join(m3,NULL);
	  pthread_join(m4,NULL);
	  pthread_join(m5,NULL);
	  pthread_join(m6,NULL);
	  pthread_join(m7,NULL);
	  pthread_join(m8,NULL);

	}

	delete tt;

}

void *addMtx(void* param) {
	addArgs* par = (addArgs*) param;

	if(par->n==1){
	  par->c[0][0]+=par->t[0][0];

	}
	else{
	  subArys* c = split(par->c, par->n);
	  subArys* t = split(par->t, par->n);

	  addArgs* param1 = new addArgs(c->ary11, t->ary11, t->n);
	  addArgs* param2 = new addArgs(c->ary12, t->ary12, t->n);
	  addArgs* param3 = new addArgs(c->ary21, t->ary21, t->n);
	  addArgs* param4 = new addArgs(c->ary22, t->ary22, t->n);
	  pthread_t m1,m2, m3, m4;
	  pthread_t threads[4]={m1, m2, m3, m4};

	  pthread_create(&m1, NULL, addMtx, (void*) param1);
	  pthread_create(&m2, NULL, addMtx, (void*) param2);
	  pthread_create(&m3, NULL, addMtx, (void*) param3);
	  pthread_create(&m4, NULL, addMtx, (void*) param4);

	  //thread syntax is all over the place and looks like a toddler threw up in my code
	  pthread_join(m1,NULL);
	  pthread_join(m2,NULL);
	  pthread_join(m3,NULL);
	  pthread_join(m4,NULL);
	}
}

int** newAry(int n){
  int** temp = new int*[n]; //outer array for poitners
  for(int i=0;i<n;++i){
   temp[i]=new int[n]; //inner 1d arrays of int*
   for(int j=0;j<n;++j){
     temp[i][j]= 0;
   }
  }
  return temp;
}

subArys* split(int** ary, int n){
 subArys* temp = new subArys;

 temp->ary11 = newAry(n/2); //define all initial vals
 temp->ary12 = newAry(n/2);
 temp->ary21 = newAry(n/2);
 temp->ary22 = newAry(n/2);
 temp->n = n/2;
 int shift=n/2;

 for(int i=0;i<n;++i){ //loop through original and push to correct quad

   if(i<n/2){
     temp->ary11[i]=&ary[i][0];
     temp->ary12[i]=&ary[i][n/shift];
   }
   else{
    temp->ary21[i%shift]=&ary[i][0];
    temp->ary22[i%shift]=&ary[i][n/shift];
   }
 }
  if(n==2){//shitty edge case
    temp->ary12[0]=&ary[0][1];
    temp->ary22[0]=&ary[1][1];
  }
   return temp;
}

void testSplit(int n){
  int** ptr=newAry(n);
  cout<<"*** Start Split Test ***\n";
  cout<<"parent matrix to be split\n";
  for(int i=0;i<n;++i){
    for(int j=0;j<n;++j){
      ptr[i][j]=(i*10)+j+1; //asign values to location pointed to
      cout<<ptr[i][j]<<" ";
    }
    cout<<endl;
  }
  cout<<endl;

  subArys* test=split(ptr, n);
  n=test->n;

  cout<<"top left quad, ary11\n";
  for(int i=0;i<n;++i){
    for(int j=0;j<n;++j){
      ptr[i][j]=(i*10)+j+1;
      cout<<test->ary11[i][j]<<" ";
    }
    cout<<endl;
  }

  cout<<"top right quad, ary12\n";
  for(int i=0;i<n;++i){
    for(int j=0;j<n;++j){
      ptr[i][j]=(i*10)+j+1;
      cout<<test->ary12[i][j]<<" ";
    }
    cout<<endl;
  }

  cout<<"bottom left quad, ary21\n";
  for(int i=0;i<n;++i){
    for(int j=0;j<n;++j){
      ptr[i][j]=(i*10)+j+1;
      cout<<test->ary21[i][j]<<" ";
    }
    cout<<endl;
  }

  cout<<"bottom right quad, ary22\n";
  for(int i=0;i<n;++i){
    for(int j=0;j<n;++j){
      ptr[i][j]=(i*10)+j+1;
      cout<<test->ary22[i][j]<<" ";
    }
    cout<<endl;
  }
  cout<<"*** End Split Test ***\n";
}

void testAdd(){
  int n=2;
  int** subA = newAry(n);
  int** subB = newAry(n);

  cout<<"*** Start Add Test ***\n";
  for(int i=0;i<n;++i){
      for(int j=0;j<n;++j){
	subA[i][j]=(i*2)+j;
	subB[i][j]=(i*2)+j;
      }
    }
  cout<<"array A before\n";
  printAry(subA, n);
  cout<<"array B before\n";
  printAry(subB, n);

  addArgs* package = new addArgs(subA, subB, n);

  addMtx((void*)package);

  cout<<"array A after\n";
  printAry(subA, 2);
  cout<<"array B after\n";
  printAry(subB, 2);

  cout<<"*** End Add Test ***\n";

}

void testMult(){
 int n=2;
  int** subA = newAry(n);
  int** subB = newAry(n);
  int** subC = newAry(n);

  cout<<"*** Start Mult Test ***\n";
  for(int i=0;i<n;++i){
      for(int j=0;j<n;++j){
	subA[i][j]=(i*2)+j;
	subB[i][j]=(i*2)+j;
      }
    }

  cout<<"array A before\n";
  printAry(subA, n);
  cout<<"array B before\n";
  printAry(subB, n);
  cout<<"answer array C before\n";
  printAry(subC, n);

  multArgs* package = new multArgs(subC, subA, subB, n);

  multMtx((void*)package);

  cout<<"array A after\n";
  printAry(subA, 2);
  cout<<"array B after\n";
  printAry(subB, 2);
  cout<<"answer array C after\n";
  printAry(subC, n);
  cout<<"should be\n2 3\n6 11\n";

  cout<<"*** End Mult Test ***\n";
}

void printAry(int ** ary, int n){
    for(int i=0;i<n;++i){
      for(int j=0;j<n;++j){
	cout<<ary[i][j]<<" ";
      }
      cout<<endl;
    }
    cout<<endl;
}
<|endoftext|>


<commit_before>#define SYS_CLOCK_GETTIME 263
#include "linux_clock.cpp"
<commit_msg>Fix a syscall number for 64-bit arm<commit_after>#ifdef BITS_64
#define SYS_CLOCK_GETTIME 113
#endif

#ifdef BITS_32
#define SYS_CLOCK_GETTIME 263
#endif

#include "linux_clock.cpp"
<|endoftext|>


<commit_before>/*****************************************************************************
 *  Copyright (C) 2008-2011 Massachusetts Institute of Technology            *
 *                                                                           *
 *  Permission is hereby granted, free of charge, to any person obtaining    *
 *  a copy of this software and associated documentation files (the          *
 *  "Software"), to deal in the Software without restriction, including      *
 *  without limitation the rights to use, copy, modify, merge, publish,      *
 *  distribute, sublicense, and/or sell copies of the Software, and to       *
 *  permit persons to whom the Software is furnished to do so, subject       *
 *  to the following conditions:                                             *
 *                                                                           *
 *  The above copyright notice and this permission notice shall be included  *
 *  in all copies or substantial portions of the Software.                   *
 *                                                                           *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY                *
 *  KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE               *
 *  WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND      *
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE   *
 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION   *
 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION    *
 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE           *
 *                                                                           *
 *  This source code is part of the PetaBricks project:                      *
 *    http://projects.csail.mit.edu/petabricks/                              *
 *                                                                           *
 *****************************************************************************/
#include "testisolation.h"
#include "dynamicscheduler.h"
#include "gpumanager.h"

#include <limits>
#include <string.h>

#include "petabricksruntime.h"

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif

// annoyingly lapack returns 0 when it aborts, so we use a "secret" rv here
#define SUCCESS_RV 198
#define RUNNING_RV -257
#define CRASH_RV 666

static void _settestprocflags(){
#ifdef HAVE_SYS_PRCTL_H
# ifdef PR_SET_PDEATHSIG //linux 2.1.57
  //automatically kill us when parent dies
  JWARNING(prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0)==0);
# endif
# ifdef PR_GET_NAME //linux 2.6.11 (PR_SET_NAME 2.6.9)
  //append "(timing)" to our process name
  char buf[128];//spec says 16 is big enough
  memset(buf, 0, sizeof buf);
  prctl(PR_GET_NAME, buf, 0, 0, 0);
  strncpy(buf+strlen(buf), "(timing)", sizeof(buf)-strlen(buf)-1);
  prctl(PR_SET_NAME, buf, 0, 0, 0);
# endif
#endif
}

//keep these 1 char long: (all must be same size)
static const char COOKIE_DONE[] = "D";
static const char COOKIE_DISABLETIMEOUT[] = "E";
static const char COOKIE_RESTARTTIMEOUT[] = "R";
JASSERT_STATIC(sizeof COOKIE_DONE == sizeof COOKIE_DISABLETIMEOUT);
JASSERT_STATIC(sizeof COOKIE_DONE == sizeof COOKIE_RESTARTTIMEOUT);

petabricks::SubprocessTestIsolation::SubprocessTestIsolation(double to)
  : _pid(-1), _fd(-1), _rv(RUNNING_RV), _timeout(to), _timeoutEnabled(false), _start(jalib::JTime::null())
{
  if(_timeout < std::numeric_limits<double>::max()-TIMEOUT_GRACESEC)
    _timeout += TIMEOUT_GRACESEC;
}

void petabricks::SubprocessTestIsolation::onTunableModification(jalib::JTunable* t, jalib::TunableValue, jalib::TunableValue newVal){
  _modifications.push_back(TunableMod(t,newVal));
}

petabricks::TestIsolation* theMasterProcess = NULL;
petabricks::TestIsolation* petabricks::SubprocessTestIsolation::masterProcess() {
  return theMasterProcess;
}

bool petabricks::SubprocessTestIsolation::beginTest(int workerThreads, int reexecchild) {
  JASSERT(theMasterProcess==NULL);
  _modifications.clear();
#ifdef HAVE_OPENCL
  GpuManager::shutdown();
#endif
  DynamicScheduler::cpuScheduler().shutdown();
  int fds[2];
  //JASSERT(pipe(fds) == 0);
  if(reexecchild<0)  {
    JASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
    JASSERT((_pid=fork()) >=0);
  }else{
    _pid=0;
  }
  if(_pid>0){
    //parent
    _fd=fds[0];
    close(fds[1]);
    _rv = RUNNING_RV;
    _timeoutEnabled = false;
    _start = jalib::JTime::now();
    //JTRACE("parent");
    return false;
  }else{
    //child
    //JTRACE("child")(reexecchild);
    if(reexecchild<0) {
      _fd=fds[1];
      close(fds[0]);
      PetabricksRuntime::reexecTestIsolation(fds[1]);
    }else{
      _fd = reexecchild;
    }
    GpuManager::start();
    _settestprocflags();
    PetabricksRuntime::startWorkerThreads(workerThreads);
    jalib::JTunable::setModificationCallback(this);
    theMasterProcess=this;
    //JTRACE("child starting");
    restartTimeout();
    return true;
  }
}

void petabricks::SubprocessTestIsolation::disableTimeout() {
  JASSERT(write(_fd, COOKIE_DISABLETIMEOUT, strlen(COOKIE_DISABLETIMEOUT))>0)(JASSERT_ERRNO);
  fsync(_fd);
}

void petabricks::SubprocessTestIsolation::restartTimeout() {
  JASSERT(write(_fd, COOKIE_RESTARTTIMEOUT, strlen(COOKIE_RESTARTTIMEOUT))>0)(JASSERT_ERRNO);
  fsync(_fd);
}

void petabricks::SubprocessTestIsolation::endTest(TestResult& result) {
  JASSERT(_pid==0);
  JASSERT(write(_fd, COOKIE_DONE, strlen(COOKIE_DONE))>0)(JASSERT_ERRNO);
  jalib::JBinarySerializeWriterRaw o("pipe", _fd);
  o.serialize(result.time);
  o.serialize(result.accuracy);
  o & result.hash;
  o.serializeVector(_modifications);
  fflush(NULL);
  fsync(_fd);
  fsync(fileno(stdout));
  fsync(fileno(stderr));
  //GpuManager::shutdown();
  //DynamicScheduler::cpuScheduler().shutdown();
  _exit(SUCCESS_RV);
}

inline static void _settimeout(struct timespec& timeout, double sec){
  if(sec >= std::numeric_limits<long>::max()){
    timeout.tv_sec=std::numeric_limits<long>::max();
    timeout.tv_nsec=0;
  }else{
    timeout.tv_sec = (long)sec;
    timeout.tv_nsec = (long)((sec-(double)timeout.tv_sec)*1.0e9);
  }
}

inline static void _settimeout(int& timeout, double sec){
  if(sec >= std::numeric_limits<int>::max()/1000-1){
    timeout = -1;
  }else{
    timeout = (int)(sec*1000.0 + 0.5);
  }
}

void petabricks::SubprocessTestIsolation::recvResult(TestResult& result) {
  TimeoutT timeout;
  int ready;
  _settimeout(timeout, std::numeric_limits<int>::max());

  struct pollfd fds[1];
  fds[0].fd = _fd;
  fds[0].events = POLLIN;
  fds[0].revents = 0;

  for(;;){
    _settimeout(timeout, timeleft());
    //JTRACE("timeout")(timeout);
    ready = poll(fds, sizeof(fds)/sizeof(struct pollfd), timeout);
    JASSERT(ready>=0)(ready);

    if(ready==0){ //timeout
      killChild();
      break;
    }

    if(handleEvent(result)){
      break;
    }
  }
}

void petabricks::SubprocessTestIsolation::recvFirstResult(SubprocessTestIsolation& a, TestResult& aresult,
                                                          SubprocessTestIsolation& b, TestResult& bresult) {
  struct pollfd fds[2];
  struct pollfd* pfds = fds;
  bool adone = false;
  bool bdone = false;
  int nfds = 2;
  fds[0].fd = a._fd;
  fds[0].events = POLLIN;
  fds[0].revents = 0;
  fds[1].fd = b._fd;
  fds[1].events = POLLIN;
  fds[1].revents = 0;

  for(;;){
    int ready = 0;
    double secleft = std::max(0.0, std::max(a.timeleft(), b.timeleft()));
    TimeoutT timeout;
    _settimeout(timeout, secleft);
    ready = poll(pfds, nfds, timeout);
    JASSERT(ready>=0)(ready);

    if(ready==0){ //timeout
      a.killChild();
      b.killChild();
      break;
    }

    try {
      adone = adone || ((fds[0].revents&POLLIN)!=0 && a.handleEvent(aresult));
    } catch(UnknownTestFailure e) {
      adone = true;
    }
    try {
      bdone = bdone || ((fds[1].revents&POLLIN)!=0 && b.handleEvent(bresult));
    } catch(UnknownTestFailure e) {
      bdone = true;
    }
    if(adone) {
      fds[0].revents = 0;
      pfds = fds+1;
      nfds = 1;
      b._timeout = PetabricksRuntime::updateRaceTimeout(aresult, 0);
    }else if(bdone) {
      fds[1].revents = 0;
      pfds = fds;
      nfds = 1;
      a._timeout = PetabricksRuntime::updateRaceTimeout(bresult, 1);
    }
    if(adone && bdone) break;
  }
}

double petabricks::SubprocessTestIsolation::timeleft() const {
  if(!running())
      return 0;
  if(_timeoutEnabled)
    return _timeout - (jalib::JTime::now() - _start) + 0.02;
  return std::numeric_limits<double>::max();
}

bool petabricks::SubprocessTestIsolation::handleEvent(TestResult& result) {
  //receive a control code
  std::string cnt = recvControlCookie();

  //check control code:
  if(cnt==COOKIE_DISABLETIMEOUT){
    _timeoutEnabled = false;
    return false;
  }
  if(cnt==COOKIE_RESTARTTIMEOUT){
    _timeoutEnabled = true;
    _start = jalib::JTime::now();
    return false;
  }
  if(cnt!=COOKIE_DONE || (!running() && rv()!=SUCCESS_RV )){
    //unknown control code, most likely assertion failure in child
    killChild();
    throw UnknownTestFailure(rv());
  }

  //read the result
  jalib::JBinarySerializeReaderRaw o("pipe", _fd);
  o.serialize(result.time);
  o.serialize(result.accuracy);
  o & result.hash;
  o.serializeVector(_modifications);

  //reapply tunable modifications to this process
  for(size_t i=0; i<_modifications.size(); ++i)
    _modifications[i].tunable->setValue(_modifications[i].value);
  _modifications.clear();

  //wait for subprocess to exit cleanly
  waitExited();
  if(rv()!=SUCCESS_RV){
    throw UnknownTestFailure(rv());
  }
  return true;
}

std::string petabricks::SubprocessTestIsolation::recvControlCookie() {
  //perform a test read -- we dont expect reads to block because of pselect above
  char buf[sizeof COOKIE_DONE];
  for(ssize_t n=0; n==0;){
    memset(buf, 0, sizeof buf);
    n=recv(_fd, buf, strlen(COOKIE_DONE), MSG_DONTWAIT);
    if(n<0 && errno==EAGAIN)
      n=0;
    testExited();
    if(!running() && rv()!=SUCCESS_RV)
      break;//child failed
  }
  return buf;
}

void  petabricks::SubprocessTestIsolation::killChild() {
  if(running()){
    kill(_pid, TIMEOUTKILLSIG);
    waitExited();
  }
}
void  petabricks::SubprocessTestIsolation::waitExited() {
  if(running()){
    if(waitpid(_pid, &_rv, 0)==_pid){
      JASSERT(!running())(_rv);
    }else
      JASSERT(false)(JASSERT_ERRNO).Text("wait failed");
  }
  if(_fd>=0){
    close(_fd);
    _fd=-1;
  }

}
void  petabricks::SubprocessTestIsolation::testExited() {
  if(running()){
    if(waitpid(_pid, &_rv, WNOHANG)==_pid)
      JASSERT(!running())(_rv);
    else
      _rv=RUNNING_RV;//ensure running()
  }
}
bool petabricks::SubprocessTestIsolation::running() const{
  return _rv<-256;
}
int  petabricks::SubprocessTestIsolation::rv(){
  JASSERT(!running());
  if(WIFEXITED(_rv))
    return WEXITSTATUS(_rv);
  return CRASH_RV;
}

bool petabricks::DummyTestIsolation::beginTest(int workerThreads, int reexecchild) {
  DynamicScheduler::cpuScheduler().startWorkerThreads(workerThreads);
  JASSERT(reexecchild<0);
  return true;
}

void petabricks::DummyTestIsolation::endTest(TestResult&) {}

void petabricks::DummyTestIsolation::recvResult(TestResult&) {
  JASSERT(false);
}

<commit_msg>shutdown remotehost<commit_after>/*****************************************************************************
 *  Copyright (C) 2008-2011 Massachusetts Institute of Technology            *
 *                                                                           *
 *  Permission is hereby granted, free of charge, to any person obtaining    *
 *  a copy of this software and associated documentation files (the          *
 *  "Software"), to deal in the Software without restriction, including      *
 *  without limitation the rights to use, copy, modify, merge, publish,      *
 *  distribute, sublicense, and/or sell copies of the Software, and to       *
 *  permit persons to whom the Software is furnished to do so, subject       *
 *  to the following conditions:                                             *
 *                                                                           *
 *  The above copyright notice and this permission notice shall be included  *
 *  in all copies or substantial portions of the Software.                   *
 *                                                                           *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY                *
 *  KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE               *
 *  WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND      *
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE   *
 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION   *
 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION    *
 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE           *
 *                                                                           *
 *  This source code is part of the PetaBricks project:                      *
 *    http://projects.csail.mit.edu/petabricks/                              *
 *                                                                           *
 *****************************************************************************/
#include "testisolation.h"
#include "dynamicscheduler.h"
#include "gpumanager.h"
#include "remotehost.h"

#include <limits>
#include <string.h>

#include "petabricksruntime.h"

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif

// annoyingly lapack returns 0 when it aborts, so we use a "secret" rv here
#define SUCCESS_RV 198
#define RUNNING_RV -257
#define CRASH_RV 666

static void _settestprocflags(){
#ifdef HAVE_SYS_PRCTL_H
# ifdef PR_SET_PDEATHSIG //linux 2.1.57
  //automatically kill us when parent dies
  JWARNING(prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0)==0);
# endif
# ifdef PR_GET_NAME //linux 2.6.11 (PR_SET_NAME 2.6.9)
  //append "(timing)" to our process name
  char buf[128];//spec says 16 is big enough
  memset(buf, 0, sizeof buf);
  prctl(PR_GET_NAME, buf, 0, 0, 0);
  strncpy(buf+strlen(buf), "(timing)", sizeof(buf)-strlen(buf)-1);
  prctl(PR_SET_NAME, buf, 0, 0, 0);
# endif
#endif
}

//keep these 1 char long: (all must be same size)
static const char COOKIE_DONE[] = "D";
static const char COOKIE_DISABLETIMEOUT[] = "E";
static const char COOKIE_RESTARTTIMEOUT[] = "R";
JASSERT_STATIC(sizeof COOKIE_DONE == sizeof COOKIE_DISABLETIMEOUT);
JASSERT_STATIC(sizeof COOKIE_DONE == sizeof COOKIE_RESTARTTIMEOUT);

petabricks::SubprocessTestIsolation::SubprocessTestIsolation(double to)
  : _pid(-1), _fd(-1), _rv(RUNNING_RV), _timeout(to), _timeoutEnabled(false), _start(jalib::JTime::null())
{
  if(_timeout < std::numeric_limits<double>::max()-TIMEOUT_GRACESEC)
    _timeout += TIMEOUT_GRACESEC;
}

void petabricks::SubprocessTestIsolation::onTunableModification(jalib::JTunable* t, jalib::TunableValue, jalib::TunableValue newVal){
  _modifications.push_back(TunableMod(t,newVal));
}

petabricks::TestIsolation* theMasterProcess = NULL;
petabricks::TestIsolation* petabricks::SubprocessTestIsolation::masterProcess() {
  return theMasterProcess;
}

bool petabricks::SubprocessTestIsolation::beginTest(int workerThreads, int reexecchild) {
  JASSERT(theMasterProcess==NULL);
  _modifications.clear();
#ifdef HAVE_OPENCL
  GpuManager::shutdown();
#endif
  DynamicScheduler::cpuScheduler().shutdown();
  int fds[2];
  //JASSERT(pipe(fds) == 0);
  if(reexecchild<0)  {
    JASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
    JASSERT((_pid=fork()) >=0);
  }else{
    _pid=0;
  }
  if(_pid>0){
    //parent
    _fd=fds[0];
    close(fds[1]);
    _rv = RUNNING_RV;
    _timeoutEnabled = false;
    _start = jalib::JTime::now();
    //JTRACE("parent");
    return false;
  }else{
    //child
    //JTRACE("child")(reexecchild);
    if(reexecchild<0) {
      _fd=fds[1];
      close(fds[0]);
      PetabricksRuntime::reexecTestIsolation(fds[1]);
    }else{
      _fd = reexecchild;
    }
    GpuManager::start();
    _settestprocflags();
    PetabricksRuntime::startWorkerThreads(workerThreads);
    jalib::JTunable::setModificationCallback(this);
    theMasterProcess=this;
    //JTRACE("child starting");
    restartTimeout();
    return true;
  }
}

void petabricks::SubprocessTestIsolation::disableTimeout() {
  JASSERT(write(_fd, COOKIE_DISABLETIMEOUT, strlen(COOKIE_DISABLETIMEOUT))>0)(JASSERT_ERRNO);
  fsync(_fd);
}

void petabricks::SubprocessTestIsolation::restartTimeout() {
  JASSERT(write(_fd, COOKIE_RESTARTTIMEOUT, strlen(COOKIE_RESTARTTIMEOUT))>0)(JASSERT_ERRNO);
  fsync(_fd);
}

void petabricks::SubprocessTestIsolation::endTest(TestResult& result) {
  JASSERT(_pid==0);
  JASSERT(write(_fd, COOKIE_DONE, strlen(COOKIE_DONE))>0)(JASSERT_ERRNO);
  jalib::JBinarySerializeWriterRaw o("pipe", _fd);
  o.serialize(result.time);
  o.serialize(result.accuracy);
  o & result.hash;
  o.serializeVector(_modifications);
  fflush(NULL);
  fsync(_fd);
  fsync(fileno(stdout));
  fsync(fileno(stderr));
  //GpuManager::shutdown();
  //DynamicScheduler::cpuScheduler().shutdown();
  RemoteHostDB().instance().shutdown();
  _exit(SUCCESS_RV);
}

inline static void _settimeout(struct timespec& timeout, double sec){
  if(sec >= std::numeric_limits<long>::max()){
    timeout.tv_sec=std::numeric_limits<long>::max();
    timeout.tv_nsec=0;
  }else{
    timeout.tv_sec = (long)sec;
    timeout.tv_nsec = (long)((sec-(double)timeout.tv_sec)*1.0e9);
  }
}

inline static void _settimeout(int& timeout, double sec){
  if(sec >= std::numeric_limits<int>::max()/1000-1){
    timeout = -1;
  }else{
    timeout = (int)(sec*1000.0 + 0.5);
  }
}

void petabricks::SubprocessTestIsolation::recvResult(TestResult& result) {
  TimeoutT timeout;
  int ready;
  _settimeout(timeout, std::numeric_limits<int>::max());

  struct pollfd fds[1];
  fds[0].fd = _fd;
  fds[0].events = POLLIN;
  fds[0].revents = 0;

  for(;;){
    _settimeout(timeout, timeleft());
    //JTRACE("timeout")(timeout);
    ready = poll(fds, sizeof(fds)/sizeof(struct pollfd), timeout);
    JASSERT(ready>=0)(ready);

    if(ready==0){ //timeout
      killChild();
      break;
    }

    if(handleEvent(result)){
      break;
    }
  }
}

void petabricks::SubprocessTestIsolation::recvFirstResult(SubprocessTestIsolation& a, TestResult& aresult,
                                                          SubprocessTestIsolation& b, TestResult& bresult) {
  struct pollfd fds[2];
  struct pollfd* pfds = fds;
  bool adone = false;
  bool bdone = false;
  int nfds = 2;
  fds[0].fd = a._fd;
  fds[0].events = POLLIN;
  fds[0].revents = 0;
  fds[1].fd = b._fd;
  fds[1].events = POLLIN;
  fds[1].revents = 0;

  for(;;){
    int ready = 0;
    double secleft = std::max(0.0, std::max(a.timeleft(), b.timeleft()));
    TimeoutT timeout;
    _settimeout(timeout, secleft);
    ready = poll(pfds, nfds, timeout);
    JASSERT(ready>=0)(ready);

    if(ready==0){ //timeout
      a.killChild();
      b.killChild();
      break;
    }

    try {
      adone = adone || ((fds[0].revents&POLLIN)!=0 && a.handleEvent(aresult));
    } catch(UnknownTestFailure e) {
      adone = true;
    }
    try {
      bdone = bdone || ((fds[1].revents&POLLIN)!=0 && b.handleEvent(bresult));
    } catch(UnknownTestFailure e) {
      bdone = true;
    }
    if(adone) {
      fds[0].revents = 0;
      pfds = fds+1;
      nfds = 1;
      b._timeout = PetabricksRuntime::updateRaceTimeout(aresult, 0);
    }else if(bdone) {
      fds[1].revents = 0;
      pfds = fds;
      nfds = 1;
      a._timeout = PetabricksRuntime::updateRaceTimeout(bresult, 1);
    }
    if(adone && bdone) break;
  }
}

double petabricks::SubprocessTestIsolation::timeleft() const {
  if(!running())
      return 0;
  if(_timeoutEnabled)
    return _timeout - (jalib::JTime::now() - _start) + 0.02;
  return std::numeric_limits<double>::max();
}

bool petabricks::SubprocessTestIsolation::handleEvent(TestResult& result) {
  //receive a control code
  std::string cnt = recvControlCookie();

  //check control code:
  if(cnt==COOKIE_DISABLETIMEOUT){
    _timeoutEnabled = false;
    return false;
  }
  if(cnt==COOKIE_RESTARTTIMEOUT){
    _timeoutEnabled = true;
    _start = jalib::JTime::now();
    return false;
  }
  if(cnt!=COOKIE_DONE || (!running() && rv()!=SUCCESS_RV )){
    //unknown control code, most likely assertion failure in child
    killChild();
    throw UnknownTestFailure(rv());
  }

  //read the result
  jalib::JBinarySerializeReaderRaw o("pipe", _fd);
  o.serialize(result.time);
  o.serialize(result.accuracy);
  o & result.hash;
  o.serializeVector(_modifications);

  //reapply tunable modifications to this process
  for(size_t i=0; i<_modifications.size(); ++i)
    _modifications[i].tunable->setValue(_modifications[i].value);
  _modifications.clear();

  //wait for subprocess to exit cleanly
  waitExited();
  if(rv()!=SUCCESS_RV){
    throw UnknownTestFailure(rv());
  }
  return true;
}

std::string petabricks::SubprocessTestIsolation::recvControlCookie() {
  //perform a test read -- we dont expect reads to block because of pselect above
  char buf[sizeof COOKIE_DONE];
  for(ssize_t n=0; n==0;){
    memset(buf, 0, sizeof buf);
    n=recv(_fd, buf, strlen(COOKIE_DONE), MSG_DONTWAIT);
    if(n<0 && errno==EAGAIN)
      n=0;
    testExited();
    if(!running() && rv()!=SUCCESS_RV)
      break;//child failed
  }
  return buf;
}

void  petabricks::SubprocessTestIsolation::killChild() {
  if(running()){
    kill(_pid, TIMEOUTKILLSIG);
    waitExited();
  }
}
void  petabricks::SubprocessTestIsolation::waitExited() {
  if(running()){
    if(waitpid(_pid, &_rv, 0)==_pid){
      JASSERT(!running())(_rv);
    }else
      JASSERT(false)(JASSERT_ERRNO).Text("wait failed");
  }
  if(_fd>=0){
    close(_fd);
    _fd=-1;
  }

}
void  petabricks::SubprocessTestIsolation::testExited() {
  if(running()){
    if(waitpid(_pid, &_rv, WNOHANG)==_pid)
      JASSERT(!running())(_rv);
    else
      _rv=RUNNING_RV;//ensure running()
  }
}
bool petabricks::SubprocessTestIsolation::running() const{
  return _rv<-256;
}
int  petabricks::SubprocessTestIsolation::rv(){
  JASSERT(!running());
  if(WIFEXITED(_rv))
    return WEXITSTATUS(_rv);
  return CRASH_RV;
}

bool petabricks::DummyTestIsolation::beginTest(int workerThreads, int reexecchild) {
  DynamicScheduler::cpuScheduler().startWorkerThreads(workerThreads);
  JASSERT(reexecchild<0);
  return true;
}

void petabricks::DummyTestIsolation::endTest(TestResult&) {}

void petabricks::DummyTestIsolation::recvResult(TestResult&) {
  JASSERT(false);
}

<|endoftext|>


<commit_before>// ========================================================================== //
// This file is part of Sara, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2015-2016 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

//! @file

#pragma once

#include <cstdint>

#include <DO/Sara/Core/ArrayIterators.hpp>
#include <DO/Sara/Core/MultiArray/ElementTraits.hpp>

namespace DO { namespace Sara {

  //! @{
  //! @brief Forward declaration of the multi-dimensional array classes.
  template <typename T, int N, int StorageOrder = ColMajor>
  class MultiArrayView;

  template <typename MultiArrayView, template <typename> class Allocator>
  class MultiArrayBase;

  template <typename T, int N, int StorageOrder = ColMajor,
            template <typename> class Allocator = std::allocator>
  using MultiArray =
      MultiArrayBase<MultiArrayView<T, N, StorageOrder>, Allocator>;
  //! @}

  template <typename T, int N, int S>
  class MultiArrayView
  {
    using self_type = MultiArrayView;

  public: /* typedefs. */
    //! Storage order.
    enum
    {
      Dimension = N,
      StorageOrder = S
    };

    //! @{
    //! @brief STL-compatible interface.
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;
    using value_type = T;
    using pointer = T *;
    using const_pointer = const T *;
    using reference = T&;
    using const_reference = const T&;
    using iterator = T *;
    using const_iterator = const T *;
    //! @}

    //! @{
    //! @brief Slice type.
    using slice_type = MultiArrayView<T, N - 1, S>;
    using const_slice_type = const MultiArrayView<T, N - 1, S>;
    //! @}

    //! @{
    //! @brief Vector type.
    using vector_type = Matrix<int, N, 1>;
    using slice_vector_type = Matrix<int, N - 1, 1>;
    //! @}

    //! @{
    //! @brief N-dimensional iterator type.
    using array_iterator = ArrayIterator<false, T, N, StorageOrder>;
    using const_array_iterator = ArrayIterator<true, T, N, StorageOrder>;
    //! @}

    //! @{
    //! @brief N-dimensional subrange iterator.
    using subarray_iterator = SubarrayIterator<false, T, N, StorageOrder>;
    using const_subarray_iterator = SubarrayIterator<true, T, N, StorageOrder>;
    //! @}

    //! @{
    //! @brief Array views for linear algebra.
    using flat_array_view_type =
        Map<Array<typename ElementTraits<T>::value_type, Dynamic, 1>>;
    using const_flat_array_view_type =
        Map<const Array<typename ElementTraits<T>::value_type, Dynamic, 1>>;
    //! @}

    //! @{
    //! @brief Matrix views for linear algebra.
    using matrix_view_type = Map<Matrix<typename ElementTraits<T>::value_type,
                                        Dynamic, Dynamic, StorageOrder>>;
    using const_matrix_view_type =
        Map<const Matrix<typename ElementTraits<T>::value_type, Dynamic,
                         Dynamic, StorageOrder>>;
    //! @}

  public: /* methods */
    //! @brief Default constructor.
    inline MultiArrayView() = default;

    //! @brief Copy constructor.
    inline MultiArrayView(const self_type&) = default;

    //! @brief Move constructor.
    inline MultiArrayView(self_type&& other)
    {
      swap(other);
    }

    //! @brief Constructor that wraps plain data with its known sizes.
    inline explicit MultiArrayView(value_type *data, const vector_type& sizes)
      : _begin{data}
      , _end{data + compute_size(sizes)}
      , _sizes{sizes}
      , _strides{compute_strides(sizes)}
    {
    }

    //! @brief Copy assignment operator.
    self_type& operator=(self_type other)
    {
      swap(other);
      return *this;
    }

    //! @brief Return the size vector of the MultiArray object.
    const vector_type& sizes() const
    {
      return _sizes;
    }

    //! @brief Return the number of elements in the internal data array.
    size_type size() const
    {
      return _end - _begin;
    }

    //! @brief Return the size of the MultiArray object along the i-th
    //! dimension.
    int size(int i) const
    {
      return _sizes[i];
    }

    //! @brief Return the number of rows.
    int rows() const
    {
      return _sizes[0];
    }

    //! @brief Return the number of cols.
    int cols() const
    {
      return _sizes[1];
    }

    //! @brief Return the depth size.
    int depth() const
    {
      return _sizes[2];
    }

    //! @brief Return the stride vector of the MultiArray object.
    inline const vector_type& strides() const
    {
      return _strides;
    }

    //! @brief Return the stride value along the i-th dimension.
    inline int stride(int i) const
    {
      return _strides[i];
    }
    //! @{
    //! @brief Return the array pointer
    inline pointer data()
    {
      return _begin;
    }

    inline const_pointer data() const
    {
      return _begin;
    }
    //! @}

    //! @{
    //! @brief Return reference to the element at the given coordinates.
    inline reference operator()(const vector_type& pos)
    {
      return _begin[offset(pos)];
    }

    inline reference operator()(int i, int j)
    {
      static_assert(N == 2, "MultiArray must be 2D");
      return _begin[offset(Vector2i(i, j))];
    }

    inline reference operator()(int i, int j, int k)
    {
      static_assert(N == 3, "MultiArray must be 3D");
      return _begin[offset(Vector3i(i, j, k))];
    }

    inline const_reference operator()(const vector_type& pos) const
    {
      return _begin[offset(pos)];
    }

    inline const_reference operator()(int i, int j) const
    {
      static_assert(N == 2, "MultiArray must be 2D");
      return _begin[offset(Vector2i(i, j))];
    }

    inline const_reference operator()(int i, int j, int k) const
    {
      static_assert(N == 3, "MultiArray must be 3D");
      return _begin[offset(Vector3i(i, j, k))];
    }
    //! @}

    //! @{
    //! @brief Return the i-th slice of the MultiArray object.
    inline slice_type operator[](int i)
    {
      auto slice_sizes = _sizes.tail(N - 1).eval();
      auto slice_data = _begin + _strides[0] * i;
      return slice_type{slice_data, slice_sizes};
    }

    inline const_slice_type operator[](int i) const
    {
      auto slice_sizes = _sizes.tail(N - 1).eval();
      auto slice_data = _begin + _strides[0] * i;
      return slice_type{slice_data, slice_sizes};
    }
    //! @}

    //! @{
    //! @brief Return the begin iterator.
    inline iterator begin()
    {
      return _begin;
    }

    inline const_iterator begin() const
    {
      return _begin;
    }
    //! @}

    //! @{
    //! @brief Return the end iterator.
    inline iterator end()
    {
      return _end;
    }

    inline const_iterator end() const
    {
      return _end;
    }
    //! @}

    //! @{
    //! @brief Return the array view for linear algebra with Eigen libraries.
    inline flat_array_view_type flat_array()
    {
      return flat_array_view_type{
          reinterpret_cast<typename ElementTraits<T>::pointer>(data()),
          static_cast<int64_t>(size())};
    }

    inline const_flat_array_view_type flat_array() const
    {
      return const_flat_array_view_type{
          reinterpret_cast<const typename ElementTraits<T>::const_pointer>(
              data()),
          static_cast<int64_t>(size())};
    }
    //! @}

    //! @{
    //! @brief Return the matrix view for linear algebra with Eigen libraries.
    inline matrix_view_type matrix()
    {
      static_assert(N == 2, "MultiArray must be 2D");
      return matrix_view_type{
          reinterpret_cast<typename ElementTraits<T>::pointer>(data()), rows(),
          cols()};
    }

    inline const_matrix_view_type matrix() const
    {
      static_assert(N == 2, "MultiArray must be 2D");
      return const_matrix_view_type{
          reinterpret_cast<typename ElementTraits<T>::const_pointer>(data()),
          rows(), cols()};
    }
    //! @}

    //! @{
    //! @brief Return the begin iterator of the whole multi-array.
    inline array_iterator begin_array()
    {
      return array_iterator{false, _begin, vector_type::Zero(), _sizes,
                            _strides};
    }

    inline const_array_iterator begin_array() const
    {
      return const_array_iterator{false, _begin, vector_type::Zero(), _sizes,
                                  _strides};
    }
    //! @}

    //! @{
    //! @brief Return the begin iterator of the sub-array.
    inline subarray_iterator begin_subarray(const vector_type& start,
                                            const vector_type& end)
    {
      return subarray_iterator{false, _begin, start, end, _strides, _sizes};
    }

    inline const_subarray_iterator begin_subarray(const vector_type& start,
                                                  const vector_type& end) const
    {
      return const_subarray_iterator{false, _begin,   start,
                                     end,   _strides, _sizes};
    }
    //! @}

    //! @brief Swap multi-array objects.
    inline void swap(self_type& other)
    {
      using std::swap;
      swap(_begin, other._begin);
      swap(_end, other._end);
      swap(_sizes, other._sizes);
      swap(_strides, other._strides);
    }

    //! @{
    //! @brief Equality comparison.
    inline bool operator==(const self_type& other) const
    {
      if (_sizes != other._sizes)
        return false;
      return std::equal(_begin, _end, other._begin);
    }

    inline bool operator!=(const self_type& other) const
    {
      return !(*this == other);
    }
    //! @}

    //! @brief Copy contents.
    inline void copy(const self_type& other) const
    {
      if (this == &other)
        return;

      if (_sizes != other._sizes)
        throw std::domain_error{
            "Source and destination image sizes are not equal!"};

      std::copy(other._begin, other._end, _begin);
    }

    //! @brief Perform coefficient-wise transform in place.
    template <typename Op>
    inline auto cwise_transform_inplace(Op op) -> self_type&
    {
      for (auto pixel = begin(); pixel != end(); ++pixel)
        op(*pixel);
      return *this;
    }

    //! @brief Perform coefficient-wise transform.
    template <typename Op>
    inline auto cwise_transform(Op op) const
        -> MultiArray<decltype(op(std::declval<value_type>())), Dimension,
                      StorageOrder>
    {
      using ValueType = decltype(op(std::declval<value_type>()));

      auto dst = MultiArray<ValueType, N, S>{sizes()};

      auto src_pixel = begin();
      auto dst_pixel = dst.begin();
      for (; src_pixel != end(); ++src_pixel, ++dst_pixel)
        *dst_pixel = op(*src_pixel);

      return dst;
    }

  protected:
    //! @brief Compute the strides according the size vector and storage order.
    inline vector_type compute_strides(const vector_type& sizes) const
    {
      return StrideComputer<StorageOrder>::eval(sizes);
    }

    //! @brief Compute the raw size needed to allocate the internal data.
    inline size_type compute_size(const vector_type& sizes) const
    {
      auto sz = sizes.template cast<size_type>().eval();
      return std::accumulate(sz.data(), sz.data() + N, size_type(1),
                             std::multiplies<size_type>());
    }

    //! @brief Compute the 1D index of the corresponding coordinates.
    inline int offset(const vector_type& pos) const
    {
      return jump(pos, _strides);
    }

  protected: /* data members. */
    //! @brief First element of the internal array.
    value_type *_begin{nullptr};
    //! @brief Last element of the internal array.
    value_type *_end{nullptr};
    //! @brief Sizes vector.
    vector_type _sizes = vector_type::Zero();
    //! @brief Strides vector.
    vector_type _strides = vector_type::Zero();
  };

  //! @brief Output stream operator.
  template <typename T, int N, int StorageOrder>
  std::ostream& operator<<(std::ostream& os,
                           const MultiArrayView<T, N, StorageOrder>& M)
  {
    os << M.sizes() << std::endl;
    os << M.array() << std::endl;
    return os;
  }

} /* namespace Sara */
} /* namespace DO */
<commit_msg>MAINT: tentative fix for gcc 4.8.4.<commit_after>// ========================================================================== //
// This file is part of Sara, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2015-2016 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

//! @file

#pragma once

#include <cstdint>

#include <DO/Sara/Core/ArrayIterators.hpp>
#include <DO/Sara/Core/MultiArray/ElementTraits.hpp>

namespace DO { namespace Sara {

  //! @{
  //! @brief Forward declaration of the multi-dimensional array classes.
  template <typename T, int N, int StorageOrder = ColMajor>
  class MultiArrayView;

  template <typename MultiArrayView, template <typename> class Allocator>
  class MultiArrayBase;

  template <typename T, int N, int StorageOrder = ColMajor,
            template <typename> class Allocator = std::allocator>
  using MultiArray =
      MultiArrayBase<MultiArrayView<T, N, StorageOrder>, Allocator>;
  //! @}

  template <typename T, int N, int S>
  class MultiArrayView
  {
    using self_type = MultiArrayView;

  public: /* typedefs. */
    //! Storage order.
    enum
    {
      Dimension = N,
      StorageOrder = S
    };

    //! @{
    //! @brief STL-compatible interface.
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;
    using value_type = T;
    using pointer = T *;
    using const_pointer = const T *;
    using reference = T&;
    using const_reference = const T&;
    using iterator = T *;
    using const_iterator = const T *;
    //! @}

    //! @{
    //! @brief Slice type.
    using slice_type = MultiArrayView<T, N - 1, S>;
    using const_slice_type = const MultiArrayView<T, N - 1, S>;
    //! @}

    //! @{
    //! @brief Vector type.
    using vector_type = Matrix<int, N, 1>;
    using slice_vector_type = Matrix<int, N - 1, 1>;
    //! @}

    //! @{
    //! @brief N-dimensional iterator type.
    using array_iterator = ArrayIterator<false, T, N, StorageOrder>;
    using const_array_iterator = ArrayIterator<true, T, N, StorageOrder>;
    //! @}

    //! @{
    //! @brief N-dimensional subrange iterator.
    using subarray_iterator = SubarrayIterator<false, T, N, StorageOrder>;
    using const_subarray_iterator = SubarrayIterator<true, T, N, StorageOrder>;
    //! @}

    //! @{
    //! @brief Array views for linear algebra.
    using flat_array_view_type =
        Map<Array<typename ElementTraits<T>::value_type, Dynamic, 1>>;
    using const_flat_array_view_type =
        Map<const Array<typename ElementTraits<T>::value_type, Dynamic, 1>>;
    //! @}

    //! @{
    //! @brief Matrix views for linear algebra.
    using matrix_view_type = Map<Matrix<typename ElementTraits<T>::value_type,
                                        Dynamic, Dynamic, StorageOrder>>;
    using const_matrix_view_type =
        Map<const Matrix<typename ElementTraits<T>::value_type, Dynamic,
                         Dynamic, StorageOrder>>;
    //! @}

  public: /* methods */
    //! @brief Default constructor.
    inline MultiArrayView() = default;

    //! @brief Copy constructor.
    inline MultiArrayView(const self_type&) = default;

    //! @brief Move constructor.
    inline MultiArrayView(self_type&& other)
    {
      swap(other);
    }

    //! @brief Constructor that wraps plain data with its known sizes.
    inline explicit MultiArrayView(value_type *data, const vector_type& sizes)
      : _begin{data}
      , _end{data + compute_size(sizes)}
      , _sizes{sizes}
      , _strides{compute_strides(sizes)}
    {
    }

    //! @brief Copy assignment operator.
    self_type& operator=(self_type other)
    {
      swap(other);
      return *this;
    }

    //! @brief Return the size vector of the MultiArray object.
    const vector_type& sizes() const
    {
      return _sizes;
    }

    //! @brief Return the number of elements in the internal data array.
    size_type size() const
    {
      return _end - _begin;
    }

    //! @brief Return the size of the MultiArray object along the i-th
    //! dimension.
    int size(int i) const
    {
      return _sizes[i];
    }

    //! @brief Return the number of rows.
    int rows() const
    {
      return _sizes[0];
    }

    //! @brief Return the number of cols.
    int cols() const
    {
      return _sizes[1];
    }

    //! @brief Return the depth size.
    int depth() const
    {
      return _sizes[2];
    }

    //! @brief Return the stride vector of the MultiArray object.
    inline const vector_type& strides() const
    {
      return _strides;
    }

    //! @brief Return the stride value along the i-th dimension.
    inline int stride(int i) const
    {
      return _strides[i];
    }
    //! @{
    //! @brief Return the array pointer
    inline pointer data()
    {
      return _begin;
    }

    inline const_pointer data() const
    {
      return _begin;
    }
    //! @}

    //! @{
    //! @brief Return reference to the element at the given coordinates.
    inline reference operator()(const vector_type& pos)
    {
      return _begin[offset(pos)];
    }

    inline reference operator()(int i, int j)
    {
      static_assert(N == 2, "MultiArray must be 2D");
      return _begin[offset(Vector2i(i, j))];
    }

    inline reference operator()(int i, int j, int k)
    {
      static_assert(N == 3, "MultiArray must be 3D");
      return _begin[offset(Vector3i(i, j, k))];
    }

    inline const_reference operator()(const vector_type& pos) const
    {
      return _begin[offset(pos)];
    }

    inline const_reference operator()(int i, int j) const
    {
      static_assert(N == 2, "MultiArray must be 2D");
      return _begin[offset(Vector2i(i, j))];
    }

    inline const_reference operator()(int i, int j, int k) const
    {
      static_assert(N == 3, "MultiArray must be 3D");
      return _begin[offset(Vector3i(i, j, k))];
    }
    //! @}

    //! @{
    //! @brief Return the i-th slice of the MultiArray object.
    inline slice_type operator[](int i)
    {
      auto slice_sizes = _sizes.tail(N - 1).eval();
      auto slice_data = _begin + _strides[0] * i;
      return slice_type{slice_data, slice_sizes};
    }

    inline const_slice_type operator[](int i) const
    {
      auto slice_sizes = _sizes.tail(N - 1).eval();
      auto slice_data = _begin + _strides[0] * i;
      return slice_type{slice_data, slice_sizes};
    }
    //! @}

    //! @{
    //! @brief Return the begin iterator.
    inline iterator begin()
    {
      return _begin;
    }

    inline const_iterator begin() const
    {
      return _begin;
    }
    //! @}

    //! @{
    //! @brief Return the end iterator.
    inline iterator end()
    {
      return _end;
    }

    inline const_iterator end() const
    {
      return _end;
    }
    //! @}

    //! @{
    //! @brief Return the array view for linear algebra with Eigen libraries.
    inline flat_array_view_type flat_array()
    {
      return flat_array_view_type{
          reinterpret_cast<typename ElementTraits<T>::pointer>(data()),
          static_cast<int64_t>(size())};
    }

    inline const_flat_array_view_type flat_array() const
    {
      return const_flat_array_view_type{
          reinterpret_cast<const typename ElementTraits<T>::const_pointer>(
              data()),
          static_cast<int64_t>(size())};
    }
    //! @}

    //! @{
    //! @brief Return the matrix view for linear algebra with Eigen libraries.
    inline matrix_view_type matrix()
    {
      static_assert(N == 2, "MultiArray must be 2D");
      return matrix_view_type{
          reinterpret_cast<typename ElementTraits<T>::pointer>(data()), rows(),
          cols()};
    }

    inline const_matrix_view_type matrix() const
    {
      static_assert(N == 2, "MultiArray must be 2D");
      return const_matrix_view_type{
          reinterpret_cast<typename ElementTraits<T>::const_pointer>(data()),
          rows(), cols()};
    }
    //! @}

    //! @{
    //! @brief Return the begin iterator of the whole multi-array.
    inline array_iterator begin_array()
    {
      return array_iterator{false, _begin, vector_type::Zero(), _sizes,
                            _strides};
    }

    inline const_array_iterator begin_array() const
    {
      return const_array_iterator{false, _begin, vector_type::Zero(), _sizes,
                                  _strides};
    }
    //! @}

    //! @{
    //! @brief Return the begin iterator of the sub-array.
    inline subarray_iterator begin_subarray(const vector_type& start,
                                            const vector_type& end)
    {
      return subarray_iterator{false, _begin, start, end, _strides, _sizes};
    }

    inline const_subarray_iterator begin_subarray(const vector_type& start,
                                                  const vector_type& end) const
    {
      return const_subarray_iterator{false, _begin,   start,
                                     end,   _strides, _sizes};
    }
    //! @}

    //! @brief Swap multi-array objects.
    inline void swap(self_type& other)
    {
      using std::swap;
      swap(_begin, other._begin);
      swap(_end, other._end);
      swap(_sizes, other._sizes);
      swap(_strides, other._strides);
    }

    //! @{
    //! @brief Equality comparison.
    inline bool operator==(const self_type& other) const
    {
      if (_sizes != other._sizes)
        return false;
      return std::equal(_begin, _end, other._begin);
    }

    inline bool operator!=(const self_type& other) const
    {
      return !(*this == other);
    }
    //! @}

    //! @brief Copy contents.
    inline void copy(const self_type& other) const
    {
      if (this == &other)
        return;

      if (_sizes != other._sizes)
        throw std::domain_error{
            "Source and destination image sizes are not equal!"};

      std::copy(other._begin, other._end, _begin);
    }

    //! @brief Perform coefficient-wise transform in place.
    template <typename Op>
    inline auto cwise_transform_inplace(Op op) -> self_type&
    {
      for (auto pixel = begin(); pixel != end(); ++pixel)
        op(*pixel);
      return *this;
    }

    //! @brief Perform coefficient-wise transform.
    template <typename Op>
    inline auto cwise_transform(Op op) const
        -> MultiArray<decltype(op(std::declval<value_type>())), Dimension,
                      StorageOrder>
    {
      using ValueType = decltype(op(std::declval<value_type>()));

      auto dst = MultiArray<ValueType, N, S>{sizes()};

      auto src_pixel = begin();
      auto dst_pixel = dst.begin();
      for (; src_pixel != end(); ++src_pixel, ++dst_pixel)
        *dst_pixel = op(*src_pixel);

      return dst;
    }

  protected:
    //! @brief Compute the strides according the size vector and storage order.
    inline vector_type compute_strides(const vector_type& sizes) const
    {
      return StrideComputer<StorageOrder>::eval(sizes);
    }

    //! @brief Compute the raw size needed to allocate the internal data.
    inline size_type compute_size(const vector_type& sizes) const
    {
      auto sz = sizes.template cast<size_type>().eval();
      return std::accumulate(sz.data(), sz.data() + N, size_type(1),
                             std::multiplies<size_type>());
    }

    //! @brief Compute the 1D index of the corresponding coordinates.
    inline int offset(const vector_type& pos) const
    {
      return jump(pos, _strides);
    }

  protected: /* data members. */
    //! @brief First element of the internal array.
    value_type *_begin{nullptr};
    //! @brief Last element of the internal array.
    value_type *_end{nullptr};
    //! @brief Sizes vector.
    vector_type _sizes{vector_type::Zero().eval()};
    //! @brief Strides vector.
    vector_type _strides{vector_type::Zero().eval()};
  };

  //! @brief Output stream operator.
  template <typename T, int N, int StorageOrder>
  std::ostream& operator<<(std::ostream& os,
                           const MultiArrayView<T, N, StorageOrder>& M)
  {
    os << M.sizes() << std::endl;
    os << M.array() << std::endl;
    return os;
  }

} /* namespace Sara */
} /* namespace DO */
<|endoftext|>


<commit_before>//===-- LLVMSymbolize.cpp -------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implementation for LLVM symbolization library.
//
//===----------------------------------------------------------------------===//

#include "LLVMSymbolize.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"

#include <sstream>

namespace llvm {
namespace symbolize {

static bool error(error_code ec) {
  if (!ec)
    return false;
  errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n";
  return true;
}

static uint32_t
getDILineInfoSpecifierFlags(const LLVMSymbolizer::Options &Opts) {
  uint32_t Flags = llvm::DILineInfoSpecifier::FileLineInfo |
                   llvm::DILineInfoSpecifier::AbsoluteFilePath;
  if (Opts.PrintFunctions)
    Flags |= llvm::DILineInfoSpecifier::FunctionName;
  return Flags;
}

static void patchFunctionNameInDILineInfo(const std::string &NewFunctionName,
                                          DILineInfo &LineInfo) {
  std::string FileName = LineInfo.getFileName();
  LineInfo = DILineInfo(StringRef(FileName), StringRef(NewFunctionName),
                        LineInfo.getLine(), LineInfo.getColumn());
}

ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
    : Module(Obj), DebugInfoContext(DICtx) {
  error_code ec;
  for (symbol_iterator si = Module->begin_symbols(), se = Module->end_symbols();
       si != se; si.increment(ec)) {
    if (error(ec))
      return;
    SymbolRef::Type SymbolType;
    if (error(si->getType(SymbolType)))
      continue;
    if (SymbolType != SymbolRef::ST_Function &&
        SymbolType != SymbolRef::ST_Data)
      continue;
    uint64_t SymbolAddress;
    if (error(si->getAddress(SymbolAddress)) ||
        SymbolAddress == UnknownAddressOrSize)
      continue;
    uint64_t SymbolSize;
    // Getting symbol size is linear for Mach-O files, so assume that symbol
    // occupies the memory range up to the following symbol.
    if (isa<MachOObjectFile>(Obj))
      SymbolSize = 0;
    else if (error(si->getSize(SymbolSize)) ||
             SymbolSize == UnknownAddressOrSize)
      continue;
    StringRef SymbolName;
    if (error(si->getName(SymbolName)))
      continue;
    // Mach-O symbol table names have leading underscore, skip it.
    if (Module->isMachO() && SymbolName.size() > 0 && SymbolName[0] == '_')
      SymbolName = SymbolName.drop_front();
    // FIXME: If a function has alias, there are two entries in symbol table
    // with same address size. Make sure we choose the correct one.
    SymbolMapTy &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects;
    SymbolDesc SD = { SymbolAddress, SymbolSize };
    M.insert(std::make_pair(SD, SymbolName));
  }
}

bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
                                        std::string &Name, uint64_t &Addr,
                                        uint64_t &Size) const {
  const SymbolMapTy &M = Type == SymbolRef::ST_Function ? Functions : Objects;
  if (M.empty())
    return false;
  SymbolDesc SD = { Address, Address };
  SymbolMapTy::const_iterator it = M.upper_bound(SD);
  if (it == M.begin())
    return false;
  --it;
  if (it->first.Size != 0 && it->first.Addr + it->first.Size <= Address)
    return false;
  Name = it->second.str();
  Addr = it->first.Addr;
  Size = it->first.Size;
  return true;
}

DILineInfo ModuleInfo::symbolizeCode(
    uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
  DILineInfo LineInfo;
  if (DebugInfoContext) {
    LineInfo = DebugInfoContext->getLineInfoForAddress(
        ModuleOffset, getDILineInfoSpecifierFlags(Opts));
  }
  // Override function name from symbol table if necessary.
  if (Opts.PrintFunctions && Opts.UseSymbolTable) {
    std::string FunctionName;
    uint64_t Start, Size;
    if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
                               FunctionName, Start, Size)) {
      patchFunctionNameInDILineInfo(FunctionName, LineInfo);
    }
  }
  return LineInfo;
}

DIInliningInfo ModuleInfo::symbolizeInlinedCode(
    uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
  DIInliningInfo InlinedContext;
  if (DebugInfoContext) {
    InlinedContext = DebugInfoContext->getInliningInfoForAddress(
        ModuleOffset, getDILineInfoSpecifierFlags(Opts));
  }
  // Make sure there is at least one frame in context.
  if (InlinedContext.getNumberOfFrames() == 0) {
    InlinedContext.addFrame(DILineInfo());
  }
  // Override the function name in lower frame with name from symbol table.
  if (Opts.PrintFunctions && Opts.UseSymbolTable) {
    DIInliningInfo PatchedInlinedContext;
    for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) {
      DILineInfo LineInfo = InlinedContext.getFrame(i);
      if (i == n - 1) {
        std::string FunctionName;
        uint64_t Start, Size;
        if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
                                   FunctionName, Start, Size)) {
          patchFunctionNameInDILineInfo(FunctionName, LineInfo);
        }
      }
      PatchedInlinedContext.addFrame(LineInfo);
    }
    InlinedContext = PatchedInlinedContext;
  }
  return InlinedContext;
}

bool ModuleInfo::symbolizeData(uint64_t ModuleOffset, std::string &Name,
                               uint64_t &Start, uint64_t &Size) const {
  return getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset, Name, Start,
                                Size);
}

const char LLVMSymbolizer::kBadString[] = "??";

std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
                                          uint64_t ModuleOffset) {
  ModuleInfo *Info = getOrCreateModuleInfo(ModuleName);
  if (Info == 0)
    return printDILineInfo(DILineInfo());
  if (Opts.PrintInlining) {
    DIInliningInfo InlinedContext =
        Info->symbolizeInlinedCode(ModuleOffset, Opts);
    uint32_t FramesNum = InlinedContext.getNumberOfFrames();
    assert(FramesNum > 0);
    std::string Result;
    for (uint32_t i = 0; i < FramesNum; i++) {
      DILineInfo LineInfo = InlinedContext.getFrame(i);
      Result += printDILineInfo(LineInfo);
    }
    return Result;
  }
  DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts);
  return printDILineInfo(LineInfo);
}

std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
                                          uint64_t ModuleOffset) {
  std::string Name = kBadString;
  uint64_t Start = 0;
  uint64_t Size = 0;
  if (Opts.UseSymbolTable) {
    if (ModuleInfo *Info = getOrCreateModuleInfo(ModuleName)) {
      if (Info->symbolizeData(ModuleOffset, Name, Start, Size) && Opts.Demangle)
        Name = DemangleName(Name);
    }
  }
  std::stringstream ss;
  ss << Name << "\n" << Start << " " << Size << "\n";
  return ss.str();
}

void LLVMSymbolizer::flush() {
  DeleteContainerSeconds(Modules);
  DeleteContainerPointers(ParsedBinariesAndObjects);
  BinaryForPath.clear();
  ObjectFileForArch.clear();
}

static std::string getDarwinDWARFResourceForPath(const std::string &Path) {
  StringRef Basename = sys::path::filename(Path);
  const std::string &DSymDirectory = Path + ".dSYM";
  SmallString<16> ResourceName = StringRef(DSymDirectory);
  sys::path::append(ResourceName, "Contents", "Resources", "DWARF");
  sys::path::append(ResourceName, Basename);
  return ResourceName.str();
}

LLVMSymbolizer::BinaryPair
LLVMSymbolizer::getOrCreateBinary(const std::string &Path) {
  BinaryMapTy::iterator I = BinaryForPath.find(Path);
  if (I != BinaryForPath.end())
    return I->second;
  Binary *Bin = 0;
  Binary *DbgBin = 0;
  OwningPtr<Binary> ParsedBinary;
  OwningPtr<Binary> ParsedDbgBinary;
  if (!error(createBinary(Path, ParsedBinary))) {
    // Check if it's a universal binary.
    Bin = ParsedBinary.take();
    ParsedBinariesAndObjects.push_back(Bin);
    if (Bin->isMachO() || Bin->isMachOUniversalBinary()) {
      // On Darwin we may find DWARF in separate object file in
      // resource directory.
      const std::string &ResourcePath =
          getDarwinDWARFResourceForPath(Path);
      bool ResourceFileExists = false;
      if (!sys::fs::exists(ResourcePath, ResourceFileExists) &&
          ResourceFileExists &&
          !error(createBinary(ResourcePath, ParsedDbgBinary))) {
        DbgBin = ParsedDbgBinary.take();
        ParsedBinariesAndObjects.push_back(DbgBin);
      }
    }
  }
  if (DbgBin == 0)
    DbgBin = Bin;
  BinaryPair Res = std::make_pair(Bin, DbgBin);
  BinaryForPath[Path] = Res;
  return Res;
}

ObjectFile *
LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, const std::string &ArchName) {
  if (Bin == 0)
    return 0;
  ObjectFile *Res = 0;
  if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin)) {
    ObjectFileForArchMapTy::iterator I = ObjectFileForArch.find(
        std::make_pair(UB, ArchName));
    if (I != ObjectFileForArch.end())
      return I->second;
    OwningPtr<ObjectFile> ParsedObj;
    if (!UB->getObjectForArch(Triple(ArchName).getArch(), ParsedObj)) {
      Res = ParsedObj.take();
      ParsedBinariesAndObjects.push_back(Res);
    }
    ObjectFileForArch[std::make_pair(UB, ArchName)] = Res;
  } else if (Bin->isObject()) {
    Res = cast<ObjectFile>(Bin);
  }
  return Res;
}

ModuleInfo *
LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
  ModuleMapTy::iterator I = Modules.find(ModuleName);
  if (I != Modules.end())
    return I->second;
  std::string BinaryName = ModuleName;
  std::string ArchName = Opts.DefaultArch;
  size_t ColonPos = ModuleName.find_last_of(':');
  // Verify that substring after colon form a valid arch name.
  if (ColonPos != std::string::npos) {
    std::string ArchStr = ModuleName.substr(ColonPos + 1);
    if (Triple(ArchStr).getArch() != Triple::ArchType::UnknownArch) {
      BinaryName = ModuleName.substr(0, ColonPos);
      ArchName = ArchStr;
    }
  }
  BinaryPair Binaries = getOrCreateBinary(BinaryName);
  ObjectFile *Obj = getObjectFileFromBinary(Binaries.first, ArchName);
  ObjectFile *DbgObj = getObjectFileFromBinary(Binaries.second, ArchName);

  if (Obj == 0) {
    // Failed to find valid object file.
    Modules.insert(make_pair(ModuleName, (ModuleInfo *)0));
    return 0;
  }
  DIContext *Context = DIContext::getDWARFContext(DbgObj);
  assert(Context);
  ModuleInfo *Info = new ModuleInfo(Obj, Context);
  Modules.insert(make_pair(ModuleName, Info));
  return Info;
}

std::string LLVMSymbolizer::printDILineInfo(DILineInfo LineInfo) const {
  // By default, DILineInfo contains "<invalid>" for function/filename it
  // cannot fetch. We replace it to "??" to make our output closer to addr2line.
  static const std::string kDILineInfoBadString = "<invalid>";
  std::stringstream Result;
  if (Opts.PrintFunctions) {
    std::string FunctionName = LineInfo.getFunctionName();
    if (FunctionName == kDILineInfoBadString)
      FunctionName = kBadString;
    else if (Opts.Demangle)
      FunctionName = DemangleName(FunctionName);
    Result << FunctionName << "\n";
  }
  std::string Filename = LineInfo.getFileName();
  if (Filename == kDILineInfoBadString)
    Filename = kBadString;
  Result << Filename << ":" << LineInfo.getLine() << ":" << LineInfo.getColumn()
         << "\n";
  return Result.str();
}

#if !defined(_MSC_VER)
// Assume that __cxa_demangle is provided by libcxxabi (except for Windows).
extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
                                size_t *length, int *status);
#endif

std::string LLVMSymbolizer::DemangleName(const std::string &Name) {
#if !defined(_MSC_VER)
  int status = 0;
  char *DemangledName = __cxa_demangle(Name.c_str(), 0, 0, &status);
  if (status != 0)
    return Name;
  std::string Result = DemangledName;
  free(DemangledName);
  return Result;
#else
  return Name;
#endif
}

} // namespace symbolize
} // namespace llvm
<commit_msg>LLVMSymbolize.cpp: Fix build. Triple::ArchType is not a namespace.<commit_after>//===-- LLVMSymbolize.cpp -------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implementation for LLVM symbolization library.
//
//===----------------------------------------------------------------------===//

#include "LLVMSymbolize.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"

#include <sstream>

namespace llvm {
namespace symbolize {

static bool error(error_code ec) {
  if (!ec)
    return false;
  errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n";
  return true;
}

static uint32_t
getDILineInfoSpecifierFlags(const LLVMSymbolizer::Options &Opts) {
  uint32_t Flags = llvm::DILineInfoSpecifier::FileLineInfo |
                   llvm::DILineInfoSpecifier::AbsoluteFilePath;
  if (Opts.PrintFunctions)
    Flags |= llvm::DILineInfoSpecifier::FunctionName;
  return Flags;
}

static void patchFunctionNameInDILineInfo(const std::string &NewFunctionName,
                                          DILineInfo &LineInfo) {
  std::string FileName = LineInfo.getFileName();
  LineInfo = DILineInfo(StringRef(FileName), StringRef(NewFunctionName),
                        LineInfo.getLine(), LineInfo.getColumn());
}

ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
    : Module(Obj), DebugInfoContext(DICtx) {
  error_code ec;
  for (symbol_iterator si = Module->begin_symbols(), se = Module->end_symbols();
       si != se; si.increment(ec)) {
    if (error(ec))
      return;
    SymbolRef::Type SymbolType;
    if (error(si->getType(SymbolType)))
      continue;
    if (SymbolType != SymbolRef::ST_Function &&
        SymbolType != SymbolRef::ST_Data)
      continue;
    uint64_t SymbolAddress;
    if (error(si->getAddress(SymbolAddress)) ||
        SymbolAddress == UnknownAddressOrSize)
      continue;
    uint64_t SymbolSize;
    // Getting symbol size is linear for Mach-O files, so assume that symbol
    // occupies the memory range up to the following symbol.
    if (isa<MachOObjectFile>(Obj))
      SymbolSize = 0;
    else if (error(si->getSize(SymbolSize)) ||
             SymbolSize == UnknownAddressOrSize)
      continue;
    StringRef SymbolName;
    if (error(si->getName(SymbolName)))
      continue;
    // Mach-O symbol table names have leading underscore, skip it.
    if (Module->isMachO() && SymbolName.size() > 0 && SymbolName[0] == '_')
      SymbolName = SymbolName.drop_front();
    // FIXME: If a function has alias, there are two entries in symbol table
    // with same address size. Make sure we choose the correct one.
    SymbolMapTy &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects;
    SymbolDesc SD = { SymbolAddress, SymbolSize };
    M.insert(std::make_pair(SD, SymbolName));
  }
}

bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
                                        std::string &Name, uint64_t &Addr,
                                        uint64_t &Size) const {
  const SymbolMapTy &M = Type == SymbolRef::ST_Function ? Functions : Objects;
  if (M.empty())
    return false;
  SymbolDesc SD = { Address, Address };
  SymbolMapTy::const_iterator it = M.upper_bound(SD);
  if (it == M.begin())
    return false;
  --it;
  if (it->first.Size != 0 && it->first.Addr + it->first.Size <= Address)
    return false;
  Name = it->second.str();
  Addr = it->first.Addr;
  Size = it->first.Size;
  return true;
}

DILineInfo ModuleInfo::symbolizeCode(
    uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
  DILineInfo LineInfo;
  if (DebugInfoContext) {
    LineInfo = DebugInfoContext->getLineInfoForAddress(
        ModuleOffset, getDILineInfoSpecifierFlags(Opts));
  }
  // Override function name from symbol table if necessary.
  if (Opts.PrintFunctions && Opts.UseSymbolTable) {
    std::string FunctionName;
    uint64_t Start, Size;
    if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
                               FunctionName, Start, Size)) {
      patchFunctionNameInDILineInfo(FunctionName, LineInfo);
    }
  }
  return LineInfo;
}

DIInliningInfo ModuleInfo::symbolizeInlinedCode(
    uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
  DIInliningInfo InlinedContext;
  if (DebugInfoContext) {
    InlinedContext = DebugInfoContext->getInliningInfoForAddress(
        ModuleOffset, getDILineInfoSpecifierFlags(Opts));
  }
  // Make sure there is at least one frame in context.
  if (InlinedContext.getNumberOfFrames() == 0) {
    InlinedContext.addFrame(DILineInfo());
  }
  // Override the function name in lower frame with name from symbol table.
  if (Opts.PrintFunctions && Opts.UseSymbolTable) {
    DIInliningInfo PatchedInlinedContext;
    for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) {
      DILineInfo LineInfo = InlinedContext.getFrame(i);
      if (i == n - 1) {
        std::string FunctionName;
        uint64_t Start, Size;
        if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
                                   FunctionName, Start, Size)) {
          patchFunctionNameInDILineInfo(FunctionName, LineInfo);
        }
      }
      PatchedInlinedContext.addFrame(LineInfo);
    }
    InlinedContext = PatchedInlinedContext;
  }
  return InlinedContext;
}

bool ModuleInfo::symbolizeData(uint64_t ModuleOffset, std::string &Name,
                               uint64_t &Start, uint64_t &Size) const {
  return getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset, Name, Start,
                                Size);
}

const char LLVMSymbolizer::kBadString[] = "??";

std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
                                          uint64_t ModuleOffset) {
  ModuleInfo *Info = getOrCreateModuleInfo(ModuleName);
  if (Info == 0)
    return printDILineInfo(DILineInfo());
  if (Opts.PrintInlining) {
    DIInliningInfo InlinedContext =
        Info->symbolizeInlinedCode(ModuleOffset, Opts);
    uint32_t FramesNum = InlinedContext.getNumberOfFrames();
    assert(FramesNum > 0);
    std::string Result;
    for (uint32_t i = 0; i < FramesNum; i++) {
      DILineInfo LineInfo = InlinedContext.getFrame(i);
      Result += printDILineInfo(LineInfo);
    }
    return Result;
  }
  DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts);
  return printDILineInfo(LineInfo);
}

std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
                                          uint64_t ModuleOffset) {
  std::string Name = kBadString;
  uint64_t Start = 0;
  uint64_t Size = 0;
  if (Opts.UseSymbolTable) {
    if (ModuleInfo *Info = getOrCreateModuleInfo(ModuleName)) {
      if (Info->symbolizeData(ModuleOffset, Name, Start, Size) && Opts.Demangle)
        Name = DemangleName(Name);
    }
  }
  std::stringstream ss;
  ss << Name << "\n" << Start << " " << Size << "\n";
  return ss.str();
}

void LLVMSymbolizer::flush() {
  DeleteContainerSeconds(Modules);
  DeleteContainerPointers(ParsedBinariesAndObjects);
  BinaryForPath.clear();
  ObjectFileForArch.clear();
}

static std::string getDarwinDWARFResourceForPath(const std::string &Path) {
  StringRef Basename = sys::path::filename(Path);
  const std::string &DSymDirectory = Path + ".dSYM";
  SmallString<16> ResourceName = StringRef(DSymDirectory);
  sys::path::append(ResourceName, "Contents", "Resources", "DWARF");
  sys::path::append(ResourceName, Basename);
  return ResourceName.str();
}

LLVMSymbolizer::BinaryPair
LLVMSymbolizer::getOrCreateBinary(const std::string &Path) {
  BinaryMapTy::iterator I = BinaryForPath.find(Path);
  if (I != BinaryForPath.end())
    return I->second;
  Binary *Bin = 0;
  Binary *DbgBin = 0;
  OwningPtr<Binary> ParsedBinary;
  OwningPtr<Binary> ParsedDbgBinary;
  if (!error(createBinary(Path, ParsedBinary))) {
    // Check if it's a universal binary.
    Bin = ParsedBinary.take();
    ParsedBinariesAndObjects.push_back(Bin);
    if (Bin->isMachO() || Bin->isMachOUniversalBinary()) {
      // On Darwin we may find DWARF in separate object file in
      // resource directory.
      const std::string &ResourcePath =
          getDarwinDWARFResourceForPath(Path);
      bool ResourceFileExists = false;
      if (!sys::fs::exists(ResourcePath, ResourceFileExists) &&
          ResourceFileExists &&
          !error(createBinary(ResourcePath, ParsedDbgBinary))) {
        DbgBin = ParsedDbgBinary.take();
        ParsedBinariesAndObjects.push_back(DbgBin);
      }
    }
  }
  if (DbgBin == 0)
    DbgBin = Bin;
  BinaryPair Res = std::make_pair(Bin, DbgBin);
  BinaryForPath[Path] = Res;
  return Res;
}

ObjectFile *
LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, const std::string &ArchName) {
  if (Bin == 0)
    return 0;
  ObjectFile *Res = 0;
  if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin)) {
    ObjectFileForArchMapTy::iterator I = ObjectFileForArch.find(
        std::make_pair(UB, ArchName));
    if (I != ObjectFileForArch.end())
      return I->second;
    OwningPtr<ObjectFile> ParsedObj;
    if (!UB->getObjectForArch(Triple(ArchName).getArch(), ParsedObj)) {
      Res = ParsedObj.take();
      ParsedBinariesAndObjects.push_back(Res);
    }
    ObjectFileForArch[std::make_pair(UB, ArchName)] = Res;
  } else if (Bin->isObject()) {
    Res = cast<ObjectFile>(Bin);
  }
  return Res;
}

ModuleInfo *
LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
  ModuleMapTy::iterator I = Modules.find(ModuleName);
  if (I != Modules.end())
    return I->second;
  std::string BinaryName = ModuleName;
  std::string ArchName = Opts.DefaultArch;
  size_t ColonPos = ModuleName.find_last_of(':');
  // Verify that substring after colon form a valid arch name.
  if (ColonPos != std::string::npos) {
    std::string ArchStr = ModuleName.substr(ColonPos + 1);
    if (Triple(ArchStr).getArch() != Triple::UnknownArch) {
      BinaryName = ModuleName.substr(0, ColonPos);
      ArchName = ArchStr;
    }
  }
  BinaryPair Binaries = getOrCreateBinary(BinaryName);
  ObjectFile *Obj = getObjectFileFromBinary(Binaries.first, ArchName);
  ObjectFile *DbgObj = getObjectFileFromBinary(Binaries.second, ArchName);

  if (Obj == 0) {
    // Failed to find valid object file.
    Modules.insert(make_pair(ModuleName, (ModuleInfo *)0));
    return 0;
  }
  DIContext *Context = DIContext::getDWARFContext(DbgObj);
  assert(Context);
  ModuleInfo *Info = new ModuleInfo(Obj, Context);
  Modules.insert(make_pair(ModuleName, Info));
  return Info;
}

std::string LLVMSymbolizer::printDILineInfo(DILineInfo LineInfo) const {
  // By default, DILineInfo contains "<invalid>" for function/filename it
  // cannot fetch. We replace it to "??" to make our output closer to addr2line.
  static const std::string kDILineInfoBadString = "<invalid>";
  std::stringstream Result;
  if (Opts.PrintFunctions) {
    std::string FunctionName = LineInfo.getFunctionName();
    if (FunctionName == kDILineInfoBadString)
      FunctionName = kBadString;
    else if (Opts.Demangle)
      FunctionName = DemangleName(FunctionName);
    Result << FunctionName << "\n";
  }
  std::string Filename = LineInfo.getFileName();
  if (Filename == kDILineInfoBadString)
    Filename = kBadString;
  Result << Filename << ":" << LineInfo.getLine() << ":" << LineInfo.getColumn()
         << "\n";
  return Result.str();
}

#if !defined(_MSC_VER)
// Assume that __cxa_demangle is provided by libcxxabi (except for Windows).
extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
                                size_t *length, int *status);
#endif

std::string LLVMSymbolizer::DemangleName(const std::string &Name) {
#if !defined(_MSC_VER)
  int status = 0;
  char *DemangledName = __cxa_demangle(Name.c_str(), 0, 0, &status);
  if (status != 0)
    return Name;
  std::string Result = DemangledName;
  free(DemangledName);
  return Result;
#else
  return Name;
#endif
}

} // namespace symbolize
} // namespace llvm
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "burg.hpp"

#include <algorithm>
#include <cassert>
#include <iostream>
#include <iterator>
#include <vector>

// Test zohar_linear_solve routine against an Octave-provided reference
int main(int argc, char *argv[])
{
    using namespace std;

    vector<double> a;
    a.push_back( 2);
    a.push_back( 3);
    a.push_back( 5);
    a.push_back( 7);
    a.push_back(11);
    a.push_back(13);
    a.push_back(17);

    cout << "Topmost row of Toeplitz matrix is: \n\t1 ";
    copy(a.begin(), a.end(), ostream_iterator<double>(cout," "));
    cout << endl;

    vector<double> r;
    r.push_back(  2);
    r.push_back(  4);
    r.push_back(  8);
    r.push_back( 16);
    r.push_back( 32);
    r.push_back( 64);
    r.push_back(128);

    assert(a.size() == r.size());

    cout << "Leftmost column of Toeplitz matrix is: \n\t1 ";
    copy(r.begin(), r.end(), ostream_iterator<double>(cout," "));
    cout << endl;

    vector<double> d;
    d.push_back(1);
    d.push_back(2);
    d.push_back(3);
    d.push_back(4);
    d.push_back(5);
    d.push_back(6);
    d.push_back(7);
    d.push_back(8);

    assert(d.size() == a.size() + 1);

    cout << "Right hand size data is:\n\t";
    copy(d.begin(), d.end(), ostream_iterator<double>(cout," "));
    cout << endl;

    vector<double> exp;
    exp.push_back(-17./27);
    exp.push_back(  4./27);
    exp.push_back( 32./ 9);
    exp.push_back(- 5./ 3);
    exp.push_back(  0.   );
    exp.push_back(- 2.   );
    exp.push_back(- 1.   );
    exp.push_back(  2.   );

    assert(exp.size() == d.size());

    cout << "Expected solution is:\n\t";
    copy(exp.begin(), exp.end(), ostream_iterator<double>(cout," "));
    cout << endl;

    cout << "Solution computed by zohar_linear_solve is:\n\t";
    zohar_linear_solve(a.begin(), a.end(), r.begin(), d.begin());
    copy(d.begin(), d.end(), ostream_iterator<double>(cout," "));
    cout << endl;

    vector<double> err(exp.size());
    for (size_t i = 0; i < err.size(); ++i) {
        err[i] = exp[i] - d[i];
    }

    cout << "Term-by-term errors are:\n\t";
    copy(err.begin(), err.end(), ostream_iterator<double>(cout," "));
    cout << endl;

    double sserr = 0;
    for (size_t i = 0; i < exp.size(); ++i) {
        sserr += err[i]*err[i];
    }
    cout << "Sum of the squared errors is:\n\t" << sserr << endl;

    return 0;
}
<commit_msg>change the error display metric<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "burg.hpp"

#include <algorithm>
#include <cassert>
#include <cmath>
#include <iostream>
#include <iterator>
#include <vector>

// Test zohar_linear_solve routine against an Octave-provided reference
int main(int argc, char *argv[])
{
    using namespace std;

    vector<double> a;
    a.push_back( 2);
    a.push_back( 3);
    a.push_back( 5);
    a.push_back( 7);
    a.push_back(11);
    a.push_back(13);
    a.push_back(17);

    cout << "Topmost row of Toeplitz matrix is: \n\t1 ";
    copy(a.begin(), a.end(), ostream_iterator<double>(cout," "));
    cout << endl;

    vector<double> r;
    r.push_back(  2);
    r.push_back(  4);
    r.push_back(  8);
    r.push_back( 16);
    r.push_back( 32);
    r.push_back( 64);
    r.push_back(128);

    assert(a.size() == r.size());

    cout << "Leftmost column of Toeplitz matrix is: \n\t1 ";
    copy(r.begin(), r.end(), ostream_iterator<double>(cout," "));
    cout << endl;

    vector<double> d;
    d.push_back(1);
    d.push_back(2);
    d.push_back(3);
    d.push_back(4);
    d.push_back(5);
    d.push_back(6);
    d.push_back(7);
    d.push_back(8);

    assert(d.size() == a.size() + 1);

    cout << "Right hand size data is:\n\t";
    copy(d.begin(), d.end(), ostream_iterator<double>(cout," "));
    cout << endl;

    vector<double> exp;
    exp.push_back(-17./27);
    exp.push_back(  4./27);
    exp.push_back( 32./ 9);
    exp.push_back(- 5./ 3);
    exp.push_back(  0.   );
    exp.push_back(- 2.   );
    exp.push_back(- 1.   );
    exp.push_back(  2.   );

    assert(exp.size() == d.size());

    cout << "Expected solution is:\n\t";
    copy(exp.begin(), exp.end(), ostream_iterator<double>(cout," "));
    cout << endl;

    cout << "Solution computed by zohar_linear_solve is:\n\t";
    zohar_linear_solve(a.begin(), a.end(), r.begin(), d.begin());
    copy(d.begin(), d.end(), ostream_iterator<double>(cout," "));
    cout << endl;

    vector<double> err(exp.size());
    for (size_t i = 0; i < err.size(); ++i) {
        err[i] = exp[i] - d[i];
    }

    cout << "Term-by-term errors are:\n\t";
    copy(err.begin(), err.end(), ostream_iterator<double>(cout," "));
    cout << endl;

    double abserr = 0;
    for (size_t i = 0; i < exp.size(); ++i) abserr += std::abs(err[i]);
    cout << "Sum of the absolute errors is:\n\t" << abserr << endl;

    return 0;
}
<|endoftext|>


<commit_before>#include "bvsd.h"

/** Main function, creates interactive loop. */
int main(const int argc, const char** argv)
{
	signal(SIGINT, mainSignal);
	signal(SIGSEGV, mainSignal);
	signal(SIGALRM, mainSignal);

	bvs = new BVS::BVS(argc, argv, &shutdownFunction);

	LOG(2, "loading modules!");
	bvs->loadModules();

	LOG(2, "connecting modules!");
	bvs->connectAllModules();

	LOG(2, "starting!");
	bvs->start();

	bvs->run();

	std::string input;
	while (true)
	{
		std::getline(std::cin, input);
		if (std::cin.eof()) input = "q";

		if (input == "r" || input == "run" || input == "c" || input == "continue")
		{
			LOG(2, "RUN!!!");
			bvs->run();
		}
		else if (input.empty() || input == "s" || input == "step")
		{
			LOG(2, "STEP!!!");
			bvs->step();
		}
		else if (input == "p" || input == "pause")
		{
			LOG(2, "PAUSING!!!");
			bvs->pause();
		}
		else if (input.substr(0,2) == "hs" || input.substr(0, 7) == "hotswap")
		{
			size_t delimiter = input.find_first_of(" ");
			input.erase(0, delimiter+1);
			if (input.empty() || delimiter==std::string::npos) std::cout << "ERROR: no module ID given!" << std::endl;
			else bvs->hotSwap(input);
		}
		else if (input == "q" || input == "quit")
		{
			LOG(2, "quitting...");
			bvs->quit();
			LOG(2, "finished!");
			break;
		}
		else if (input == "h" || input == "help")
		{
			std::cout << "usage:" << std::endl;
			std::cout << "   r|run            run system until paused" << std::endl;
			std::cout << "   c|continue       same as run" << std::endl;
			std::cout << "   s|step           advance system by one step" << std::endl;
			std::cout << "   p|pause          pause(stop) system" << std::endl;
			std::cout << "   hs|hotswap <arg> HotSwap(TM) <moduleID>" << std::endl;
			std::cout << "   q|quit           shutdown system and quit" << std::endl;
			std::cout << "   h|help           show help" << std::endl;
		}
		else
		{
			std::cout << ">>> unknown command: " << input << std::endl << ">>> for help press 'h<enter>'!" << std::endl;
		}
	}

	delete bvs;

	return 0;
}

void mainSignal(int sig)
{
	switch (sig)
	{
		case SIGINT:
			LOG(2, "Caught 'Ctrl-C', quitting!");
			break;
		case SIGSEGV:
			LOG(2, "Caught segmentation fault...!");
			void *msgs[100];
			size_t size;
			size = backtrace(msgs, 100);
			fprintf(stderr, "\n\n\nCaught signal %d (%s)!\n\n", sig, strsignal(sig));
			char** messages;
			messages = backtrace_symbols(msgs, size);
			for (size_t i=2; i < size && messages != NULL; ++i)
				fprintf(stderr, "[bt]: (%lu) %s\n", i-2, messages[i]);
			free(messages);
			break;
		case SIGALRM:
			LOG(2, "Shutdown requested, quitting!");
			break;
	}

	if (sig==SIGSEGV)
	{
		signal(SIGSEGV, SIG_DFL);
		raise(SIGSEGV);
	}
	else
	{
		// TODO: BUG, causes system to hang, probably because it waits for some thread to join, investigate!
		bvs->quit();
		delete bvs;
		exit(EXIT_FAILURE);
	}
}

void shutdownFunction()
{
	LOG(1,"daemon exit caused by bvs shutdown request!");
	bvs->quit();
	alarm(1); // SIGALRM after 1 second so all framework/module threads have a chance to quit
}

<commit_msg>daemon: disable shutdown function for now<commit_after>#include "bvsd.h"

/** Main function, creates interactive loop. */
int main(const int argc, const char** argv)
{
	signal(SIGINT, mainSignal);
	signal(SIGSEGV, mainSignal);
	signal(SIGALRM, mainSignal);

	//bvs = new BVS::BVS(argc, argv, &shutdownFunction); // TODO: disable shutdown function for now, also see mainSignal
	bvs = new BVS::BVS(argc, argv);

	LOG(2, "loading modules!");
	bvs->loadModules();

	LOG(2, "connecting modules!");
	bvs->connectAllModules();

	LOG(2, "starting!");
	bvs->start();

	bvs->run();

	std::string input;
	while (true)
	{
		std::getline(std::cin, input);
		if (std::cin.eof()) input = "q";

		if (input == "r" || input == "run" || input == "c" || input == "continue")
		{
			LOG(2, "RUN!!!");
			bvs->run();
		}
		else if (input.empty() || input == "s" || input == "step")
		{
			LOG(2, "STEP!!!");
			bvs->step();
		}
		else if (input == "p" || input == "pause")
		{
			LOG(2, "PAUSING!!!");
			bvs->pause();
		}
		else if (input.substr(0,2) == "hs" || input.substr(0, 7) == "hotswap")
		{
			size_t delimiter = input.find_first_of(" ");
			input.erase(0, delimiter+1);
			if (input.empty() || delimiter==std::string::npos) std::cout << "ERROR: no module ID given!" << std::endl;
			else bvs->hotSwap(input);
		}
		else if (input == "q" || input == "quit")
		{
			LOG(2, "quitting...");
			bvs->quit();
			LOG(2, "finished!");
			break;
		}
		else if (input == "h" || input == "help")
		{
			std::cout << "usage:" << std::endl;
			std::cout << "   r|run            run system until paused" << std::endl;
			std::cout << "   c|continue       same as run" << std::endl;
			std::cout << "   s|step           advance system by one step" << std::endl;
			std::cout << "   p|pause          pause(stop) system" << std::endl;
			std::cout << "   hs|hotswap <arg> HotSwap(TM) <moduleID>" << std::endl;
			std::cout << "   q|quit           shutdown system and quit" << std::endl;
			std::cout << "   h|help           show help" << std::endl;
		}
		else
		{
			std::cout << ">>> unknown command: " << input << std::endl << ">>> for help press 'h<enter>'!" << std::endl;
		}
	}

	delete bvs;

	return 0;
}

void mainSignal(int sig)
{
	switch (sig)
	{
		case SIGINT:
			LOG(2, "Caught 'Ctrl-C', quitting!");
			break;
		case SIGSEGV:
			LOG(2, "Caught segmentation fault...!");
			void *msgs[100];
			size_t size;
			size = backtrace(msgs, 100);
			fprintf(stderr, "\n\n\nCaught signal %d (%s)!\n\n", sig, strsignal(sig));
			char** messages;
			messages = backtrace_symbols(msgs, size);
			for (size_t i=2; i < size && messages != NULL; ++i)
				fprintf(stderr, "[bt]: (%lu) %s\n", i-2, messages[i]);
			free(messages);
			break;
		case SIGALRM:
			LOG(2, "Shutdown requested, quitting!");
			break;
	}

	if (sig==SIGSEGV)
	{
		signal(SIGSEGV, SIG_DFL);
		raise(SIGSEGV);
	}
	else
	{
		// TODO: BUG, causes system to hang, probably because it waits for some thread to join, investigate!
		bvs->quit();
		delete bvs;
		exit(EXIT_FAILURE);
	}
}

void shutdownFunction()
{
	LOG(1,"daemon exit caused by bvs shutdown request!");
	bvs->quit();
	alarm(1); // SIGALRM after 1 second so all framework/module threads have a chance to quit
}

<|endoftext|>


<commit_before>#include <sigma/util/filesystem.hpp>

#include <filesystem>

namespace sigma {
namespace filesystem {
    bool contains_file(std::filesystem::path directory, std::filesystem::path file)
    {
        auto dbegin = directory.begin();
        auto dend = directory.end();
        auto fbegin = file.begin();
        auto fend = file.end();

        auto directory_size = std::distance(dbegin, dend);
        auto file_size = std::distance(fbegin, fend);
        if (directory_size > file_size)
            return false;

        return std::equal(dbegin, dend, fbegin);
    }

    std::filesystem::path make_relative(std::filesystem::path directory, std::filesystem::path file)
    {
        auto dbegin = directory.begin();
        auto fbegin = file.begin();
        auto fend = file.end();

        while (*dbegin == *fbegin) {
            dbegin++;
            fbegin++;
        }
        std::filesystem::path output;
        do {
            output = output / (*fbegin).string();
            fbegin++;
        } while (fbegin != fend);
        return output;
    }

    bool is_hidden(const std::filesystem::path& path)
    {
        auto name = path.filename().string();
        return !name.empty() && name != ".." && name != "." && name[0] == '.';
    }
}
}
<commit_msg>Bye bye boost part1.5<commit_after>#include <sigma/util/filesystem.hpp>

#include <filesystem>

namespace sigma {
namespace filesystem {
    bool contains_file(std::filesystem::path directory, std::filesystem::path file)
    {
        auto dbegin = directory.begin();
        auto dend = directory.end();
        auto fbegin = file.begin();
        auto fend = file.end();

        auto directory_size = std::distance(dbegin, dend);
        auto file_size = std::distance(fbegin, fend);
        if (directory_size > file_size)
            return false;

        return std::equal(dbegin, dend, fbegin);
    }

    std::filesystem::path make_relative(std::filesystem::path directory, std::filesystem::path file)
    {
        auto dbegin = directory.begin();
        auto dend = directory.end();
        auto fbegin = file.begin();
        auto fend = file.end();

        while (dbegin != dend && fbegin != fend && *dbegin == *fbegin) {
            dbegin++;
            fbegin++;
        }
        std::filesystem::path output;
        do {
            output = output / (*fbegin).string();
            fbegin++;
        } while (fbegin != fend);
        return output;
    }

    bool is_hidden(const std::filesystem::path& path)
    {
        auto name = path.filename().string();
        return !name.empty() && name != ".." && name != "." && name[0] == '.';
    }
}
}
<|endoftext|>