]>
Commit | Line | Data |
---|---|---|
fd67aa11 | 1 | /* Copyright (C) 2021-2024 Free Software Foundation, Inc. |
bb368aad VM |
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 | } |