1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2    Contributed by Oracle.
3 
4    This file is part of GNU Binutils.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20 
21 #ifndef _EEXPERIMENT_H
22 #define _EEXPERIMENT_H
23 
24 // The experiment class is responsible for managing all the data
25 //  for an individual experiment
26 
27 #include "Metric.h"
28 #include "Histable.h"
29 #include "Stats_data.h"
30 #include "DefaultMap.h"
31 #include "HeapMap.h"
32 
33 class Data_window;
34 class DbeFile;
35 class CallStack;
36 class JMethod;
37 class Sample;
38 class SegMem;
39 class LoadObject;
40 class SourceFile;
41 class UserLabel;
42 class PRBTree;
43 class Emsg;
44 class Emsgqueue;
45 struct JThread;
46 struct GCEvent;
47 class FileData;
48 class Module;
49 class Experiment;
50 template <class ITEM> class Vector;
51 
52 #define JTHREAD_DEFAULT     ((JThread*)0)
53 #define JTHREAD_NONE        ((JThread*)-1)
54 
55 // When we perform the pipelined optimization on resolve_frame_info() and add_stack()
56 // this is the number of iterations one phase works on before passing on the work to
57 // the next phase
58 
59 #define CSTCTX_CHUNK_SZ 10000
60 #define PIPELINE_QUEUE_SZ_HI 8
61 #define PIPELINE_QUEUE_SZ_LOW 2
62 
63 // the add_stack_ctx structure contains the intermediate state (context) after
64 // CSTCTX_CHUNK_SZ number of iterations to pass on the work to another thread to
65 // operate on the next stage
66 typedef struct
67 {
68   Vector<DbeInstr*> *natpcs;
69   Vector<Histable*> *jpcs;
70   long idx;
71   FramePacket *frp;
72   hrtime_t tstamp;
73   uint32_t thrid;
74   bool last_ctx;
75 } cstk_ctx;
76 
77 // To minimize threadpool overhead, the granularity of a job submitted is made larger:
78 // containing a chunk of iterations (of size CSTCTX_CHUNK_SZ)
79 typedef struct
80 {
81   cstk_ctx* cstCtxAr[CSTCTX_CHUNK_SZ];
82   int last_idx;
83   long idx_begin;
84   long idx_end;
85   DataDescriptor *dDscr;
86   Experiment *exp;
87   void *cstk;
88 } cstk_ctx_chunk;
89 
90 class Experiment : public Histable, public DbeMessages
91 {
92 public:
93 
94   enum Exp_status
95   {
96     SUCCESS,
97     INCOMPLETE,
98     FAILURE
99   };
100 
101   Experiment ();
102   virtual ~Experiment ();
103 
104   virtual Histable_type
get_type()105   get_type ()
106   {
107     return EXPERIMENT;
108   };
109   virtual Vector<Histable*> *get_comparable_objs ();
110 
111   int groupId;
112   Experiment *founder_exp;              // parent of this experiment
113   Vector<Experiment*> *children_exps;   // children of this experiment
114 
115   // Configuration Information
116   char *hostname;       // Hosthame (e.g. mymachine)
117   hrtime_t start_sec;       // Starting timeval secs.
118   char *username;       // name of person performing the test
119   char *architecture;   // Architecture name ("sun4")
120   Platform_t platform;  // Sparc,Sparcv9,Intel
121   WSize_t wsize;        // word size: may be w32 or w64
122   int clock;            // CPU clock frequency, Mhz
123   int varclock;         // Set if CPU clock frequency can change: turbo-mode
124   int maxclock;         // max. CPU clock frequency on MP machine
125   int minclock;         // min. CPU clock frequency on MP machine
126   int ncpus;            // count of CPUs where expt was recorded
127   int hw_cpuver;        // CPU version from libcpc
128   char *machinemodel;   // machine model of machine on which experiment was recorded
129   char *os_version;     // Operating system name
130   int page_size;        // Page size (bytes)
131   int npages;           // Number of page size
132   int exp_maj_version;  // major version number of current experiment
133   int exp_min_version;  // minor version number of current experiment
134   int hex_field_width;  // number of digits in hex form of address
135 			// for current experiment, i.e. 8 for 32bit addresses
136   int broken;           // If SP_JCMD_RUN line not seen
137   int obsolete;         // If pointer file experiment detected
138   bool hwc_default;     // True if HW counters were enabled by default
139   int hwc_bogus;        // Count of bogus HWC packets
140   int hwc_lost_int;     // Count of packets reflecting lost interrupt
141   int hwc_scanned;      // If the HWC packets have been scanned
142   int invalid_packet;   // Count of invalid packets
143   bool exec_started;    // True if exec was called, and exec error not yet seen
144   bool dataspaceavail;  // True if dataspace data is in the experiment
145   bool leaklistavail;   // True if leaklist data is in the experiment
146   bool heapdataavail;   // True if heap data is in the experiment
147   bool racelistavail;   // true if there are race events in the experiment
148   bool iodataavail;     // true if there are io events in the experiment
149   bool deadlocklistavail; // true if there are deadlock events in the experiment
150   bool timelineavail;   // true if there are valid timestamps in the experiment
151   bool ifreqavail;      // True if instruction-frequency data is in the experiment
152   bool ompavail;        // true if there is OpenMP data in the experiment
153   bool has_java;
154   char *uarglist;       // argv[] array, as a string
155   char *utargname;      // basename of argv[0] extracted from uarglist
156   char *ucwd;           // working directory
157   char *cversion;       // collector version string
158   char *dversion;       // driver version string (er_kernel)
159   char *jversion;       // Java version string (java profiling)
160 
161   // Open the named experiment record and process log file
162   Exp_status open (char *directory_name);
163 
164   // Update experiment (read and process new data)
165   Exp_status update ();
166 
167   // Returns collector parameters for the current sample selection
168   Collection_params *
get_params()169   get_params ()
170   {
171     return &coll_params;
172   }
173 
174   Exp_status
get_status()175   get_status ()
176   {
177     return status;
178   }
179 
180   // Returns the number of samples. For use by FilterNumeric
181   int
nsamples()182   nsamples ()
183   {
184     return samples->size ();
185   }
186 
187   // Release any releasable memory.
188   void purge ();
189 
190   void resetShowHideStack ();
191   int save_notes (char*, bool);
192   int delete_notes (bool);
193   Experiment *getBaseFounder (); // returns topmost founder or this if no descendents
194 
195   hrtime_t
getStartTime()196   getStartTime ()
197   {
198     return exp_start_time;
199   }
200   hrtime_t getRelativeStartTime (); // delta between start and founder's start
201 
202   hrtime_t
getWallStartSec()203   getWallStartSec ()
204   {
205     return start_sec;
206   }
207 
208   hrtime_t
getLastEvent()209   getLastEvent ()
210   {
211     if (last_event != ZERO_TIME)
212       return last_event;
213     return exp_start_time;
214   }
215 
216   hrtime_t
getGCDuration()217   getGCDuration ()
218   {
219     return gc_duration;
220   }
221 
222   int
getPID()223   getPID ()
224   {
225     return pid;
226   }
227 
228   int
getUserExpId()229   getUserExpId ()
230   {
231     return userExpId;
232   }
233 
234   int
getExpIdx()235   getExpIdx ()
236   {
237     return expIdx;
238   }
239 
240   void
setExpIdx(int idx)241   setExpIdx (int idx)
242   {
243     expIdx = idx;
244   }
245 
246   void
setUserExpId(int idx)247   setUserExpId (int idx)
248   {
249     userExpId = idx;
250   }
251 
252   void
setTinyThreshold(int limit)253   setTinyThreshold (int limit)
254   {
255     tiny_threshold = limit;
256   }
257 
258   bool
isDiscardedTinyExperiment()259   isDiscardedTinyExperiment ()
260   {
261     return discardTiny;
262   }
263 
264   Exp_status open_epilogue ();
265   void read_experiment_data (bool read_ahead);
266   static int copy_file_to_archive (const char *name, const char *aname, int hide_msg);
267   static int copy_file_to_common_archive (const char *name, const char *aname,
268 	       int hide_msg, const char *common_archive, int relative_path = 0);
269   static int copy_file (char *name, char *aname, int hide_msg,
270 			char *common_archive = NULL, int relative_path = 0);
271 
272   // get_raw_events()
273   // action: get unfiltered packets, loading them if required
274   // parameters: data_id (see ProfData_type)
275   DataDescriptor *get_raw_events (int data_id);
276   Vector<DataDescriptor*> *getDataDescriptors ();
277 
278   // Some DATA_* types are derived from others, e.g. DATA_HEAPSZ is derived from DATA_HEAP
279   // The following hooks support derived DataViews
280   int base_data_id (int data_id); // returns base data_id type  (ProfData_type DATA_*)
281   DataView *create_derived_data_view (int data_id, DataView *dview);
282 
283   Vector<BaseMetric*>*
get_metric_list()284   get_metric_list ()
285   {
286     return metrics;
287   }
288 
289   char *
get_expt_name()290   get_expt_name ()
291   {
292     return expt_name;   // Return the pathname to the experiment
293   };
294 
295   Vector<char*> *get_descendants_names ();
296   char *get_fndr_arch_name ();
297   char *get_arch_name ();
298   char *getNameInArchive (const char *fname, bool archiveFile = false);
299   char *checkFileInArchive (const char *fname, bool archiveFile = false);
300   DbeFile *findFileInArchive (const char *className, const char *runTimePath);
301   DbeFile *findFileInArchive (const char *fname);
302   bool create_dir (char *dname);
303 
304   Vaddr
ret_stack_base()305   ret_stack_base ()
306   {
307     return stack_base;
308   };
309 
310   // Map a virtual address to a PC pair
311   DbeInstr *map_Vaddr_to_PC (Vaddr addr, hrtime_t ts);
312   DbeInstr *map_jmid_to_PC (Vaddr mid, int lineno, hrtime_t ts);
313   Sample *map_event_to_Sample (hrtime_t ts);
314   GCEvent *map_event_to_GCEvent (hrtime_t ts);
315 
316   DataView *
getOpenMPdata()317   getOpenMPdata ()
318   {
319     return openMPdata;
320   }
321 
322   time_t
get_mtime()323   get_mtime ()
324   {
325     return mtime;
326   }
327 
328   Emsg *fetch_comments (void);  // fetch the queue of comment messages
329   Emsg *fetch_runlogq (void);   // fetch the queue of run log messages
330   Emsg *fetch_errors (void);    // fetch the queue of error messages
331   Emsg *fetch_warnings (void);  // fetch the queue of warning messages
332   Emsg *fetch_notes (void);     // fetch the queue of notes messages
333   Emsg *fetch_ifreq (void);     // fetch the queue of ifreq messages
334   Emsg *fetch_pprocq (void);    // fetch the queue of post-processing messages
335 
336   // message queues
337   Emsgqueue *commentq;  // comments for the experiment header
338   Emsgqueue *runlogq;   // used temporarily; after log file processing,
339   // messages are appended to the commentq
340   Emsgqueue *errorq;    // error messages
341   Emsgqueue *warnq;     // warning messages
342   Emsgqueue *notesq;    // user-written notes messages
343   Emsgqueue *pprocq;    // postprocessing messages
344   Emsgqueue *ifreqq;    // Instruction frequency data, from count experiment
345   Map<const char*, LoadObject*> *loadObjMap;
346   Vector<LoadObject*> *loadObjs;
347   void append (LoadObject *lo);
348   LoadObject *createLoadObject (const char *path, uint64_t chksum = 0);
349   LoadObject *createLoadObject (const char *path, const char *runTimePath);
350   SourceFile *get_source (const char *path);
351   void set_clock (int clk);
352 
353   CallStack *
callTree()354   callTree ()
355   {
356     return cstack;
357   }
358 
359   CallStack *
callTreeShowHide()360   callTreeShowHide ()
361   {
362     return cstackShowHide;
363   }
364 
365   uint32_t mapTagValue (Prop_type, uint64_t value);
366   Histable *getTagObj (Prop_type, uint32_t idx);
367   Vector<Histable*> *getTagObjs (Prop_type);
368 
369   JThread *map_pckt_to_Jthread (uint32_t tid, hrtime_t tstamp);
370   JThread *get_jthread (uint32_t tid);
371 
372   Vector<JThread*> *
get_jthreads()373   get_jthreads ()
374   {
375     return jthreads;
376   }
377 
378   Vector<GCEvent*> *
get_gcevents()379   get_gcevents ()
380   {
381     return gcevents;
382   }
383 
384   bool need_swap_endian;
385   Collection_params coll_params; // Collection params
386 
387   // Ranges for threads, lwps, cpu
388   uint64_t min_thread;
389   uint64_t max_thread;
390   uint64_t thread_cnt;
391   uint64_t min_lwp;
392   uint64_t max_lwp;
393   uint64_t lwp_cnt;
394   uint64_t min_cpu;
395   uint64_t max_cpu;
396   uint64_t cpu_cnt;
397   uint64_t dsevents;        // count of dataspace events
398   uint64_t dsnoxhwcevents;  /* count of ds events that could be be validated
399 			     * because of no branch target info */
400 
401   PacketDescriptor *newPacketDescriptor (int kind, DataDescriptor *dDscr);
402   PacketDescriptor *getPacketDescriptor (int kind);
403 
404   // debugging aids -- dump_stacks, dump_map
405   void dump_stacks (FILE *);
406   void dump_map (FILE *);
407 
408   // These methods are used in nightly performance regression testing
409   void DBG_memuse (Sample *);
410   void DBG_memuse (const char *sname);
411   void init_cache ();
412 
413   DefaultMap<int64_t, FileData*> *
getFDataMap()414   getFDataMap ()
415   {
416     return fDataMap;
417   }
418   CallStack *cstack;
419 
420 protected:
421 
422   Exp_status status;        // Error status
423   Vector<SegMem*> *seg_items; // Master list of seg_items
424   CallStack *cstackShowHide;
425   PRBTree *maps;            // All maps in (Vaddr,time)
426 
427   hrtime_t gc_duration;     // wall-clock hrtime of total GC intervals
428   hrtime_t exp_start_time;  // wall-clock hrtime at exp start
429   hrtime_t last_event;      // wall-clock hrtime of last known sample or log.xml entry
430   hrtime_t non_paused_time; // sum of periods where data collection is active (not paused)
431   hrtime_t resume_ts;       // tracks log.xml start/resume times
432   void update_last_event (hrtime_t ts /*wall time (not 0-based)*/);
433 
434   char *expt_name;      // name of experiment
435   char *arch_name;      // <experiment>/archive
436   char *fndr_arch_name; // <founder_experiment>/archive
437   //TBR? hrtime_t sample_time;  // total of sample durations
438   int yyparse ();       // Allow yyparse actions to access
439   Vaddr stack_base;     // Stack base
440 
441   // Write experiment header to comment queue
442   void write_header ();
443   void write_coll_params ();
444 
445   Exp_status find_expdir (char *directory_name);
446 
447   // Invoke the parser to process a file.
448   void read_data_file (const char*, const char*);
449   int read_log_file ();
450   void read_labels_file ();
451   void read_notes_file ();
452   void read_archives ();
453   int read_java_classes_file ();
454   void read_map_file ();
455   int read_overview_file ();
456   int read_dyntext_file ();
457   void read_omp_file ();
458   void read_omp_preg ();
459   void read_omp_task ();
460   void read_ifreq_file ();
461   void read_frameinfo_file ();
462 
463   // Functions to process the log and loadobjects file entries
464   // They are deliberately made virtual to overload them
465   // in er_export.
466   virtual int process_arglist_cmd (char *, char *);
467   virtual int process_desc_start_cmd (char *, hrtime_t, char *, char *, int, char *);
468   virtual int process_desc_started_cmd (char *, hrtime_t, char *, char *, int, char *);
469   virtual int process_fn_load_cmd (Module *mod, char *fname, Vaddr vaddr, int fsize, hrtime_t ts);
470   virtual int process_fn_unload_cmd (char *, Vaddr, hrtime_t);
471   virtual int process_hwcounter_cmd (char *, int, char *, char *, int, int, int, char *);
472   virtual int process_hwsimctr_cmd (char *, int, char *, char *, char*, int, int, int, int, int);
473   virtual int process_jcm_load_cmd (char*, Vaddr, Vaddr, int, hrtime_t);
474   virtual int process_jcm_unload_cmd (char*, Vaddr, hrtime_t);
475   virtual int process_Linux_kernel_cmd (hrtime_t);
476   virtual int process_jthr_end_cmd (char *, uint64_t, Vaddr, Vaddr, hrtime_t);
477   virtual int process_jthr_start_cmd (char *, char *, char *, char *, uint64_t, Vaddr, Vaddr, hrtime_t);
478   virtual int process_gc_end_cmd (hrtime_t);
479   virtual int process_gc_start_cmd (hrtime_t);
480   virtual int process_sample_cmd (char *, hrtime_t, int id, char *lbl);
481   virtual int process_sample_sig_cmd (char *, int);
482   virtual int process_seg_map_cmd (char *, hrtime_t, Vaddr, int, int, int64_t, int64_t, int64_t, char *);
483   virtual int process_seg_unmap_cmd (char *, hrtime_t, Vaddr);
484 
485   // creation time for experiment
486   time_t mtime;
487   hrtime_t exp_rel_start_time;      // start of exp. relative to founder
488   bool exp_rel_start_time_set;
489   Vector<UserLabel*> *userLabels;   // List of er_labels
490   int userExpId;                    // user value for EXPID
491   int expIdx;                       // DbeSession exp identifier
492   PRBTree *jmaps;                   // JAVA_CLASSES: (id,time)->Histable
493   Experiment* baseFounder;  // outermost experiment (null until lazily computed)
494 
495   // Represents a file in experiment
496   class ExperimentFile;
497 
498   // XML handler to parse various experiment files
499   class ExperimentHandler;
500   class ExperimentLabelsHandler;
501 
502   uint64_t readPacket (Data_window *dwin, Data_window::Span *span);
503   void readPacket (Data_window *dwin, char *ptr, PacketDescriptor *pDscr,
504 		   DataDescriptor *dDscr, int arg, uint64_t pktsz);
505 
506   // read data
507   DataDescriptor *get_profile_events ();
508   DataDescriptor *get_sync_events ();
509   DataDescriptor *get_hwc_events ();
510   DataDescriptor *get_heap_events ();
511   DataDescriptor *get_heapsz_events ();
512   DataDescriptor *get_iotrace_events ();
513   DataDescriptor *get_race_events ();
514   DataDescriptor *get_deadlock_events ();
515   DataDescriptor *get_sample_events ();
516   DataDescriptor *get_gc_events ();
517   DataDescriptor *getDataDescriptor (int data_id);
518   DataDescriptor *newDataDescriptor (int data_id, int flags = 0,
519 				     DataDescriptor *master_dDscr = NULL);
520 
521   // Frame info data structures and methods
522   struct UIDnode;
523   struct RawFramePacket;
524 
525   Vector<RawFramePacket*>*frmpckts; // frame info data
526   static int frUidCmp (const void*, const void*);
527   RawFramePacket *find_frame_packet (uint64_t uid);
528 
529   static const int CHUNKSZ = 16384;
530   long nnodes;
531   long nchunks;
532   UIDnode **chunks;
533   UIDnode **uidHTable;
534   Vector<UIDnode*> *uidnodes;
535   bool resolveFrameInfo;
536   bool discardTiny;
537   int tiny_threshold; /* optimize away tiny experiments which ran
538 		       * for less than specified time (ms): default 0 */
539 
540   static int uidNodeCmp (const void *a, const void *b);
541   UIDnode *add_uid (Data_window *dwin, uint64_t uid, int size, uint32_t *array, uint64_t link_uid);
542   UIDnode *add_uid (Data_window *dwin, uint64_t uid, int size, uint64_t *array, uint64_t link_uid);
543   UIDnode *new_uid_node (uint64_t uid, uint64_t val);
544   UIDnode *get_uid_node (uint64_t uid, uint64_t val);
545   UIDnode *get_uid_node (uint64_t uid);
546   UIDnode *find_uid_node (uint64_t uid);
547 
548   ExperimentFile *logFile;
549 
550   // Data descriptors
551   Vector<DataDescriptor*> *dataDscrs;
552   Vector<PacketDescriptor*> *pcktDscrs;
553   long blksz; // binary data file block size
554 
555   // Processed data packets
556   DataView *openMPdata; // OMP fork events
557 
558   // Map events to OpenMP parallel regions and tasks
559   Map2D<uint32_t, hrtime_t, uint64_t> *mapPRid;
560   Map2D<uint32_t, hrtime_t, void*> *mapPReg;
561   Map2D<uint32_t, hrtime_t, void*> *mapTask;
562 
563   // Archive content
564   Map<const char*, DbeFile *> *archiveMap;
565   Map<const char*, SourceFile*>*sourcesMap;
566 
567   void init ();
568   void fini ();
569   void post_process ();
570   void constructJavaStack (FramePacket *, UIDnode *, Map<uint64_t, uint64_t> *);
571   void resolve_frame_info (DataDescriptor*);
572   void cleanup_cstk_ctx_chunk ();
573   void register_metric (Metric::Type type);
574   void register_metric (Hwcentry *ctr, const char* aux, const char* username);
575 
576   Sample *sample_last_used;
577   GCEvent *gcevent_last_used;
578   char *first_sample_label;
579   Module *get_jclass (const char *className, const char *fileName);
580   LoadObject *get_j_lo (const char *className, const char *fileName);
581 
582   Vector<BaseMetric*> *metrics;
583   Vector<JThread*> *jthreads;       // master list of Java threads
584   Vector<JThread*> *jthreads_idx;   // index in the master list
585   Vector<GCEvent*> *gcevents;
586   Vector<UnmapChunk*> *heapUnmapEvents;
587   Vector<Sample*> *samples;         // Array of Sample pointers
588 
589   DefaultMap<int64_t, FileData*> *fDataMap; // list of FileData objects using the virtual File descriptor as the key
590   DefaultMap<int, int64_t> *vFdMap; // list of virtual file descrptors using the file descriptor as the key
591 
592   Vector<Vector<Histable*>*> *tagObjs; // tag objects
593   bool sparse_threads;
594 
595   SegMem **smemHTable; // hash table for SegMem's
596   DbeInstr **instHTable; // hash table for DbeInstr
597   Map<unsigned long long, JMethod*> *jmidHTable; // hash table for jmid
598 
599   // identity of target process
600   int pid;
601   int ppid;
602   int pgrp;
603   int sid;
604 
605   // Map file processing related data
606   struct MapRecord
607   {
608 
609     enum
610     {
611       LOAD, UNLOAD
612     } kind;
613     Histable *obj;
614     Vaddr base;
615     Size size;
616     hrtime_t ts;
617     uint64_t foff;
618   };
619 
620   void mrec_insert (MapRecord *mrec);
621   SegMem *update_ts_in_maps (Vaddr addr, hrtime_t ts);
622   int read_warn_file ();
623   LoadObject *get_dynfunc_lo (const char *loName);
624   Function *create_dynfunc (Module *mod, char *fname, int64_t vaddr, int64_t fsize);
625   char *get_archived_name (const char *fname, bool archiveFile = false);
626 
627   Vector<MapRecord*> *mrecs;
628 
629 private:
630   void add_evt_time_to_profile_events (DataDescriptor *dDscr);
631   DataView *create_heapsz_data_view (DataView *heap_dview);
632   void compute_heapsz_data_view (DataView *heapsz_dview);
633 };
634 
635 struct JThread
636 {
637   JThread *next;
638   char *name;
639   char *group_name;
640   char *parent_name;
641   uint32_t tid;     // system thread id
642   Vaddr jthr;       // recorded Java thread id
643   Vaddr jenv;       // recorded JNIEnv id
644   uint32_t jthr_id; // internal JThread object id
645   hrtime_t start;
646   hrtime_t end;
647 
JThreadJThread648   JThread ()
649   {
650     name = NULL;
651     group_name = NULL;
652     parent_name = NULL;
653   }
654 
~JThreadJThread655   ~JThread ()
656   {
657     free (name);
658     free (group_name);
659     free (parent_name);
660   }
661   bool is_system ();
662 };
663 
664 struct GCEvent
665 {
666 
GCEventGCEvent667   GCEvent ()
668   {
669     id = -1;
670   }
671 
~GCEventGCEvent672   ~GCEvent () { }
673 
674   hrtime_t start;
675   hrtime_t end;
676   int id;
677 };
678 
679 class ExperimentLoadCancelException
680 {
681 public:
682 
ExperimentLoadCancelException()683   ExperimentLoadCancelException () { };
684 
~ExperimentLoadCancelException()685   ~ExperimentLoadCancelException () { };
686 };
687 
688 
689 #endif  /* _EEXPERIMENT_H */
690