xref: /netbsd-src/external/gpl3/binutils.old/dist/gprofng/src/Ovw_data.cc (revision b2c35e17b976cf7ccd7250c86c6f5e95090ed636)
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 
34 void
35 Ovw_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 
57 Ovw_data::Ovw_item *
58 Ovw_data::reset_item (Ovw_data::Ovw_item *item)
59 {
60   memset (item, 0, sizeof (*item));
61   return item;
62 }
63 
64 Ovw_data::Ovw_item
65 Ovw_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 
117 Ovw_data::Ovw_item
118 Ovw_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 
144 Ovw_data::Ovw_data ()
145 {
146   packets = NULL;
147   ovw_items = new Vector<Ovw_item*>;
148   totals = NULL;
149 }
150 
151 Ovw_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 
182 Ovw_data::~Ovw_data ()
183 {
184   ovw_items->destroy ();
185   delete ovw_items;
186   delete totals;
187 }
188 
189 void
190 Ovw_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