]>
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 "CallStack.h" | |
23 | #include "DbeSession.h" | |
24 | #include "Exp_Layout.h" | |
25 | #include "Experiment.h" | |
26 | #include "Function.h" | |
27 | #include "Table.h" | |
28 | #include "dbe_types.h" | |
29 | #include "util.h" | |
30 | ||
31 | /* | |
32 | * PrUsage is a class which wraps access to the values of prusage | |
33 | * system structure. It was expanded to 64 bit entities in 2.7 | |
34 | * (experiment version 6 & 7). | |
35 | */ | |
36 | PrUsage::PrUsage () | |
37 | { | |
38 | pr_tstamp = pr_create = pr_term = pr_rtime = (hrtime_t) 0; | |
39 | pr_utime = pr_stime = pr_ttime = pr_tftime = pr_dftime = (hrtime_t) 0; | |
40 | pr_kftime = pr_ltime = pr_slptime = pr_wtime = pr_stoptime = (hrtime_t) 0; | |
41 | ||
42 | pr_minf = pr_majf = pr_nswap = pr_inblk = pr_oublk = 0; | |
43 | pr_msnd = pr_mrcv = pr_sigs = pr_vctx = pr_ictx = pr_sysc = pr_ioch = 0; | |
44 | } | |
45 | ||
46 | /* | |
47 | * Resource usage. /proc/<pid>/usage /proc/<pid>/lwp/<lwpid>/lwpusage | |
48 | */ | |
49 | struct timestruc_32 | |
50 | { /* v8 timestruc_t */ | |
51 | uint32_t tv_sec; /* seconds */ | |
52 | uint32_t tv_nsec; /* and nanoseconds */ | |
53 | }; | |
54 | ||
55 | typedef struct ana_prusage | |
56 | { | |
57 | id_t pr_lwpid; /* lwp id. 0: process or defunct */ | |
58 | int pr_count; /* number of contributing lwps */ | |
59 | timestruc_32 pr_tstamp; /* current time stamp */ | |
60 | timestruc_32 pr_create; /* process/lwp creation time stamp */ | |
61 | timestruc_32 pr_term; /* process/lwp termination time stamp */ | |
62 | timestruc_32 pr_rtime; /* total lwp real (elapsed) time */ | |
63 | timestruc_32 pr_utime; /* user level cpu time */ | |
64 | timestruc_32 pr_stime; /* system call cpu time */ | |
65 | timestruc_32 pr_ttime; /* other system trap cpu time */ | |
66 | timestruc_32 pr_tftime; /* text page fault sleep time */ | |
67 | timestruc_32 pr_dftime; /* data page fault sleep time */ | |
68 | timestruc_32 pr_kftime; /* kernel page fault sleep time */ | |
69 | timestruc_32 pr_ltime; /* user lock wait sleep time */ | |
70 | timestruc_32 pr_slptime; /* all other sleep time */ | |
71 | timestruc_32 pr_wtime; /* wait-cpu (latency) time */ | |
72 | timestruc_32 pr_stoptime; /* stopped time */ | |
73 | timestruc_32 filltime[6]; /* filler for future expansion */ | |
74 | uint32_t pr_minf; /* minor page faults */ | |
75 | uint32_t pr_majf; /* major page faults */ | |
76 | uint32_t pr_nswap; /* swaps */ | |
77 | uint32_t pr_inblk; /* input blocks */ | |
78 | uint32_t pr_oublk; /* output blocks */ | |
79 | uint32_t pr_msnd; /* messages sent */ | |
80 | uint32_t pr_mrcv; /* messages received */ | |
81 | uint32_t pr_sigs; /* signals received */ | |
82 | uint32_t pr_vctx; /* voluntary context switches */ | |
83 | uint32_t pr_ictx; /* involuntary context switches */ | |
84 | uint32_t pr_sysc; /* system calls */ | |
85 | uint32_t pr_ioch; /* chars read and written */ | |
86 | uint32_t filler[10]; /* filler for future expansion */ | |
87 | } raw_prusage_32; | |
88 | ||
89 | uint64_t | |
90 | PrUsage::bind32Size () | |
91 | { | |
92 | uint64_t bindSize = sizeof (raw_prusage_32); | |
93 | return bindSize; | |
94 | } | |
95 | ||
96 | #define timestruc2hr(x) ((hrtime_t)(x).tv_sec*NANOSEC + (hrtime_t)(x).tv_nsec) | |
97 | ||
98 | PrUsage * | |
99 | PrUsage::bind32 (void *p, bool need_swap_endian) | |
100 | { | |
101 | if (p == NULL) | |
102 | return NULL; | |
103 | raw_prusage_32 pu, *tmp = (raw_prusage_32*) p; | |
104 | if (need_swap_endian) | |
105 | { | |
106 | pu = *tmp; | |
107 | tmp = &pu; | |
108 | SWAP_ENDIAN (pu.pr_tstamp.tv_sec); | |
109 | SWAP_ENDIAN (pu.pr_tstamp.tv_nsec); | |
110 | SWAP_ENDIAN (pu.pr_create.tv_sec); | |
111 | SWAP_ENDIAN (pu.pr_create.tv_nsec); | |
112 | SWAP_ENDIAN (pu.pr_term.tv_sec); | |
113 | SWAP_ENDIAN (pu.pr_term.tv_nsec); | |
114 | SWAP_ENDIAN (pu.pr_rtime.tv_sec); | |
115 | SWAP_ENDIAN (pu.pr_rtime.tv_nsec); | |
116 | SWAP_ENDIAN (pu.pr_utime.tv_sec); | |
117 | SWAP_ENDIAN (pu.pr_utime.tv_nsec); | |
118 | SWAP_ENDIAN (pu.pr_stime.tv_sec); | |
119 | SWAP_ENDIAN (pu.pr_stime.tv_nsec); | |
120 | SWAP_ENDIAN (pu.pr_ttime.tv_sec); | |
121 | SWAP_ENDIAN (pu.pr_ttime.tv_nsec); | |
122 | SWAP_ENDIAN (pu.pr_tftime.tv_sec); | |
123 | SWAP_ENDIAN (pu.pr_tftime.tv_nsec); | |
124 | SWAP_ENDIAN (pu.pr_dftime.tv_sec); | |
125 | SWAP_ENDIAN (pu.pr_dftime.tv_nsec); | |
126 | SWAP_ENDIAN (pu.pr_kftime.tv_sec); | |
127 | SWAP_ENDIAN (pu.pr_kftime.tv_nsec); | |
128 | SWAP_ENDIAN (pu.pr_ltime.tv_sec); | |
129 | SWAP_ENDIAN (pu.pr_ltime.tv_nsec); | |
130 | SWAP_ENDIAN (pu.pr_slptime.tv_sec); | |
131 | SWAP_ENDIAN (pu.pr_slptime.tv_nsec); | |
132 | SWAP_ENDIAN (pu.pr_wtime.tv_sec); | |
133 | SWAP_ENDIAN (pu.pr_wtime.tv_nsec); | |
134 | SWAP_ENDIAN (pu.pr_stoptime.tv_sec); | |
135 | SWAP_ENDIAN (pu.pr_stoptime.tv_nsec); | |
136 | SWAP_ENDIAN (pu.pr_minf); | |
137 | SWAP_ENDIAN (pu.pr_majf); | |
138 | SWAP_ENDIAN (pu.pr_nswap); | |
139 | SWAP_ENDIAN (pu.pr_inblk); | |
140 | SWAP_ENDIAN (pu.pr_oublk); | |
141 | SWAP_ENDIAN (pu.pr_msnd); | |
142 | SWAP_ENDIAN (pu.pr_mrcv); | |
143 | SWAP_ENDIAN (pu.pr_sigs); | |
144 | SWAP_ENDIAN (pu.pr_vctx); | |
145 | SWAP_ENDIAN (pu.pr_ictx); | |
146 | SWAP_ENDIAN (pu.pr_sysc); | |
147 | SWAP_ENDIAN (pu.pr_ioch); | |
148 | } | |
149 | pr_tstamp = timestruc2hr (tmp->pr_tstamp); | |
150 | pr_create = timestruc2hr (tmp->pr_create); | |
151 | pr_term = timestruc2hr (tmp->pr_term); | |
152 | pr_rtime = timestruc2hr (tmp->pr_rtime); | |
153 | pr_utime = timestruc2hr (tmp->pr_utime); | |
154 | pr_stime = timestruc2hr (tmp->pr_stime); | |
155 | pr_ttime = timestruc2hr (tmp->pr_ttime); | |
156 | pr_tftime = timestruc2hr (tmp->pr_tftime); | |
157 | pr_dftime = timestruc2hr (tmp->pr_dftime); | |
158 | pr_kftime = timestruc2hr (tmp->pr_kftime); | |
159 | pr_ltime = timestruc2hr (tmp->pr_ltime); | |
160 | pr_slptime = timestruc2hr (tmp->pr_slptime); | |
161 | pr_wtime = timestruc2hr (tmp->pr_wtime); | |
162 | pr_stoptime = timestruc2hr (tmp->pr_stoptime); | |
163 | pr_minf = tmp->pr_minf; | |
164 | pr_majf = tmp->pr_majf; | |
165 | pr_nswap = tmp->pr_nswap; | |
166 | pr_inblk = tmp->pr_inblk; | |
167 | pr_oublk = tmp->pr_oublk; | |
168 | pr_msnd = tmp->pr_msnd; | |
169 | pr_mrcv = tmp->pr_mrcv; | |
170 | pr_sigs = tmp->pr_sigs; | |
171 | pr_vctx = tmp->pr_vctx; | |
172 | pr_ictx = tmp->pr_ictx; | |
173 | pr_sysc = tmp->pr_sysc; | |
174 | pr_ioch = tmp->pr_ioch; | |
175 | return this; | |
176 | } | |
177 | ||
178 | struct timestruc_64 | |
179 | { /* 64-bit timestruc_t */ | |
180 | uint64_t tv_sec; /* seconds */ | |
181 | uint64_t tv_nsec; /* and nanoseconds */ | |
182 | }; | |
183 | ||
184 | typedef struct | |
185 | { | |
186 | id_t pr_lwpid; /* lwp id. 0: process or defunct */ | |
187 | int pr_count; /* number of contributing lwps */ | |
188 | timestruc_64 pr_tstamp; /* current time stamp */ | |
189 | timestruc_64 pr_create; /* process/lwp creation time stamp */ | |
190 | timestruc_64 pr_term; /* process/lwp termination time stamp */ | |
191 | timestruc_64 pr_rtime; /* total lwp real (elapsed) time */ | |
192 | timestruc_64 pr_utime; /* user level cpu time */ | |
193 | timestruc_64 pr_stime; /* system call cpu time */ | |
194 | timestruc_64 pr_ttime; /* other system trap cpu time */ | |
195 | timestruc_64 pr_tftime; /* text page fault sleep time */ | |
196 | timestruc_64 pr_dftime; /* data page fault sleep time */ | |
197 | timestruc_64 pr_kftime; /* kernel page fault sleep time */ | |
198 | timestruc_64 pr_ltime; /* user lock wait sleep time */ | |
199 | timestruc_64 pr_slptime; /* all other sleep time */ | |
200 | timestruc_64 pr_wtime; /* wait-cpu (latency) time */ | |
201 | timestruc_64 pr_stoptime; /* stopped time */ | |
202 | timestruc_64 filltime[6]; /* filler for future expansion */ | |
203 | uint64_t pr_minf; /* minor page faults */ | |
204 | uint64_t pr_majf; /* major page faults */ | |
205 | uint64_t pr_nswap; /* swaps */ | |
206 | uint64_t pr_inblk; /* input blocks */ | |
207 | uint64_t pr_oublk; /* output blocks */ | |
208 | uint64_t pr_msnd; /* messages sent */ | |
209 | uint64_t pr_mrcv; /* messages received */ | |
210 | uint64_t pr_sigs; /* signals received */ | |
211 | uint64_t pr_vctx; /* voluntary context switches */ | |
212 | uint64_t pr_ictx; /* involuntary context switches */ | |
213 | uint64_t pr_sysc; /* system calls */ | |
214 | uint64_t pr_ioch; /* chars read and written */ | |
215 | uint64_t filler[10]; /* filler for future expansion */ | |
216 | } raw_prusage_64; | |
217 | ||
218 | uint64_t | |
219 | PrUsage::bind64Size () | |
220 | { | |
221 | uint64_t bindSize = sizeof (raw_prusage_64); | |
222 | return bindSize; | |
223 | } | |
224 | ||
225 | PrUsage * | |
226 | PrUsage::bind64 (void *p, bool need_swap_endian) | |
227 | { | |
228 | if (p == NULL) | |
229 | { | |
230 | return NULL; | |
231 | } | |
232 | raw_prusage_64 pu, *tmp = (raw_prusage_64*) p; | |
233 | if (need_swap_endian) | |
234 | { | |
235 | pu = *tmp; | |
236 | tmp = &pu; | |
237 | SWAP_ENDIAN (pu.pr_tstamp.tv_sec); | |
238 | SWAP_ENDIAN (pu.pr_tstamp.tv_nsec); | |
239 | SWAP_ENDIAN (pu.pr_create.tv_sec); | |
240 | SWAP_ENDIAN (pu.pr_create.tv_nsec); | |
241 | SWAP_ENDIAN (pu.pr_term.tv_sec); | |
242 | SWAP_ENDIAN (pu.pr_term.tv_nsec); | |
243 | SWAP_ENDIAN (pu.pr_rtime.tv_sec); | |
244 | SWAP_ENDIAN (pu.pr_rtime.tv_nsec); | |
245 | SWAP_ENDIAN (pu.pr_utime.tv_sec); | |
246 | SWAP_ENDIAN (pu.pr_utime.tv_nsec); | |
247 | SWAP_ENDIAN (pu.pr_stime.tv_sec); | |
248 | SWAP_ENDIAN (pu.pr_stime.tv_nsec); | |
249 | SWAP_ENDIAN (pu.pr_ttime.tv_sec); | |
250 | SWAP_ENDIAN (pu.pr_ttime.tv_nsec); | |
251 | SWAP_ENDIAN (pu.pr_tftime.tv_sec); | |
252 | SWAP_ENDIAN (pu.pr_tftime.tv_nsec); | |
253 | SWAP_ENDIAN (pu.pr_dftime.tv_sec); | |
254 | SWAP_ENDIAN (pu.pr_dftime.tv_nsec); | |
255 | SWAP_ENDIAN (pu.pr_kftime.tv_sec); | |
256 | SWAP_ENDIAN (pu.pr_kftime.tv_nsec); | |
257 | SWAP_ENDIAN (pu.pr_ltime.tv_sec); | |
258 | SWAP_ENDIAN (pu.pr_ltime.tv_nsec); | |
259 | SWAP_ENDIAN (pu.pr_slptime.tv_sec); | |
260 | SWAP_ENDIAN (pu.pr_slptime.tv_nsec); | |
261 | SWAP_ENDIAN (pu.pr_wtime.tv_sec); | |
262 | SWAP_ENDIAN (pu.pr_wtime.tv_nsec); | |
263 | SWAP_ENDIAN (pu.pr_stoptime.tv_sec); | |
264 | SWAP_ENDIAN (pu.pr_stoptime.tv_nsec); | |
265 | SWAP_ENDIAN (pu.pr_minf); | |
266 | SWAP_ENDIAN (pu.pr_majf); | |
267 | SWAP_ENDIAN (pu.pr_nswap); | |
268 | SWAP_ENDIAN (pu.pr_inblk); | |
269 | SWAP_ENDIAN (pu.pr_oublk); | |
270 | SWAP_ENDIAN (pu.pr_msnd); | |
271 | SWAP_ENDIAN (pu.pr_mrcv); | |
272 | SWAP_ENDIAN (pu.pr_sigs); | |
273 | SWAP_ENDIAN (pu.pr_vctx); | |
274 | SWAP_ENDIAN (pu.pr_ictx); | |
275 | SWAP_ENDIAN (pu.pr_sysc); | |
276 | SWAP_ENDIAN (pu.pr_ioch); | |
277 | } | |
278 | ||
279 | pr_tstamp = timestruc2hr (tmp->pr_tstamp); | |
280 | pr_create = timestruc2hr (tmp->pr_create); | |
281 | pr_term = timestruc2hr (tmp->pr_term); | |
282 | pr_rtime = timestruc2hr (tmp->pr_rtime); | |
283 | pr_utime = timestruc2hr (tmp->pr_utime); | |
284 | pr_stime = timestruc2hr (tmp->pr_stime); | |
285 | pr_ttime = timestruc2hr (tmp->pr_ttime); | |
286 | pr_tftime = timestruc2hr (tmp->pr_tftime); | |
287 | pr_dftime = timestruc2hr (tmp->pr_dftime); | |
288 | pr_kftime = timestruc2hr (tmp->pr_kftime); | |
289 | pr_ltime = timestruc2hr (tmp->pr_ltime); | |
290 | pr_slptime = timestruc2hr (tmp->pr_slptime); | |
291 | pr_wtime = timestruc2hr (tmp->pr_wtime); | |
292 | pr_stoptime = timestruc2hr (tmp->pr_stoptime); | |
293 | pr_minf = tmp->pr_minf; | |
294 | pr_majf = tmp->pr_majf; | |
295 | pr_nswap = tmp->pr_nswap; | |
296 | pr_inblk = tmp->pr_inblk; | |
297 | pr_oublk = tmp->pr_oublk; | |
298 | pr_msnd = tmp->pr_msnd; | |
299 | pr_mrcv = tmp->pr_mrcv; | |
300 | pr_sigs = tmp->pr_sigs; | |
301 | pr_vctx = tmp->pr_vctx; | |
302 | pr_ictx = tmp->pr_ictx; | |
303 | pr_sysc = tmp->pr_sysc; | |
304 | pr_ioch = tmp->pr_ioch; | |
305 | return this; | |
306 | } | |
307 | ||
308 | Vector<long long> * | |
309 | PrUsage::getMstateValues () | |
310 | { | |
311 | const PrUsage *prusage = this; | |
312 | Vector<long long> *states = new Vector<long long>; | |
313 | states->store (0, prusage->pr_utime); | |
314 | states->store (1, prusage->pr_stime); | |
315 | states->store (2, prusage->pr_ttime); | |
316 | states->store (3, prusage->pr_tftime); | |
317 | states->store (4, prusage->pr_dftime); | |
318 | states->store (5, prusage->pr_kftime); | |
319 | states->store (6, prusage->pr_ltime); | |
320 | states->store (7, prusage->pr_slptime); | |
321 | states->store (8, prusage->pr_wtime); | |
322 | states->store (9, prusage->pr_stoptime); | |
323 | assert (LMS_NUM_SOLARIS_MSTATES == states->size ()); | |
324 | return states; | |
325 | } | |
326 | ||
327 | void* CommonPacket::jvm_overhead = NULL; | |
328 | ||
329 | CommonPacket::CommonPacket () | |
330 | { | |
331 | for (int i = 0; i < NTAGS; i++) | |
332 | tags[i] = 0; | |
333 | tstamp = 0; | |
334 | jthread_TBR = NULL; | |
335 | frinfo = 0; | |
336 | leafpc = 0; | |
337 | nat_stack = NULL; | |
338 | user_stack = NULL; | |
339 | } | |
340 | ||
341 | int | |
342 | CommonPacket::cmp (const void *a, const void *b) | |
343 | { | |
344 | if ((*(CommonPacket **) a)->tstamp > (*(CommonPacket **) b)->tstamp) | |
345 | return 1; | |
346 | else if ((*(CommonPacket **) a)->tstamp < (*(CommonPacket **) b)->tstamp) | |
347 | return -1; | |
348 | else | |
349 | return 0; | |
350 | } | |
351 | ||
352 | void * | |
353 | CommonPacket::getStack (VMode view_mode) | |
354 | { | |
355 | if (view_mode == VMODE_MACHINE) | |
356 | return nat_stack; | |
357 | else if (view_mode == VMODE_USER) | |
358 | { | |
359 | if (jthread_TBR == JTHREAD_NONE || (jthread_TBR && jthread_TBR->is_system ())) | |
360 | return jvm_overhead; | |
361 | } | |
362 | else if (view_mode == VMODE_EXPERT) | |
363 | { | |
364 | Histable *hist = CallStack::getStackPC (user_stack, 0); | |
365 | if (hist->get_type () == Histable::INSTR) | |
366 | { | |
367 | DbeInstr *instr = (DbeInstr*) hist; | |
368 | if (instr->func == dbeSession->get_JUnknown_Function ()) | |
369 | return nat_stack; | |
370 | } | |
371 | else if (hist->get_type () == Histable::LINE) | |
372 | { | |
373 | DbeLine *line = (DbeLine *) hist; | |
374 | if (line->func == dbeSession->get_JUnknown_Function ()) | |
375 | return nat_stack; | |
376 | } | |
377 | } | |
378 | return user_stack; | |
379 | } | |
380 | ||
381 | Histable * | |
382 | CommonPacket::getStackPC (int n, VMode view_mode) | |
383 | { | |
384 | return CallStack::getStackPC (getStack (view_mode), n); | |
385 | } | |
386 | ||
387 | Vector<Histable*> * | |
388 | CommonPacket::getStackPCs (VMode view_mode) | |
389 | { | |
390 | return CallStack::getStackPCs (getStack (view_mode)); | |
391 | } | |
392 | ||
393 | void * | |
394 | getStack (VMode view_mode, DataView *dview, long idx) | |
395 | { | |
396 | void *stack = NULL; | |
397 | if (view_mode == VMODE_MACHINE) | |
398 | stack = dview->getObjValue (PROP_MSTACK, idx); | |
399 | else if (view_mode == VMODE_USER) | |
400 | stack = dview->getObjValue (PROP_USTACK, idx); | |
401 | else if (view_mode == VMODE_EXPERT) | |
402 | stack = dview->getObjValue (PROP_XSTACK, idx); | |
403 | return stack; | |
404 | } | |
405 | ||
406 | int | |
407 | stackSize (VMode view_mode, DataView *dview, long idx) | |
408 | { | |
409 | return CallStack::stackSize (getStack (view_mode, dview, idx)); | |
410 | } | |
411 | ||
412 | Histable * | |
413 | getStackPC (int n, VMode view_mode, DataView *dview, long idx) | |
414 | { | |
415 | return CallStack::getStackPC (getStack (view_mode, dview, idx), n); | |
416 | } | |
417 | ||
418 | Vector<Histable*> * | |
419 | getStackPCs (VMode view_mode, DataView *dview, long idx) | |
420 | { | |
421 | return CallStack::getStackPCs (getStack (view_mode, dview, idx)); | |
422 | } |