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#include "config.h" 22#include <memory.h> 23#include <values.h> 24#include <assert.h> 25#include "Data_window.h" 26#include "Exp_Layout.h" 27#include "Table.h" 28#include "Ovw_data.h" 29#include "Sample.h" 30#include "data_pckts.h" 31#include "util.h" 32#include "i18n.h" 33 34void 35Ovw_data::sum (Ovw_data *data) 36{ 37 Ovw_item data_totals = data->get_totals (); 38 if (totals == NULL) 39 { 40 totals = reset_item (new Ovw_item); 41 *totals = data_totals; 42 totals->start.tv_sec = totals->end.tv_sec = -1; 43 totals->start.tv_nsec = totals->end.tv_nsec = 0; 44 } 45 else 46 { 47 tsadd (&totals->duration, &data_totals.duration); 48 tsadd (&totals->tlwp, &data_totals.tlwp); 49 if (tstodouble (totals->duration) != 0) 50 totals->nlwp = tstodouble (totals->tlwp) / tstodouble (totals->duration); 51 52 for (int i = 0, size = totals->size; i < size; i++) 53 tsadd (&totals->values[i].t, &data_totals.values[i].t); 54 } 55} 56 57Ovw_data::Ovw_item * 58Ovw_data::reset_item (Ovw_data::Ovw_item *item) 59{ 60 memset (item, 0, sizeof (*item)); 61 return item; 62} 63 64Ovw_data::Ovw_item 65Ovw_data::get_totals () 66{ 67 // This routine will return the totals values for item in the sample. 68 // Compute maximums and totals only once, and save the result. 69 // On subsequent calls, just return the saved result. 70 // If maximums is NULL, then totals is also NULL 71 if (totals != NULL) 72 return *totals; 73 74 timestruc_t zero = {0, 0}; 75 totals = reset_item (new Ovw_item); 76 totals->start.tv_sec = MAXINT; // new 77 totals->start.tv_nsec = MAXINT; // new 78 totals->start_label = totals->end_label = NTXT ("Total"); 79 totals->type = VT_HRTIME; 80 81 int nsampsel = 0; 82 for (int index = 0; index < size (); index++) 83 { 84 Ovw_item item = fetch (index); 85 nsampsel++; 86 87 // Compute totals 88 for (int i = 0; i < OVW_NUMVALS + 1; i++) 89 tsadd (&totals->values[i].t, &item.values[i].t); 90 91 int_max (&totals->states, item.states); 92 tsadd (&totals->total.t, &item.total.t); 93 int_max (&totals->size, item.size); 94 tsadd (&totals->duration, &item.duration); 95 tsadd (&totals->tlwp, &item.tlwp); 96 totals->number += item.number; 97 if (tscmp (&totals->start, &item.start) > 0) 98 totals->start = item.start; 99 if (tscmp (&totals->end, &item.end) < 0) 100 totals->end = item.end; 101 } 102 103 if (totals->start.tv_sec == MAXINT && totals->start.tv_nsec == MAXINT) 104 totals->start = zero; 105 totals->nlwp = tstodouble (totals->tlwp) / tstodouble (totals->duration); 106 107 if (nsampsel == 0) 108 { 109 totals->size = OVW_NUMVALS + 1; 110 totals->start.tv_sec = totals->end.tv_sec = -1; 111 totals->start.tv_nsec = totals->end.tv_nsec = 0; 112 totals->nlwp = -1; 113 } 114 return *totals; 115} 116 117Ovw_data::Ovw_item 118Ovw_data::get_labels () 119{ 120 Ovw_item ovw_item; 121 Value *values; 122 memset (&ovw_item, 0, sizeof (Ovw_item)); 123 values = &ovw_item.values[0]; 124 125 char *stateUNames[/*LMS_NUM_STATES*/] = LMS_STATE_USTRINGS; 126 values[0].l = dbe_strdup (GTXT ("Leftover")); 127 values[OVW_LMS_USER + 1].l = stateUNames[LMS_USER]; 128 values[OVW_LMS_SYSTEM + 1].l = stateUNames[LMS_SYSTEM]; 129 values[OVW_LMS_WAIT_CPU + 1].l = stateUNames[LMS_WAIT_CPU]; 130 values[OVW_LMS_USER_LOCK + 1].l = stateUNames[LMS_USER_LOCK]; 131 values[OVW_LMS_TFAULT + 1].l = stateUNames[LMS_TFAULT]; 132 values[OVW_LMS_DFAULT + 1].l = stateUNames[LMS_DFAULT]; 133 values[OVW_LMS_KFAULT + 1].l = stateUNames[LMS_KFAULT]; 134 values[OVW_LMS_SLEEP + 1].l = stateUNames[LMS_SLEEP]; 135 values[OVW_LMS_STOPPED + 1].l = stateUNames[LMS_STOPPED]; 136 values[OVW_LMS_TRAP + 1].l = stateUNames[LMS_TRAP]; 137 138 ovw_item.size = OVW_NUMVALS + 1; 139 ovw_item.states = 0; 140 ovw_item.type = VT_LABEL; 141 return ovw_item; 142} 143 144Ovw_data::Ovw_data () 145{ 146 packets = NULL; 147 ovw_items = new Vector<Ovw_item*>; 148 totals = NULL; 149} 150 151Ovw_data::Ovw_data (DataView *_packets, hrtime_t exp_start) 152{ 153 packets = _packets; 154 ovw_items = new Vector<Ovw_item*>; 155 totals = NULL; 156 long npackets = packets->getSize (); 157 for (long index = 0; index < npackets; index++) 158 { 159 Ovw_item *ovw_item = new Ovw_item; 160 memset (ovw_item, 0, sizeof (Ovw_item)); 161 Sample *sample = (Sample*) packets->getObjValue (PROP_SMPLOBJ, index); 162 extract_data (ovw_item, sample); 163 hr2timestruc (&ovw_item->start, sample->get_start_time () - exp_start); 164 hr2timestruc (&ovw_item->end, sample->get_end_time () - exp_start); 165 // No need to check for duration, as duration has to be > 0. 166 // If not, it would have been found out in yyparse. 167 tssub (&ovw_item->duration, &ovw_item->end, &ovw_item->start); 168 ovw_item->number = sample->get_number (); 169 ovw_item->start_label = sample->get_start_label (); 170 ovw_item->end_label = sample->get_end_label (); 171 172 int size = ovw_item->size; 173 for (int j = 0; j < size; j++) 174 tsadd (&ovw_item->tlwp, &ovw_item->values[j].t); 175 if (tstodouble (ovw_item->duration) != 0) 176 ovw_item->nlwp = tstodouble (ovw_item->tlwp) / 177 tstodouble (ovw_item->duration); 178 ovw_items->append (ovw_item); 179 } 180} 181 182Ovw_data::~Ovw_data () 183{ 184 ovw_items->destroy (); 185 delete ovw_items; 186 delete totals; 187} 188 189void 190Ovw_data::extract_data (Ovw_data::Ovw_item *ovw_item, Sample *sample) 191{ 192 // This routine break out the data in "data" into buckets in "ovw_item" 193 int index; 194 int states; 195 timestruc_t sum, rtime; 196 timestruc_t zero = {0, 0}; 197 Value *values; 198 PrUsage *prusage = sample->get_usage (); 199 if (prusage == NULL) 200 prusage = new PrUsage; 201 202 values = &ovw_item->values[0]; 203 hr2timestruc (&values[OVW_LMS_USER + 1].t, prusage->pr_utime); 204 hr2timestruc (&values[OVW_LMS_SYSTEM + 1].t, prusage->pr_stime); 205 hr2timestruc (&values[OVW_LMS_WAIT_CPU + 1].t, prusage->pr_wtime); 206 hr2timestruc (&values[OVW_LMS_USER_LOCK + 1].t, prusage->pr_ltime); 207 hr2timestruc (&values[OVW_LMS_TFAULT + 1].t, prusage->pr_tftime); 208 hr2timestruc (&values[OVW_LMS_DFAULT + 1].t, prusage->pr_dftime); 209 hr2timestruc (&values[OVW_LMS_TRAP + 1].t, prusage->pr_ttime); 210 hr2timestruc (&values[OVW_LMS_KFAULT + 1].t, prusage->pr_kftime); 211 hr2timestruc (&values[OVW_LMS_SLEEP + 1].t, prusage->pr_slptime); 212 hr2timestruc (&values[OVW_LMS_STOPPED + 1].t, prusage->pr_stoptime); 213 ovw_item->size = OVW_NUMVALS + 1; 214 215 //XXX: Compute values[0] as rtime - sum_of(other_times) 216 sum = zero; 217 states = 0; 218 for (index = 1; index < ovw_item->size; index++) 219 { 220 if (values[index].t.tv_sec != 0 || values[index].t.tv_nsec != 0) 221 states++; 222 tsadd (&sum, &values[index].t); 223 } 224 225 // If the sum of all times is greater than rtime then adjust 226 // rtime to be equal to sum and also adjust the pr_rtime field 227 hr2timestruc (&rtime, prusage->pr_rtime); 228 if (tscmp (&sum, &rtime) > 0) 229 { 230 ovw_item->total.t = sum; 231 values[0].t = zero; 232 } 233 else 234 { 235 ovw_item->total.t = rtime; 236 tssub (&rtime, &rtime, &sum); 237 tsadd (&values[0].t, &rtime); 238 states++; 239 } 240 ovw_item->type = VT_HRTIME; 241 ovw_item->states = states; 242} 243