Commit b8bdfff3 authored by Augustin Degomme's avatar Augustin Degomme

Features :

- add a second thread to separate OTF file operations and trace operations : not as much parallelism as in Paje as file operations are more efficient for OTF (as for Paje parsing, flag MT_PARSING)

- multithreaded loading of serialized files : moves loading from the main thread to multiple threads, as for serialization.

- beginning of the work with MPI : work can now be distributed and several intervals loaded from several machines and displayed there. 

How to use: the flag USE_MPI must be set, links  -lboost_mpi -lmpi -lmpi_cxx must be added in src.pro

mpicc and mpic++ have to be used instead of gcc and g++. This can be set manually in src/makefile, but will be reseted by the global makefile. Another solution is to add

unix{
QMAKESPEC = mpicc
QMAKE_CXX = mpic++
}

to the src.pro file.

To launch on a single machine :
mpirun -np nprocess vite path/to/file.vite2/configure

on several machines with separated screens and a machinefile to list them :
- allow ssh authentification without password (by key)
- allow display on each distant machine with "xhost +"
- have a split folder in a folder accessible with the same path for each machine (nfs or local)
- have vite in the path for each machine
- use mpirun -np nprocess -hostfile machinefile -mca orte_rsh_agent "ssh -X" -xDISPLAY=:0.0 vite -tInterval path/to/file.vite

