GCC Code Coverage Report


Directory: src/
File: src/talp/talp_hwc.c
Date: 2026-10-14 08:39:21
Exec Total Coverage
Lines: 5 57 8.8%
Functions: 1 6 16.7%
Branches: 1 34 2.9%

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 hw_counters_t last_raw; // last raw value from backend
39 } hwc_ctx_t;
40
41 static __thread hwc_ctx_t ctx = {0};
42
43 static const backend_api_t *hwc_backend_api = NULL;
44
45
46 28 int talp_hwc_init(const subprocess_descriptor_t *spd) {
47
48 28 hwc_backend_api = talp_backend_manager_load_hwc_backend(spd->options.talp_hwc_backend);
49
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (hwc_backend_api == NULL) {
50 28 debug_warning("HWC backend could not be loaded");
51 28 return DLB_ERR_UNKNOWN;
52 }
53
54 int error;
55
56 /* If HWC component is not explicitly set, probe plugin first */
57 ✗ if (!(spd->options.talp & TALP_COMPONENT_HWC)) {
58 ✗ error = hwc_backend_api->probe();
59 ✗ if (error == DLB_BACKEND_ERROR) {
60 ✗ debug_warning("HWC backend probe failed");
61 ✗ return DLB_ERR_UNKNOWN;
62 }
63 }
64
65 ✗ error = hwc_backend_api->init(&core_api);
66 ✗ if (error == DLB_BACKEND_ERROR) {
67 ✗ debug_warning("HWC backend could not be initialized");
68 ✗ return DLB_ERR_UNKNOWN;
69 }
70
71 ✗ error = hwc_backend_api->start();
72 ✗ if (error == DLB_BACKEND_ERROR) {
73 ✗ debug_warning("HWC backend could not be started");
74 ✗ hwc_backend_api->finalize();
75 ✗ return DLB_ERR_UNKNOWN;
76 }
77
78 ✗ return DLB_SUCCESS;
79 }
80
81
82 ✗ int talp_hwc_thread_init(void) {
83
84 ✗ if (hwc_backend_api == NULL) return DLB_ERR_UNKNOWN;
85
86 ✗ int error = hwc_backend_api->start();
87 ✗ if (error == DLB_BACKEND_ERROR) return DLB_ERR_UNKNOWN;
88
89 ✗ return DLB_SUCCESS;
90 }
91
92
93 ✗ void talp_hwc_finalize(void) {
94
95 ✗ if (hwc_backend_api != NULL) {
96
97 ✗ hwc_backend_api->stop();
98 ✗ hwc_backend_api->finalize();
99
100 ✗ talp_backend_manager_unload_hwc_backend();
101 ✗ hwc_backend_api = NULL;
102 }
103 }
104
105 ✗ void talp_hwc_thread_finalize(void) {
106
107 ✗ if (hwc_backend_api != NULL) {
108 ✗ hwc_backend_api->stop();
109 }
110 }
111
112 ✗ void talp_hwc_on_state_change(talp_sample_state_t old_state, talp_sample_state_t new_state) {
113
114 ✗ if (old_state != TALP_STATE_USEFUL
115 ✗ && new_state == TALP_STATE_USEFUL) {
116
117 ✗ ctx.active = true;
118 ✗ if (hwc_backend_api->hwc.collect(&ctx.last_raw) == DLB_BACKEND_SUCCESS) {
119 ✗ ctx.have_last = true;
120 }
121 }
122
123 ✗ else if (old_state == TALP_STATE_USEFUL
124 ✗ && new_state != TALP_STATE_USEFUL) {
125 ✗ ctx.active = false;
126 }
127 }
128
129 ✗ bool talp_hwc_collect(hw_counters_t *out) {
130
131 ✗ if (!ctx.active) {
132 ✗ return false;
133 }
134
135 hw_counters_t raw;
136 ✗ if (hwc_backend_api->hwc.collect(&raw) != DLB_BACKEND_SUCCESS) {
137 ✗ return false;
138 }
139
140 /* Only if we try to collect before changing to 'useful' for the first time,
141 * discard this reading and use it as baseline for the next. */
142 ✗ if (unlikely(!ctx.have_last)) {
143 ✗ ctx.have_last = true;
144 ✗ ctx.last_raw = raw;
145 ✗ return false;
146 }
147
148 ✗ *out = (hw_counters_t) {
149 ✗ .cycles = raw.cycles - ctx.last_raw.cycles,
150 ✗ .instructions = raw.instructions - ctx.last_raw.instructions,
151 };
152
153 ✗ ctx.last_raw = raw;
154
155 ✗ return true;
156 }
157