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
33class Data_window;
34class DbeFile;
35class CallStack;
36class JMethod;
37class Sample;
38class SegMem;
39class LoadObject;
40class SourceFile;
41class UserLabel;
42class PRBTree;
43class Emsg;
44class Emsgqueue;
45struct JThread;
46struct GCEvent;
47class FileData;
48class Module;
49class Experiment;
50template <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
66typedef 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)
79typedef 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
90class Experiment : public Histable, public DbeMessages
91{
92public:
93
94  enum Exp_status
95  {
96    SUCCESS,
97    INCOMPLETE,
98    FAILURE
99  };
100
101  Experiment ();
102  virtual ~Experiment ();
103
104  virtual Histable_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 *
169  get_params ()
170  {
171    return &coll_params;
172  }
173
174  Exp_status
175  get_status ()
176  {
177    return status;
178  }
179
180  // Returns the number of samples. For use by FilterNumeric
181  int
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
196  getStartTime ()
197  {
198    return exp_start_time;
199  }
200  hrtime_t getRelativeStartTime (); // delta between start and founder's start
201
202  hrtime_t
203  getWallStartSec ()
204  {
205    return start_sec;
206  }
207
208  hrtime_t
209  getLastEvent ()
210  {
211    if (last_event != ZERO_TIME)
212      return last_event;
213    return exp_start_time;
214  }
215
216  hrtime_t
217  getGCDuration ()
218  {
219    return gc_duration;
220  }
221
222  int
223  getPID ()
224  {
225    return pid;
226  }
227
228  int
229  getUserExpId ()
230  {
231    return userExpId;
232  }
233
234  int
235  getExpIdx ()
236  {
237    return expIdx;
238  }
239
240  void
241  setExpIdx (int idx)
242  {
243    expIdx = idx;
244  }
245
246  void
247  setUserExpId (int idx)
248  {
249    userExpId = idx;
250  }
251
252  void
253  setTinyThreshold (int limit)
254  {
255    tiny_threshold = limit;
256  }
257
258  bool
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*>*
284  get_metric_list ()
285  {
286    return metrics;
287  }
288
289  char *
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
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 *
317  getOpenMPdata ()
318  {
319    return openMPdata;
320  }
321
322  time_t
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 *
354  callTree ()
355  {
356    return cstack;
357  }
358
359  CallStack *
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*> *
373  get_jthreads ()
374  {
375    return jthreads;
376  }
377
378  Vector<GCEvent*> *
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*> *
414  getFDataMap ()
415  {
416    return fDataMap;
417  }
418  CallStack *cstack;
419
420protected:
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
629private:
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
635struct 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
648  JThread ()
649  {
650    name = NULL;
651    group_name = NULL;
652    parent_name = NULL;
653  }
654
655  ~JThread ()
656  {
657    free (name);
658    free (group_name);
659    free (parent_name);
660  }
661  bool is_system ();
662};
663
664struct GCEvent
665{
666
667  GCEvent ()
668  {
669    id = -1;
670  }
671
672  ~GCEvent () { }
673
674  hrtime_t start;
675  hrtime_t end;
676  int id;
677};
678
679class ExperimentLoadCancelException
680{
681public:
682
683  ExperimentLoadCancelException () { };
684
685  ~ExperimentLoadCancelException () { };
686};
687
688
689#endif  /* _EEXPERIMENT_H */
690