This will split the given interval in nprocess parts and send them for display to the various nodes described, displaying on their local display
parent 7be547a8
......@@ -283,8 +283,8 @@ if [ $with_otf -ge 1 ]; then
exit;
else
defines="$defines WITH_OTF"
sources="$sources parser/ParserOTF.cpp parser/ParserEventOTF.cpp parser/ParserDefinitionOTF.cpp"
headers="$headers parser/ParserOTF.hpp parser/ParserEventOTF.hpp parser/ParserDefinitionOTF.hpp"
sources="$sources parser/ParserOTF.cpp parser/ParserEventOTF.cpp parser/OTFTraceBuilderThread.cpp parser/ParserDefinitionOTF.cpp parser/mt_ParserOTF.cpp parser/mt_ParserEventOTF.cpp"
headers="$headers parser/ParserOTF.hpp parser/ParserEventOTF.hpp parser/OTFTraceBuilderThread.hpp parser/ParserDefinitionOTF.hpp parser/mt_ParserOTF.hpp parser/mt_ParserEventOTF.hpp"
includepath="$includepath $otfincdir"
libs="$libs -L$otflibdir $otflibdir/libotf.a"
fi
......
......@@ -282,6 +282,8 @@ IF(VITE_ENABLE_OTF)
parser/ParserDefinitionOTF.hpp
parser/ParserEventOTF.hpp
parser/ParserOTF.hpp
parser/mt_ParserEventOTF.hpp
parser/mt_ParserOTF.hpp
)
SET(VITE_SRCS
......@@ -289,6 +291,8 @@ IF(VITE_ENABLE_OTF)
parser/ParserDefinitionOTF.cpp
parser/ParserEventOTF.cpp
parser/ParserOTF.cpp
parser/mt_ParserEventOTF.cpp
parser/mt_ParserOTF.cpp
)
INCLUDE_DIRECTORIES(${OTF_INCLUDE_DIR})
......
......@@ -86,6 +86,7 @@ bool Info::Splitter::load_splitted = false;
bool Info::Splitter::preview = false;
std::string Info::Splitter::path ;
std::string Info::Splitter::filename ;
std::string Info::Splitter::xml_filename ;
Element_pos Info::Splitter::_x_min = 0.0;
Element_pos Info::Splitter::_x_max = 0.0;
......
......@@ -305,6 +305,10 @@ public:
*/
static std::string filename;
/*!
* \brief filename of the node selection file, used to select nodes to display in PArserSplitted
*/
static std::string xml_filename;
/*!
* \brief min time we want to load
*/
static Element_pos _x_min;
......
......@@ -131,6 +131,11 @@
#endif
#ifdef USE_MPI
#include <boost/mpi/environment.hpp>
#include <boost/mpi/communicator.hpp>
#endif
using namespace std;
#define message *Message::get_instance() << "(" << __FILE__ << " l." << __LINE__ << "): "
......@@ -170,6 +175,10 @@ Core::Core(int &argc, char ** argv){
Message::set_interface(this);/* define which interface will receive messages */
_state = get_state(argc, argv);
#ifdef USE_MPI
boost::mpi::environment env(argc, argv);
#endif
if (_state!= _STATE_EXPORT_FILE)
app = new QApplication(argc, argv);/* create the Qt application */
......@@ -298,8 +307,10 @@ bool Core::draw_trace(const string & filename, const int format) {
}
#if defined(USE_ITC) && defined(BOOST_SERIALIZE)
Info::Splitter::path=QFileInfo(_file_opened.c_str()).dir().path().toStdString();
Info::Splitter::filename=QFileInfo(_file_opened.c_str()).baseName().toStdString();
if(Info::Splitter::path.empty())Info::Splitter::path=QFileInfo(_file_opened.c_str()).dir().path().toStdString();
if(Info::Splitter::filename.empty())Info::Splitter::filename=QFileInfo(_file_opened.c_str()).baseName().toStdString();
if(Info::Splitter::xml_filename.empty() && !_xml_config_file.empty())Info::Splitter::xml_filename=_xml_config_file;
if(Info::Splitter::split==true){
std::stringstream str;
str<<Info::Splitter::path<<"/"<<Info::Splitter::filename;
......@@ -310,13 +321,56 @@ bool Core::draw_trace(const string & filename, const int format) {
#endif
}
Info::Splitter::_x_min = _time_start;
if((Info::Splitter::_x_max==0.0)&&(Info::Splitter::_x_min==0.0)){
#ifdef USE_MPI
if (_world.rank() == 0) {
double min = _time_start;
double max = 0;
if(_time_end == 0.) {
max = _trace->get_max_date().get_value();
}
else {
max =_time_end;
}
double interval = (max-min)/ _world.size();
for(int i=1;i<_world.size(); i++){
//send the new working interval for each node
// double out_msg[2]={min+i*interval,min+(i+1)*interval};
_world.send(i, 0,min+i*interval );
_world.send(i, 1,min+(i+1)*interval );
}
//0 displays the first interval
_time_start=min;
_time_end=min+interval;
if(_time_end == 0.) {
Info::Splitter::_x_max = _trace->get_max_date().get_value();
}
else {
Info::Splitter::_x_max =_time_end;
} else {
double msg[2];
_world.recv(0, 0, msg[0]);
_world.recv(0, 1, msg[1]);
_time_start=msg[0];
_time_end=msg[1];
}
#endif
Info::Splitter::_x_min = _time_start;
if(_time_end == 0.) {
Info::Splitter::_x_max = _trace->get_max_date().get_value();
}
else {
Info::Splitter::_x_max =_time_end;
}
}
#endif
......@@ -353,16 +407,7 @@ bool Core::draw_trace(const string & filename, const int format) {
// if(finish_trace_after_parse) {
// unsigned long long before = getCurrentTime();
#if defined(USE_ITC) && defined(BOOST_SERIALIZE)
if(Info::Splitter::load_splitted==true){
if(Info::Splitter::_x_max == 0)Info::Splitter::preview = true; //we are in the preview mode
if(Info::Splitter::preview==true)_trace->loadPreview();
else {
Interval* i= new Interval(Info::Splitter::_x_min,Info::Splitter::_x_max);
_trace->updateTrace(i);
}
}else{
#endif
......@@ -387,12 +432,12 @@ bool Core::draw_trace(const string & filename, const int format) {
*Message::get_instance() << QObject::tr("Splitting was asked but neither USE_ITC nor BOOST_SERIALIZE flags were set ").toStdString() << Message::ende;
#endif
}
#if defined(USE_ITC) && defined(BOOST_SERIALIZE)
//#if defined(USE_ITC) && defined(BOOST_SERIALIZE)
finished.wait(&mutex);
}
#endif
// }
// #endif
parsing_finished=true;
}
cout << QObject::tr("Loading of the trace : ").toStdString() << loaded << "%" ;
......
......@@ -67,6 +67,10 @@ class QCoreApplication;
class QString;
#include <interface/Interface_graphic.hpp>
#include <QObject>
#ifdef USE_MPI
#include <boost/mpi/environment.hpp>
#include <boost/mpi/communicator.hpp>
#endif
//#include "render/Render.hpp"
//#include "interface/Interface.hpp"
......@@ -286,6 +290,11 @@ protected:
#endif
//Render<Render_opengl>* _render_opengl;
#ifdef USE_MPI
boost::mpi::communicator _world;
#endif
/*!
* \brief Contains the SVG render instance.
*/
......
......@@ -616,9 +616,15 @@ void Interface_graphic::on_export_file_triggered(){
void Interface_graphic::on_reload_triggered() {
if(_is_rendering_trace) {
Element_pos zoom[2]={Info::Splitter::_x_min,Info::Splitter::_x_max};
_core->launch_action(Core::_STATE_RELEASE_RENDER_AREA);
_core->draw_trace(_trace_path, Core::_DRAW_OPENGL);
if(Info::Splitter::_x_max!=0.0)_core->launch_action(Core:: _STATE_ZOOM_IN_AN_INTERVAL, &zoom);
_core->launch_action(Core:: _STATE_RENDER_UPDATE);
//update the interval selection display
if(_ui_interval_selection!=NULL)_ui_interval_selection->update_values();
}
......
This diff is collapsed.
/*
** This file is part of the ViTE project.
**
** This software is governed by the CeCILL-A license under French law
** and abiding by the rules of distribution of free software. You can
** use, modify and/or redistribute the software under the terms of the
** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following
** URL: "http://www.cecill.info".
**
** As a counterpart to the access to the source code and rights to copy,
** modify and redistribute granted by the license, users are provided
** only with a limited warranty and the software's author, the holder of
** the economic rights, and the successive licensors have only limited
** liability.
**
** In this respect, the user's attention is drawn to the risks associated
** with loading, using, modifying and/or developing or reproducing the
** software by the user in light of its specific status of free software,
** that may mean that it is complicated to manipulate, and that also
** therefore means that it is reserved for developers and experienced
** professionals having in-depth computer knowledge. Users are therefore
** encouraged to load and test the software's suitability as regards
** their requirements in conditions enabling the security of their
** systems and/or data to be ensured and, more generally, to use and
** operate it in the same conditions as regards security.
**
** The fact that you are presently reading this means that you have had
** knowledge of the CeCILL-A license and that you accept its terms.
**
**
** ViTE developers are (for version 0.* to 1.0):
**
** - COULOMB Kevin
** - FAVERGE Mathieu
** - JAZEIX Johnny
** - LAGRASSE Olivier
** - MARCOUEILLE Jule
** - NOISETTE Pascal
** - REDONDY Arthur
** - VUCHENER Clément
**
*/
/*!
*\file ParserEventOTF.hpp
*\brief This file contains the event parser used by the ParserOTF.
*/
#ifndef OTFTraceBuilderThread_HPP
#define OTFTraceBuilderThread_HPP
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <list>
/* -- */
#include <otf.h>
/* -- */
#include "common/Errors.hpp"
/* -- */
#include "trace/values/Values.hpp"
#include "trace/EntityValue.hpp"
#include "trace/EntityTypes.hpp"
#include "trace/Entitys.hpp"
#include "trace/Trace.hpp"
/* -- */
#include "parser/ParserDefinitionOTF.hpp"
#include <QWaitCondition>
#include <QSemaphore>
#include <QObject>
#include <QMutex>
#include <QThread>
/*!
* \struct Marker
* \brief Contains the definition of a marker
*/
struct Marker {
/*!
* \brief Name of the marker
*/
std::string _name;
/*!
* \brief stream where is defined this marker
*/
uint32_t _stream;
/*!
* \brief type of the marker
*/
uint32_t _type;
};
typedef struct OTF_Trace_builder_struct{
int _id;
int (*func)(OTF_Trace_builder_struct*);
void *trace;
uint64_t time;
uint32_t process;
uint32_t process2;
uint64_t value;
const char *text;
uint32_t group;
uint32_t type;
uint32_t length;
uint32_t source;
OTF_Trace_builder_struct(){ }
}OTF_Trace_builder_struct;
//class to handle the real work in a second thread
class OTFTraceBuilderThread: public QObject{
Q_OBJECT
private:
QWaitCondition* _cond;
bool _is_finished;
QSemaphore * _freeSlots;
QMutex* _mutex;
static std::map <const String, Container *, String::less_than> _containers;
static std::map<uint32_t, Marker > _marker;
public:
/* static int handler_begin_process(void *trace, uint64_t time, uint32_t process);
static int handler_end_process (void *trace, uint64_t time, uint32_t process);
static int handler_enter (void *trace, uint64_t time, uint32_t function, uint32_t process, uint32_t process2);
static int handler_leave (void *trace, uint64_t time, uint32_t function, uint32_t process, uint32_t process2);
static int handler_counter(void *trace, uint64_t time, uint32_t process, uint32_t process2, uint64_t value);
static int handler_defmarker(void *trace, uint32_t process, uint32_t token, const char *name, uint32_t type);
static int handler_marker(void *trace, uint64_t time, uint32_t process, uint32_t token, const char *text);
static int handler_send_message (void *trace, uint64_t time, uint32_t process, uint32_t receiver, uint32_t group, uint32_t type, uint32_t length, uint32_t source);
static int handler_receive_message (void *trace, uint64_t time, uint32_t process, uint32_t sendProc, uint32_t group, uint32_t type, uint32_t length, uint32_t source);
*/
static int handler_begin_process(OTF_Trace_builder_struct* tb_struct);
static int handler_end_process (OTF_Trace_builder_struct* tb_struct);
static int handler_enter (OTF_Trace_builder_struct* tb_struct);
static int handler_leave (OTF_Trace_builder_struct* tb_struct);
static int handler_counter(OTF_Trace_builder_struct* tb_struct);
static int handler_defmarker(OTF_Trace_builder_struct* tb_struct);
static int handler_marker(OTF_Trace_builder_struct* tb_struct);
static int handler_send_message (OTF_Trace_builder_struct* tb_struct);
static int handler_receive_message (OTF_Trace_builder_struct* tb_struct);
public slots:
void build_trace(int n, OTF_Trace_builder_struct* tb_struct);
void build_finished();
public:
/*!
* \fn ParserEventOTF()
* \brief constructor
*/
OTFTraceBuilderThread(QWaitCondition* cond, QSemaphore * freeSlots, QMutex* mutex);
/*!
* \fn ~ParserEventOTF()
* \brief constructor
*/
~OTFTraceBuilderThread();
};
#endif
......@@ -55,14 +55,21 @@
#include "common/Message.hpp"
/* -- */
#include "parser/Parser.hpp"
#include "parser/ParserPaje.hpp"
#ifdef MT_PARSING
#include "parser/mt_ParserPaje.hpp"
#else
#include "parser/ParserPaje.hpp"
#endif
#include "parser/ParserVite.hpp"
#ifdef WITH_OTF
#include <otf.h>
#include "parser/ParserOTF.hpp"
#include <otf.h>
#ifdef MT_PARSING
#include "parser/mt_ParserOTF.hpp"
#else
#include "parser/ParserOTF.hpp"
#endif
#endif //WITH_OTF
#ifdef WITH_TAU
......@@ -100,7 +107,11 @@ bool ParserFactory::create(Parser **parser,
}
else if(ext == ".otf") {
#ifdef WITH_OTF
#ifdef MT_PARSING
*parser = new mt_ParserOTF(filename);
#else
*parser = new ParserOTF(filename);
#endif
#else
*Message::get_instance() << "OTF parser was not compiled. Use parser Paje by default" << Message::endw;
return false;
......@@ -124,7 +135,11 @@ bool ParserFactory::create(Parser **parser,
}
if(*parser == NULL) {
*parser = new ParserPaje(filename);
#ifdef MT_PARSING
*parser = new mt_ParserPaje(filename);
#else
*parser = new ParserPaje(filename);
#endif
}
return true;
......
......@@ -11,6 +11,7 @@
#include "common/common.hpp"
#include "common/Errors.hpp"
#include "common/Info.hpp"
#include "common/Message.hpp"
/* -- */
#if defined(USE_ITC) && defined(BOOST_SERIALIZE)
/* -- */
......@@ -29,6 +30,7 @@
#include "trace/Serializer_types.hpp"
#include "trace/Serializer_structs.hpp"
#include "trace/Serializer_container.hpp"
#include "trace/SerializerDispatcher.hpp"
#include "trace/values/Values.hpp"
#include "trace/tree/Interval.hpp"
......@@ -40,12 +42,13 @@
#include "parser/ParserSplitted.hpp"
#define message *Message::get_instance() << "(" << __FILE__ << " l." << __LINE__ << "): "
using namespace std;
ParserSplitted::ParserSplitted(){}
ParserSplitted::ParserSplitted(): _loaded_itc(0), _nb_itc(0){}
ParserSplitted::ParserSplitted(const string &filename): Parser(filename){
ParserSplitted::ParserSplitted(const string &filename): Parser(filename), _loaded_itc(0), _nb_itc(0){
}
......@@ -63,7 +66,9 @@ Info::Splitter::load_splitted=true;
//dump containers
// char* filename=(char*)malloc(128*sizeof(char));
// sprintf(filename,"%s/%s.vite", Info::Splitter::path, );
Serializer<Container>::Instance().clear();
Serializer<ContainerType>::Instance().clear();
Serializer<EntityType>::Instance().clear();
std::list<ContainerType*> conts_types;
std::list<Container*> conts;
......@@ -88,9 +93,20 @@ Info::Splitter::load_splitted=true;
//ia >> test;
// restore the schedule from the archive
ia >> conts;
// (trace.get_root_containers())->insert((trace.get_root_containers())->begin(), conts.begin(),conts.end() );
trace.set_root_containers(conts);
if(Info::Splitter::xml_filename.length()!=0)//we need to load a config from file
{
bool xml_success = trace.load_config_from_xml(QString(Info::Splitter::xml_filename.c_str()));
if(!xml_success){
message << "Error while parsing" << Info::Splitter::xml_filename << Message::ende;
}
}
std::map<Name, StateType* > _state_types;
std::map<Name, EventType* > _event_types;
std::map<Name, LinkType* > _link_types;
......@@ -114,6 +130,76 @@ Info::Splitter::load_splitted=true;
ia >>d;
trace.set_max_date(d);
//we count the number of containers to load, in order to have a pseudo relevant loaded percentage to display_build
//we should do this with ITC, but that would mean to handle all of the loading here or to have a feedback from trace and containers
{
stack<Container *> containers;
const Container::Vector* root_containers =trace.get_view_root_containers();
if(root_containers->empty())root_containers=trace.get_root_containers();
Container::VectorIt i = root_containers->begin();
Container::VectorIt const &end = root_containers->end();
for (; i != end; i++)
containers.push(*i);
while (!containers.empty()) {
Container * c = containers.top();
_nb_itc+=c->get_intervalsOfContainer()->size();
containers.pop();
{
const Container::Vector* children =c->get_view_children();
if (children->empty())children=c->get_children();
Container::VectorIt it = children->begin();
Container::VectorIt const &it_end = children->end();
for (; it != it_end; it++)
containers.push(*it);
}
}
}
if(Info::Splitter::load_splitted==true){
if(Info::Splitter::_x_max == 0)Info::Splitter::preview = true; //we are in the preview mode
if(Info::Splitter::preview==true)trace.loadPreview();
else {
Interval* interval= new Interval(Info::Splitter::_x_min,Info::Splitter::_x_max);
//trace.loadTraceInside(i);
//in order to manage the percentage of loading, do this inside parser and not in trace
stack<Container *> containers;
const Container::Vector* root_containers =trace.get_view_root_containers();
if(root_containers->empty())root_containers=trace.get_root_containers();
Container::VectorIt i = root_containers->begin();
Container::VectorIt const &end = root_containers->end();
for (; i != end; i++)
containers.push(*i);
while (!containers.empty()) {
Container * c = containers.top();
c->loadItcInside(interval);
_loaded_itc+=c->get_intervalsOfContainer()->size();//just an approximation, based on the total number of itc, and not on the number of loaded itc (maybe heavy to parse)
containers.pop();
{
const Container::Vector* children =c->get_view_children();
if (children->empty())children=c->get_children();
Container::VectorIt it = children->begin();
Container::VectorIt const &it_end = children->end();
for (; it != it_end; it++)
containers.push(*it);
}
}
SerializerDispatcher::Instance().kill_all_threads();
}
}
if(finish_trace_after_parse) {
//we need to build the display only if we are not splitting the trace
......@@ -131,6 +217,6 @@ void ParserSplitted::releasefile(){
}
float ParserSplitted::get_percent_loaded() const {
return 0.0;
return (double)_loaded_itc/(double)_nb_itc;
}
#endif
......@@ -62,6 +62,9 @@ class PajeFileManager;
*
*/
class ParserSplitted : public Parser{
int _loaded_itc;
int _nb_itc;
public:
......
/*
** This file is part of the ViTE project.
**
** This software is governed by the CeCILL-A license under French law
** and abiding by the rules of distribution of free software. You can
** use, modify and/or redistribute the software under the terms of the
** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following
** URL: "http://www.cecill.info".
**
** As a counterpart to the access to the source code and rights to copy,
** modify and redistribute granted by the license, users are provided
** only with a limited warranty and the software's author, the holder of
** the economic rights, and the successive licensors have only limited
** liability.
**
** In this respect, the user's attention is drawn to the risks associated
** with loading, using, modifying and/or developing or reproducing the
** software by the user in light of its specific status of free software,
** that may mean that it is complicated to manipulate, and that also
** therefore means that it is reserved for developers and experienced
** professionals having in-depth computer knowledge. Users are therefore
** encouraged to load and test the software's suitability as regards
** their requirements in conditions enabling the security of their
** systems and/or data to be ensured and, more generally, to use and
** operate it in the same conditions as regards security.
**
** The fact that you are presently reading this means that you have had
** knowledge of the CeCILL-A license and that you accept its terms.
**
**
** ViTE developers are (for version 0.* to 1.0):
**
** - COULOMB Kevin
** - FAVERGE Mathieu
** - JAZEIX Johnny
** - LAGRASSE Olivier
** - MARCOUEILLE Jule
** - NOISETTE Pascal
** - REDONDY Arthur
** - VUCHENER Clément
**
*/
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <list>
/* -- */
#include <otf.h>
/* -- */
#include "common/Errors.hpp"
/* -- */
#include "trace/values/Values.hpp"
#include "trace/EntityValue.hpp"
#include "trace/EntityTypes.hpp"
#include "trace/Entitys.hpp"
#include "trace/Trace.hpp"
/* -- */
#include "parser/ParserDefinitionOTF.hpp"
#include "parser/mt_ParserEventOTF.hpp"
#include "parser/OTFTraceBuilderThread.hpp"
/* -- */
using namespace std;
uint64_t mt_ParserEventOTF::_cur_time = 0;
uint64_t mt_ParserEventOTF::_min_time = 0;
uint64_t mt_ParserEventOTF::_max_time = 0;
uint64_t mt_ParserEventOTF::_n_read=0;
OTF_Trace_builder_struct* mt_ParserEventOTF::_tb_struct=NULL;
static mt_ParserEventOTF* my_address=NULL;
mt_ParserEventOTF::mt_ParserEventOTF() : _handlers(OTF_HandlerArray_open()) {
my_address=this;
}
mt_ParserEventOTF::~mt_ParserEventOTF() {
OTF_HandlerArray_close(_handlers);
// _containers.clear();
}
void mt_ParserEventOTF::set_handlers(Trace *t) {
SET_HANDLER(_handlers, handler_enter, t, OTF_ENTER_RECORD);
SET_HANDLER(_handlers, handler_leave, t, OTF_LEAVE_RECORD);
SET_HANDLER(_handlers, handler_send_message, t, OTF_SEND_RECORD);
SET_HANDLER(_handlers, handler_receive_message, t, OTF_RECEIVE_RECORD);
SET_HANDLER(_handlers, handler_begin_process, t, OTF_BEGINPROCESS_RECORD);
SET_HANDLER(_handlers, handler_end_process, t, OTF_ENDPROCESS_RECORD);
SET_HANDLER(_handlers, handler_counter, t, OTF_COUNTER_RECORD);
SET_HANDLER(_handlers, handler_defmarker, t, OTF_DEFMARKER_RECORD);
SET_HANDLER(_handlers, handler_marker, t, OTF_MARKER_RECORD);
}
int mt_ParserEventOTF::handler_begin_process(void *trace, uint64_t time, uint32_t process) {
_tb_struct[_n_read].trace=trace;
_tb_struct[_n_read].time=time;
_tb_struct[_n_read].process=process;
_tb_struct[_n_read].func=OTFTraceBuilderThread::handler_begin_process;
_n_read++;
//emit my_address->signal_handler_begin_process(trace,time,process);
return OTF_RETURN_OK;
}
/*typedef struct OTF_Trace_builder_struct{
int _id;
void (*func)(OTF_Trace_builder_struct*);
void *trace;
uint64_t time;
uint32_t process;
uint32_t process2;
uint64_t value;
const char *text;
uint32_t group;
uint32_t type;