diff options
Diffstat (limited to 'gprofng/src/Ovw_data.cc')
-rw-r--r-- | gprofng/src/Ovw_data.cc | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/gprofng/src/Ovw_data.cc b/gprofng/src/Ovw_data.cc new file mode 100644 index 00000000000..2cd57180783 --- /dev/null +++ b/gprofng/src/Ovw_data.cc @@ -0,0 +1,242 @@ +/* Copyright (C) 2021 Free Software Foundation, Inc. + Contributed by Oracle. + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "config.h" +#include <memory.h> +#include <values.h> +#include <assert.h> +#include "Data_window.h" +#include "Exp_Layout.h" +#include "Table.h" +#include "Ovw_data.h" +#include "Sample.h" +#include "data_pckts.h" +#include "util.h" +#include "i18n.h" + +void +Ovw_data::sum (Ovw_data *data) +{ + Ovw_item data_totals = data->get_totals (); + if (totals == NULL) + { + totals = reset_item (new Ovw_item); + *totals = data_totals; + totals->start.tv_sec = totals->end.tv_sec = -1; + totals->start.tv_nsec = totals->end.tv_nsec = 0; + } + else + { + tsadd (&totals->duration, &data_totals.duration); + tsadd (&totals->tlwp, &data_totals.tlwp); + if (tstodouble (totals->duration) != 0) + totals->nlwp = tstodouble (totals->tlwp) / tstodouble (totals->duration); + + for (int i = 0, size = totals->size; i < size; i++) + tsadd (&totals->values[i].t, &data_totals.values[i].t); + } +} + +Ovw_data::Ovw_item * +Ovw_data::reset_item (Ovw_data::Ovw_item *item) +{ + memset (item, 0, sizeof (*item)); + return item; +} + +Ovw_data::Ovw_item +Ovw_data::get_totals () +{ + // This routine will return the totals values for item in the sample. + // Compute maximums and totals only once, and save the result. + // On subsequent calls, just return the saved result. + // If maximums is NULL, then totals is also NULL + if (totals != NULL) + return *totals; + + timestruc_t zero = {0, 0}; + totals = reset_item (new Ovw_item); + totals->start.tv_sec = MAXINT; // new + totals->start.tv_nsec = MAXINT; // new + totals->start_label = totals->end_label = NTXT ("Total"); + totals->type = VT_HRTIME; + + int nsampsel = 0; + for (int index = 0; index < size (); index++) + { + Ovw_item item = fetch (index); + nsampsel++; + + // Compute totals + for (int i = 0; i < OVW_NUMVALS + 1; i++) + tsadd (&totals->values[i].t, &item.values[i].t); + + int_max (&totals->states, item.states); + tsadd (&totals->total.t, &item.total.t); + int_max (&totals->size, item.size); + tsadd (&totals->duration, &item.duration); + tsadd (&totals->tlwp, &item.tlwp); + totals->number += item.number; + if (tscmp (&totals->start, &item.start) > 0) + totals->start = item.start; + if (tscmp (&totals->end, &item.end) < 0) + totals->end = item.end; + } + + if (totals->start.tv_sec == MAXINT && totals->start.tv_nsec == MAXINT) + totals->start = zero; + totals->nlwp = tstodouble (totals->tlwp) / tstodouble (totals->duration); + + if (nsampsel == 0) + { + totals->size = OVW_NUMVALS + 1; + totals->start.tv_sec = totals->end.tv_sec = -1; + totals->start.tv_nsec = totals->end.tv_nsec = 0; + totals->nlwp = -1; + } + return *totals; +} + +Ovw_data::Ovw_item +Ovw_data::get_labels () +{ + Ovw_item ovw_item; + Value *values; + memset (&ovw_item, 0, sizeof (Ovw_item)); + values = &ovw_item.values[0]; + + char *stateUNames[/*LMS_NUM_STATES*/] = LMS_STATE_USTRINGS; + values[0].l = dbe_strdup (GTXT ("Leftover")); + values[OVW_LMS_USER + 1].l = stateUNames[LMS_USER]; + values[OVW_LMS_SYSTEM + 1].l = stateUNames[LMS_SYSTEM]; + values[OVW_LMS_WAIT_CPU + 1].l = stateUNames[LMS_WAIT_CPU]; + values[OVW_LMS_USER_LOCK + 1].l = stateUNames[LMS_USER_LOCK]; + values[OVW_LMS_TFAULT + 1].l = stateUNames[LMS_TFAULT]; + values[OVW_LMS_DFAULT + 1].l = stateUNames[LMS_DFAULT]; + values[OVW_LMS_KFAULT + 1].l = stateUNames[LMS_KFAULT]; + values[OVW_LMS_SLEEP + 1].l = stateUNames[LMS_SLEEP]; + values[OVW_LMS_STOPPED + 1].l = stateUNames[LMS_STOPPED]; + values[OVW_LMS_TRAP + 1].l = stateUNames[LMS_TRAP]; + + ovw_item.size = OVW_NUMVALS + 1; + ovw_item.states = 0; + ovw_item.type = VT_LABEL; + return ovw_item; +} + +Ovw_data::Ovw_data () +{ + packets = NULL; + ovw_items = new Vector<Ovw_item*>; + totals = NULL; +} + +Ovw_data::Ovw_data (DataView *_packets, hrtime_t exp_start) +{ + packets = _packets; + ovw_items = new Vector<Ovw_item*>; + totals = NULL; + long npackets = packets->getSize (); + for (long index = 0; index < npackets; index++) + { + Ovw_item *ovw_item = new Ovw_item; + memset (ovw_item, 0, sizeof (Ovw_item)); + Sample *sample = (Sample*) packets->getObjValue (PROP_SMPLOBJ, index); + extract_data (ovw_item, sample); + hr2timestruc (&ovw_item->start, sample->get_start_time () - exp_start); + hr2timestruc (&ovw_item->end, sample->get_end_time () - exp_start); + // No need to check for duration, as duration has to be > 0. + // If not, it would have been found out in yyparse. + tssub (&ovw_item->duration, &ovw_item->end, &ovw_item->start); + ovw_item->number = sample->get_number (); + ovw_item->start_label = sample->get_start_label (); + ovw_item->end_label = sample->get_end_label (); + + int size = ovw_item->size; + for (int j = 0; j < size; j++) + tsadd (&ovw_item->tlwp, &ovw_item->values[j].t); + if (tstodouble (ovw_item->duration) != 0) + ovw_item->nlwp = tstodouble (ovw_item->tlwp) / + tstodouble (ovw_item->duration); + ovw_items->append (ovw_item); + } +} + +Ovw_data::~Ovw_data () +{ + ovw_items->destroy (); + delete ovw_items; + delete totals; +} + +void +Ovw_data::extract_data (Ovw_data::Ovw_item *ovw_item, Sample *sample) +{ + // This routine break out the data in "data" into buckets in "ovw_item" + int index; + int states; + timestruc_t sum, rtime; + timestruc_t zero = {0, 0}; + Value *values; + PrUsage *prusage = sample->get_usage (); + if (prusage == NULL) + prusage = new PrUsage; + + values = &ovw_item->values[0]; + hr2timestruc (&values[OVW_LMS_USER + 1].t, prusage->pr_utime); + hr2timestruc (&values[OVW_LMS_SYSTEM + 1].t, prusage->pr_stime); + hr2timestruc (&values[OVW_LMS_WAIT_CPU + 1].t, prusage->pr_wtime); + hr2timestruc (&values[OVW_LMS_USER_LOCK + 1].t, prusage->pr_ltime); + hr2timestruc (&values[OVW_LMS_TFAULT + 1].t, prusage->pr_tftime); + hr2timestruc (&values[OVW_LMS_DFAULT + 1].t, prusage->pr_dftime); + hr2timestruc (&values[OVW_LMS_TRAP + 1].t, prusage->pr_ttime); + hr2timestruc (&values[OVW_LMS_KFAULT + 1].t, prusage->pr_kftime); + hr2timestruc (&values[OVW_LMS_SLEEP + 1].t, prusage->pr_slptime); + hr2timestruc (&values[OVW_LMS_STOPPED + 1].t, prusage->pr_stoptime); + ovw_item->size = OVW_NUMVALS + 1; + + //XXX: Compute values[0] as rtime - sum_of(other_times) + sum = zero; + states = 0; + for (index = 1; index < ovw_item->size; index++) + { + if (values[index].t.tv_sec != 0 || values[index].t.tv_nsec != 0) + states++; + tsadd (&sum, &values[index].t); + } + + // If the sum of all times is greater than rtime then adjust + // rtime to be equal to sum and also adjust the pr_rtime field + hr2timestruc (&rtime, prusage->pr_rtime); + if (tscmp (&sum, &rtime) > 0) + { + ovw_item->total.t = sum; + values[0].t = zero; + } + else + { + ovw_item->total.t = rtime; + tssub (&rtime, &rtime, &sum); + tsadd (&values[0].t, &rtime); + states++; + } + ovw_item->type = VT_HRTIME; + ovw_item->states = states; +} |