GCC Code Coverage Report


Directory: src/
File: src/talp/talp_hwc.c
Date: 2026-04-21 15:16:03
Exec Total Coverage
Lines: 5 60 8.3%
Functions: 1 7 14.3%
Branches: 1 32 3.1%

Line Branch Exec Source
1 /*********************************************************************************/
2 /* Copyright 2009-2026 Barcelona Supercomputing Center */
3 /* */
4 /* This file is part of the DLB library. */
5 /* */
6 /* DLB is free software: you can redistribute it and/or modify */
7 /* it under the terms of the GNU Lesser General Public License as published by */
8 /* the Free Software Foundation, either version 3 of the License, or */
9 /* (at your option) any later version. */
10 /* */
11 /* DLB 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 Lesser General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU Lesser General Public License */
17 /* along with DLB. If not, see <https://www.gnu.org/licenses/>. */
18 /*********************************************************************************/
19
20 #include "talp/talp_hwc.h"
21
22 #include "apis/dlb_errors.h"
23 #include "LB_core/spd.h"
24 #include "support/atomic.h"
25 #include "support/debug.h"
26 #include "support/dlb_common.h"
27 #include "talp/backend.h"
28 #include "talp/backend_manager.h"
29 #include "talp/regions.h"
30 #include "talp/talp.h"
31 #include "talp/talp_output.h"
32 #include "talp/talp_types.h"
33
34
35 typedef struct {
36 bool active;
37 bool have_last;
38 hwc_measurements_t last_raw; // last raw value from backend
39 hwc_measurements_t accum; // accumulated delta
40 } hwc_ctx_t;
41
42 static __thread hwc_ctx_t ctx = {0};
43
44 static const backend_api_t *hwc_backend_api = NULL;
45
46
47 23 int talp_hwc_init(const subprocess_descriptor_t *spd) {
48
49 23 hwc_backend_api = talp_backend_manager_load_hwc_backend(NULL);
50
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if (hwc_backend_api == NULL) {
51 23 debug_warning("HWC backend could not be loaded");
52 23 return DLB_ERR_UNKNOWN;
53 }
54
55 int error;
56
57 /* If HWC component is not explicitly set, probe plugin first */
58 if (!(spd->options.talp & TALP_COMPONENT_HWC)) {
59 error = hwc_backend_api->probe();
60 if (error == DLB_BACKEND_ERROR) {
61 debug_warning("HWC backend probe failed");
62 return DLB_ERR_UNKNOWN;
63 }
64 }
65
66 error = hwc_backend_api->init(&core_api);
67 if (error == DLB_BACKEND_ERROR) {
68 debug_warning("HWC backend could not be initialized");
69 return DLB_ERR_UNKNOWN;
70 }
71
72 error = hwc_backend_api->start();
73 if (error == DLB_BACKEND_ERROR) {
74 debug_warning("HWC backend could not be started");
75 hwc_backend_api->finalize();
76 return DLB_ERR_UNKNOWN;
77 }
78
79 return DLB_SUCCESS;
80 }
81
82
83 int talp_hwc_thread_init(void) {
84
85 if (hwc_backend_api == NULL) return DLB_ERR_UNKNOWN;
86
87 int error = hwc_backend_api->start();
88 if (error == DLB_BACKEND_ERROR) return DLB_ERR_UNKNOWN;
89
90 return DLB_SUCCESS;
91 }
92
93
94 void talp_hwc_finalize(void) {
95
96 if (hwc_backend_api != NULL) {
97
98 hwc_backend_api->stop();
99 hwc_backend_api->finalize();
100
101 talp_backend_manager_unload_hwc_backend();
102 hwc_backend_api = NULL;
103 }
104 }
105
106 void talp_hwc_thread_finalize(void) {
107
108 if (hwc_backend_api != NULL) {
109 hwc_backend_api->stop();
110 }
111 }
112
113 void talp_hwc_on_state_change(talp_sample_state_t old_state, talp_sample_state_t new_state) {
114
115 if (old_state != TALP_STATE_USEFUL
116 && new_state == TALP_STATE_USEFUL) {
117 // ctx.last_raw is updated here
118 ctx.active = true;
119 ctx.have_last = false;
120 hwc_backend_api->flush();
121 }
122
123 else if (old_state == TALP_STATE_USEFUL
124 && new_state != TALP_STATE_USEFUL) {
125 ctx.active = false;
126 }
127 }
128
129 // called from backend plugin
130 void talp_hwc_submit(const hwc_measurements_t *raw) {
131
132 if (!ctx.active) return;
133
134 // First submission after changing to 'useful'
135 if (!ctx.have_last) {
136 ctx.have_last = true;
137 ctx.last_raw = *raw;
138 return;
139 }
140
141 ctx.accum.cycles += raw->cycles - ctx.last_raw.cycles;
142 ctx.accum.instructions += raw->instructions - ctx.last_raw.instructions;
143
144 ctx.last_raw = *raw;
145 }
146
147 // called from core
148 bool talp_hwc_collect(hwc_measurements_t *out) {
149
150 if (!ctx.active) {
151 *out = (const hwc_measurements_t){0};
152 return false;
153 }
154
155 // plugin updates ctx at this point
156 hwc_backend_api->flush();
157
158 *out = ctx.accum;
159 ctx.accum = (const hwc_measurements_t){0};
160
161 return true;
162 }
163