1 /* Copyright (C) 2021-2025 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<Histable*> *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 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 bigendian; // the experiment was created on a big_endian machine 139 bool hwc_default; // True if HW counters were enabled by default 140 int hwc_bogus; // Count of bogus HWC packets 141 int hwc_lost_int; // Count of packets reflecting lost interrupt 142 int hwc_scanned; // If the HWC packets have been scanned 143 int invalid_packet; // Count of invalid packets 144 bool exec_started; // True if exec was called, and exec error not yet seen 145 bool dataspaceavail; // True if dataspace data is in the experiment 146 bool leaklistavail; // True if leaklist data is in the experiment 147 bool heapdataavail; // True if heap data is in the experiment 148 bool racelistavail; // true if there are race events in the experiment 149 bool iodataavail; // true if there are io events in the experiment 150 bool deadlocklistavail; // true if there are deadlock events in the experiment 151 bool timelineavail; // true if there are valid timestamps in the experiment 152 bool ifreqavail; // True if instruction-frequency data is in the experiment 153 bool ompavail; // true if there is OpenMP data in the experiment 154 bool has_java; 155 char *uarglist; // argv[] array, as a string 156 char *utargname; // basename of argv[0] extracted from uarglist 157 char *ucwd; // working directory 158 char *cversion; // collector version string 159 char *dversion; // driver version string (er_kernel) 160 char *jversion; // Java version string (java profiling) 161 162 // Open the named experiment record and process log file 163 Exp_status open (char *directory_name); 164 165 // Update experiment (read and process new data) 166 Exp_status update (); 167 168 // Returns collector parameters for the current sample selection 169 Collection_params * 170 get_params () 171 { 172 return &coll_params; 173 } 174 175 Exp_status 176 get_status () 177 { 178 return status; 179 } 180 181 // Returns the number of samples. For use by FilterNumeric 182 int 183 nsamples () 184 { 185 return samples->size (); 186 } 187 188 // Release any releasable memory. 189 void purge (); 190 191 void resetShowHideStack (); 192 int save_notes (char*, bool); 193 int delete_notes (bool); 194 Experiment *getBaseFounder (); // returns topmost founder or this if no descendents 195 196 hrtime_t 197 getStartTime () 198 { 199 return exp_start_time; 200 } 201 hrtime_t getRelativeStartTime (); // delta between start and founder's start 202 203 hrtime_t 204 getWallStartSec () 205 { 206 return start_sec; 207 } 208 209 hrtime_t 210 getLastEvent () 211 { 212 if (last_event != ZERO_TIME) 213 return last_event; 214 return exp_start_time; 215 } 216 217 hrtime_t 218 getGCDuration () 219 { 220 return gc_duration; 221 } 222 223 int 224 getPID () 225 { 226 return pid; 227 } 228 229 int 230 getUserExpId () 231 { 232 return userExpId; 233 } 234 235 int 236 getExpIdx () 237 { 238 return expIdx; 239 } 240 241 void 242 setExpIdx (int idx) 243 { 244 expIdx = idx; 245 } 246 247 void 248 setUserExpId (int idx) 249 { 250 userExpId = idx; 251 } 252 253 void 254 setTinyThreshold (int limit) 255 { 256 tiny_threshold = limit; 257 } 258 259 bool 260 isDiscardedTinyExperiment () 261 { 262 return discardTiny; 263 } 264 265 Exp_status open_epilogue (); 266 void read_experiment_data (bool read_ahead); 267 static int copy_file_to_archive (const char *name, const char *aname, int hide_msg); 268 static int copy_file_to_common_archive (const char *name, const char *aname, 269 int hide_msg, const char *common_archive, int relative_path = 0); 270 static int copy_file (const char *name, const char *aname, int hide_msg, 271 const char *common_archive = NULL, int relative_path = 0); 272 273 // get_raw_events() 274 // action: get unfiltered packets, loading them if required 275 // parameters: data_id (see ProfData_type) 276 DataDescriptor *get_raw_events (int data_id); 277 Vector<DataDescriptor*> *getDataDescriptors (); 278 279 // Some DATA_* types are derived from others, e.g. DATA_HEAPSZ is derived from DATA_HEAP 280 // The following hooks support derived DataViews 281 int base_data_id (int data_id); // returns base data_id type (ProfData_type DATA_*) 282 DataView *create_derived_data_view (int data_id, DataView *dview); 283 284 Vector<BaseMetric*>* 285 get_metric_list () 286 { 287 return metrics; 288 } 289 290 char * 291 get_expt_name () 292 { 293 return expt_name; // Return the pathname to the experiment 294 }; 295 296 Vector<char*> *get_descendants_names (); 297 char *get_fndr_arch_name (); 298 char *get_arch_name (); 299 char *getNameInArchive (const char *fname, bool archiveFile = false); 300 char *checkFileInArchive (const char *fname, bool archiveFile = false); 301 DbeFile *findFileInArchive (const char *className, const char *runTimePath); 302 DbeFile *findFileInArchive (const char *fname); 303 bool create_dir (char *dname); 304 305 Vaddr 306 ret_stack_base () 307 { 308 return stack_base; 309 }; 310 311 // Map a virtual address to a PC pair 312 DbeInstr *map_Vaddr_to_PC (Vaddr addr, hrtime_t ts); 313 DbeInstr *map_jmid_to_PC (Vaddr mid, int lineno, hrtime_t ts); 314 Sample *map_event_to_Sample (hrtime_t ts); 315 GCEvent *map_event_to_GCEvent (hrtime_t ts); 316 317 DataView * 318 getOpenMPdata () 319 { 320 return openMPdata; 321 } 322 323 time_t 324 get_mtime () 325 { 326 return mtime; 327 } 328 329 Emsg *fetch_comments (void); // fetch the queue of comment messages 330 Emsg *fetch_runlogq (void); // fetch the queue of run log messages 331 Emsg *fetch_errors (void); // fetch the queue of error messages 332 Emsg *fetch_warnings (void); // fetch the queue of warning messages 333 Emsg *fetch_notes (void); // fetch the queue of notes messages 334 Emsg *fetch_ifreq (void); // fetch the queue of ifreq messages 335 Emsg *fetch_pprocq (void); // fetch the queue of post-processing messages 336 337 // message queues 338 Emsgqueue *commentq; // comments for the experiment header 339 Emsgqueue *runlogq; // used temporarily; after log file processing, 340 // messages are appended to the commentq 341 Emsgqueue *errorq; // error messages 342 Emsgqueue *warnq; // warning messages 343 Emsgqueue *notesq; // user-written notes messages 344 Emsgqueue *pprocq; // postprocessing messages 345 Emsgqueue *ifreqq; // Instruction frequency data, from count experiment 346 Map<const char*, LoadObject*> *loadObjMap; 347 Vector<LoadObject*> *loadObjs; 348 void append (LoadObject *lo); 349 LoadObject *createLoadObject (const char *path, uint64_t chksum = 0); 350 LoadObject *createLoadObject (const char *path, const char *runTimePath); 351 SourceFile *get_source (const char *path); 352 void set_clock (int clk); 353 354 CallStack * 355 callTree () 356 { 357 return cstack; 358 } 359 360 CallStack * 361 callTreeShowHide () 362 { 363 return cstackShowHide; 364 } 365 366 uint32_t mapTagValue (Prop_type, uint64_t value); 367 Histable *getTagObj (Prop_type, uint32_t idx); 368 Vector<Histable*> *getTagObjs (Prop_type); 369 370 JThread *map_pckt_to_Jthread (uint32_t tid, hrtime_t tstamp); 371 JThread *get_jthread (uint32_t tid); 372 373 Vector<JThread*> * 374 get_jthreads () 375 { 376 return jthreads; 377 } 378 379 Vector<GCEvent*> * 380 get_gcevents () 381 { 382 return gcevents; 383 } 384 385 bool need_swap_endian; 386 Collection_params coll_params; // Collection params 387 388 // Ranges for threads, lwps, cpu 389 uint64_t min_thread; 390 uint64_t max_thread; 391 uint64_t thread_cnt; 392 uint64_t min_lwp; 393 uint64_t max_lwp; 394 uint64_t lwp_cnt; 395 uint64_t min_cpu; 396 uint64_t max_cpu; 397 uint64_t cpu_cnt; 398 uint64_t dsevents; // count of dataspace events 399 uint64_t dsnoxhwcevents; /* count of ds events that could be be validated 400 * because of no branch target info */ 401 402 PacketDescriptor *newPacketDescriptor (int kind, DataDescriptor *dDscr); 403 PacketDescriptor *getPacketDescriptor (int kind); 404 405 // debugging aids -- dump_stacks, dump_map 406 void dump_stacks (FILE *); 407 void dump_map (FILE *); 408 409 // These methods are used in nightly performance regression testing 410 void DBG_memuse (Sample *); 411 void DBG_memuse (const char *sname); 412 void init_cache (); 413 414 DefaultMap<int64_t, FileData*> * 415 getFDataMap () 416 { 417 return fDataMap; 418 } 419 CallStack *cstack; 420 421 protected: 422 423 Exp_status status; // Error status 424 Vector<SegMem*> *seg_items; // Master list of seg_items 425 CallStack *cstackShowHide; 426 PRBTree *maps; // All maps in (Vaddr,time) 427 428 hrtime_t gc_duration; // wall-clock hrtime of total GC intervals 429 hrtime_t exp_start_time; // wall-clock hrtime at exp start 430 hrtime_t last_event; // wall-clock hrtime of last known sample or log.xml entry 431 hrtime_t non_paused_time; // sum of periods where data collection is active (not paused) 432 hrtime_t resume_ts; // tracks log.xml start/resume times 433 void update_last_event (hrtime_t ts /*wall time (not 0-based)*/); 434 435 char *expt_name; // name of experiment 436 char *arch_name; // <experiment>/archive 437 char *fndr_arch_name; // <founder_experiment>/archive 438 char *dyntext_name; // <experiment>/dyntext 439 440 int yyparse (); // Allow yyparse actions to access 441 Vaddr stack_base; // Stack base 442 443 // Write experiment header to comment queue 444 void write_header (); 445 void write_coll_params (); 446 447 Exp_status find_expdir (char *directory_name); 448 449 // Invoke the parser to process a file. 450 void read_data_file (const char*, const char*); 451 int read_log_file (); 452 void read_labels_file (); 453 void read_notes_file (); 454 void read_archives (); 455 int read_java_classes_file (); 456 void read_map_file (); 457 int read_overview_file (); 458 int read_dyntext_file (); 459 void read_omp_file (); 460 void read_omp_preg (); 461 void read_omp_task (); 462 void read_ifreq_file (); 463 void read_frameinfo_file (); 464 465 // Functions to process the log and loadobjects file entries 466 // They are deliberately made virtual to overload them 467 // in er_export. 468 virtual int process_arglist_cmd (char *, char *); 469 virtual int process_desc_start_cmd (char *, hrtime_t, char *, char *, int, char *); 470 virtual int process_desc_started_cmd (char *, hrtime_t, char *, char *, int, char *); 471 virtual int process_fn_load_cmd (Module *mod, char *fname, Vaddr vaddr, int fsize, hrtime_t ts); 472 virtual int process_fn_unload_cmd (char *, Vaddr, hrtime_t); 473 virtual int process_hwcounter_cmd (char *, int, char *, char *, int, int, int, char *); 474 virtual int process_hwsimctr_cmd (char *, int, char *, char *, char*, int, int, int, int, int); 475 virtual int process_jcm_load_cmd (char*, Vaddr, Vaddr, int, hrtime_t); 476 virtual int process_jcm_unload_cmd (char*, Vaddr, hrtime_t); 477 virtual int process_Linux_kernel_cmd (hrtime_t); 478 virtual int process_jthr_end_cmd (char *, uint64_t, Vaddr, Vaddr, hrtime_t); 479 virtual int process_jthr_start_cmd (char *, char *, char *, char *, uint64_t, Vaddr, Vaddr, hrtime_t); 480 virtual int process_gc_end_cmd (hrtime_t); 481 virtual int process_gc_start_cmd (hrtime_t); 482 virtual int process_sample_cmd (char *, hrtime_t, int id, char *lbl); 483 virtual int process_sample_sig_cmd (char *, int); 484 virtual int process_seg_map_cmd (char *, hrtime_t, Vaddr, int, int, int64_t, int64_t, int64_t, char *); 485 virtual int process_seg_unmap_cmd (char *, hrtime_t, Vaddr); 486 487 // creation time for experiment 488 time_t mtime; 489 hrtime_t exp_rel_start_time; // start of exp. relative to founder 490 bool exp_rel_start_time_set; 491 Vector<UserLabel*> *userLabels; // List of er_labels 492 int userExpId; // user value for EXPID 493 int expIdx; // DbeSession exp identifier 494 PRBTree *jmaps; // JAVA_CLASSES: (id,time)->Histable 495 Experiment* baseFounder; // outermost experiment (null until lazily computed) 496 497 // Represents a file in experiment 498 class ExperimentFile; 499 500 // XML handler to parse various experiment files 501 class ExperimentHandler; 502 class ExperimentLabelsHandler; 503 504 uint64_t readPacket (Data_window *dwin, Data_window::Span *span); 505 void readPacket (Data_window *dwin, char *ptr, PacketDescriptor *pDscr, 506 DataDescriptor *dDscr, int arg, uint64_t pktsz); 507 508 // read data 509 DataDescriptor *get_profile_events (); 510 DataDescriptor *get_sync_events (); 511 DataDescriptor *get_hwc_events (); 512 DataDescriptor *get_heap_events (); 513 DataDescriptor *get_heapsz_events (); 514 DataDescriptor *get_iotrace_events (); 515 DataDescriptor *get_race_events (); 516 DataDescriptor *get_deadlock_events (); 517 DataDescriptor *get_sample_events (); 518 DataDescriptor *get_gc_events (); 519 DataDescriptor *getDataDescriptor (int data_id); 520 DataDescriptor *newDataDescriptor (int data_id, int flags = 0, 521 DataDescriptor *master_dDscr = NULL); 522 523 // Frame info data structures and methods 524 struct UIDnode; 525 struct RawFramePacket; 526 527 Vector<RawFramePacket*>*frmpckts; // frame info data 528 static int frUidCmp (const void*, const void*); 529 RawFramePacket *find_frame_packet (uint64_t uid); 530 531 static const int CHUNKSZ = 16384; 532 long nnodes; 533 long nchunks; 534 UIDnode **chunks; 535 UIDnode **uidHTable; 536 Vector<UIDnode*> *uidnodes; 537 bool resolveFrameInfo; 538 bool discardTiny; 539 int tiny_threshold; /* optimize away tiny experiments which ran 540 * for less than specified time (ms): default 0 */ 541 542 static int uidNodeCmp (const void *a, const void *b); 543 UIDnode *add_uid (Data_window *dwin, uint64_t uid, int size, uint32_t *array, uint64_t link_uid); 544 UIDnode *add_uid (Data_window *dwin, uint64_t uid, int size, uint64_t *array, uint64_t link_uid); 545 UIDnode *new_uid_node (uint64_t uid, uint64_t val); 546 UIDnode *get_uid_node (uint64_t uid, uint64_t val); 547 UIDnode *get_uid_node (uint64_t uid); 548 UIDnode *find_uid_node (uint64_t uid); 549 550 ExperimentFile *logFile; 551 552 // Data descriptors 553 Vector<DataDescriptor*> *dataDscrs; 554 Vector<PacketDescriptor*> *pcktDscrs; 555 long blksz; // binary data file block size 556 557 // Processed data packets 558 DataView *openMPdata; // OMP fork events 559 560 // Map events to OpenMP parallel regions and tasks 561 Map2D<uint32_t, hrtime_t, uint64_t> *mapPRid; 562 Map2D<uint32_t, hrtime_t, void*> *mapPReg; 563 Map2D<uint32_t, hrtime_t, void*> *mapTask; 564 565 // Archive content 566 Map<const char*, DbeFile *> *archiveMap; 567 Map<const char*, SourceFile*>*sourcesMap; 568 569 void init (); 570 void fini (); 571 void post_process (); 572 void constructJavaStack (FramePacket *, UIDnode *, Map<uint64_t, uint64_t> *); 573 void resolve_frame_info (DataDescriptor*); 574 void cleanup_cstk_ctx_chunk (); 575 void register_metric (Metric::Type type); 576 void register_metric (Hwcentry *ctr, const char* aux, const char* username); 577 578 Sample *sample_last_used; 579 GCEvent *gcevent_last_used; 580 char *first_sample_label; 581 Module *get_jclass (const char *className, const char *fileName); 582 LoadObject *get_j_lo (const char *className, const char *fileName); 583 584 Vector<BaseMetric*> *metrics; 585 Vector<JThread*> *jthreads; // master list of Java threads 586 Vector<JThread*> *jthreads_idx; // index in the master list 587 Vector<GCEvent*> *gcevents; 588 Vector<UnmapChunk*> *heapUnmapEvents; 589 Vector<Sample*> *samples; // Array of Sample pointers 590 591 DefaultMap<int64_t, FileData*> *fDataMap; // list of FileData objects using the virtual File descriptor as the key 592 DefaultMap<int, int64_t> *vFdMap; // list of virtual file descrptors using the file descriptor as the key 593 594 Vector<Vector<Histable*>*> *tagObjs; // tag objects 595 bool sparse_threads; 596 597 SegMem **smemHTable; // hash table for SegMem's 598 DbeInstr **instHTable; // hash table for DbeInstr 599 Map<unsigned long long, JMethod*> *jmidHTable; // hash table for jmid 600 601 // identity of target process 602 int pid; 603 int ppid; 604 int pgrp; 605 int sid; 606 607 // Map file processing related data 608 struct MapRecord 609 { 610 611 enum 612 { 613 LOAD, UNLOAD 614 } kind; 615 Histable *obj; 616 Vaddr base; 617 Size size; 618 hrtime_t ts; 619 uint64_t foff; 620 }; 621 622 void mrec_insert (MapRecord *mrec); 623 SegMem *update_ts_in_maps (Vaddr addr, hrtime_t ts); 624 int read_warn_file (); 625 LoadObject *get_dynfunc_lo (const char *loName); 626 Function *create_dynfunc (Module *mod, char *fname, int64_t vaddr, int64_t fsize); 627 char *get_archived_name (const char *fname, bool archiveFile = false); 628 629 Vector<MapRecord*> *mrecs; 630 631 private: 632 void add_evt_time_to_profile_events (DataDescriptor *dDscr); 633 DataView *create_heapsz_data_view (DataView *heap_dview); 634 void compute_heapsz_data_view (DataView *heapsz_dview); 635 }; 636 637 struct JThread 638 { 639 JThread *next; 640 char *name; 641 char *group_name; 642 char *parent_name; 643 uint32_t tid; // system thread id 644 Vaddr jthr; // recorded Java thread id 645 Vaddr jenv; // recorded JNIEnv id 646 uint32_t jthr_id; // internal JThread object id 647 hrtime_t start; 648 hrtime_t end; 649 650 JThread () 651 { 652 name = NULL; 653 group_name = NULL; 654 parent_name = NULL; 655 } 656 657 ~JThread () 658 { 659 free (name); 660 free (group_name); 661 free (parent_name); 662 } 663 bool is_system (); 664 }; 665 666 struct GCEvent 667 { 668 669 GCEvent () 670 { 671 id = -1; 672 } 673 674 ~GCEvent () { } 675 676 hrtime_t start; 677 hrtime_t end; 678 int id; 679 }; 680 681 class ExperimentLoadCancelException 682 { 683 public: 684 685 ExperimentLoadCancelException () { }; 686 687 ~ExperimentLoadCancelException () { }; 688 }; 689 690 691 #endif /* _EEXPERIMENT_H */ 692