hwcfuncs.c revision 1.1.1.3 1 1.1.1.3 christos /* Copyright (C) 2021-2025 Free Software Foundation, Inc.
2 1.1 christos Contributed by Oracle.
3 1.1 christos
4 1.1 christos This file is part of GNU Binutils.
5 1.1 christos
6 1.1 christos This program is free software; you can redistribute it and/or modify
7 1.1 christos it under the terms of the GNU General Public License as published by
8 1.1 christos the Free Software Foundation; either version 3, or (at your option)
9 1.1 christos any later version.
10 1.1 christos
11 1.1 christos This program is distributed in the hope that it will be useful,
12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 christos GNU General Public License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with this program; if not, write to the Free Software
18 1.1 christos Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 1.1 christos MA 02110-1301, USA. */
20 1.1 christos
21 1.1 christos /* Hardware counter profiling */
22 1.1 christos #include "hwcdrv.h"
23 1.1 christos #include "hwcfuncs.h"
24 1.1 christos
25 1.1 christos /*---------------------------------------------------------------------------*/
26 1.1 christos /* macros */
27 1.1 christos
28 1.1 christos #define IS_GLOBAL /* Mark global symbols */
29 1.1 christos #define HWCDRV_API static /* Mark functions used by hwcdrv API */
30 1.1 christos
31 1.1 christos /*---------------------------------------------------------------------------*/
32 1.1 christos /* static variables */
33 1.1 christos static uint_t cpcN_npics;
34 1.1 christos static char hwcfuncs_errmsg_buf[1024];
35 1.1 christos static int hwcfuncs_errmsg_enabled = 1;
36 1.1 christos static int hwcfuncs_errmsg_valid;
37 1.1 christos
38 1.1 christos /* --- user counter selections and options */
39 1.1 christos static unsigned hwcdef_cnt; /* number of *active* hardware counters */
40 1.1 christos static Hwcentry hwcdef[MAX_PICS]; /* HWC definitions */
41 1.1 christos static Hwcentry *hwctable[MAX_PICS]; /* HWC definitions */
42 1.1 christos
43 1.1 christos /* --- drivers --- */
44 1.1 christos
45 1.1 christos // default driver
46 1.1 christos
47 1.1 christos HWCDRV_API int
48 1.1 christos hwcdrv_init (hwcfuncs_abort_fn_t abort_ftn, int* tsd_sz)
49 1.1 christos {
50 1.1 christos return -1;
51 1.1 christos }
52 1.1 christos
53 1.1 christos HWCDRV_API void
54 1.1 christos hwcdrv_get_info (
55 1.1 christos int * cpuver, const char ** cciname,
56 1.1 christos uint_t * npics, const char ** docref, uint64_t* support) { }
57 1.1 christos
58 1.1 christos HWCDRV_API int
59 1.1 christos hwcdrv_enable_mt (hwcfuncs_tsd_get_fn_t tsd_ftn)
60 1.1 christos {
61 1.1 christos return -1;
62 1.1 christos }
63 1.1 christos
64 1.1 christos HWCDRV_API int
65 1.1 christos hwcdrv_get_descriptions (hwcf_hwc_cb_t *hwc_find_action,
66 1.1.1.3 christos hwcf_attr_cb_t *attr_find_action, Hwcentry *hwcdef)
67 1.1 christos {
68 1.1 christos return 0;
69 1.1 christos }
70 1.1 christos
71 1.1 christos HWCDRV_API int
72 1.1 christos hwcdrv_assign_regnos (Hwcentry *entries[], unsigned numctrs)
73 1.1 christos {
74 1.1 christos return -1;
75 1.1 christos }
76 1.1 christos
77 1.1 christos HWCDRV_API int
78 1.1 christos hwcdrv_create_counters (unsigned hwcdef_cnt, Hwcentry *hwcdef)
79 1.1 christos {
80 1.1 christos return -1;
81 1.1 christos }
82 1.1 christos
83 1.1 christos HWCDRV_API int
84 1.1 christos hwcdrv_read_events (hwc_event_t *events, hwc_event_samples_t*samples)
85 1.1 christos {
86 1.1 christos return -1;
87 1.1 christos }
88 1.1 christos
89 1.1 christos HWCDRV_API int
90 1.1 christos hwcdrv_start (void)
91 1.1 christos {
92 1.1 christos return -1;
93 1.1 christos }
94 1.1 christos
95 1.1 christos HWCDRV_API int
96 1.1 christos hwcdrv_overflow (siginfo_t *si, hwc_event_t *s, hwc_event_t *t)
97 1.1 christos {
98 1.1 christos return 0;
99 1.1 christos }
100 1.1 christos
101 1.1 christos HWCDRV_API int
102 1.1 christos hwcdrv_sighlr_restart (const hwc_event_t *sample)
103 1.1 christos {
104 1.1 christos return -1;
105 1.1 christos }
106 1.1 christos
107 1.1 christos HWCDRV_API int
108 1.1 christos hwcdrv_lwp_suspend (void)
109 1.1 christos {
110 1.1 christos return -1;
111 1.1 christos }
112 1.1 christos
113 1.1 christos HWCDRV_API int
114 1.1 christos hwcdrv_lwp_resume (void)
115 1.1 christos {
116 1.1 christos return -1;
117 1.1 christos }
118 1.1 christos
119 1.1 christos HWCDRV_API int
120 1.1 christos hwcdrv_free_counters (void)
121 1.1 christos {
122 1.1 christos return 0;
123 1.1 christos }
124 1.1 christos
125 1.1 christos HWCDRV_API int
126 1.1 christos hwcdrv_lwp_init (void)
127 1.1 christos {
128 1.1 christos return 0;
129 1.1 christos }
130 1.1 christos
131 1.1 christos HWCDRV_API void
132 1.1 christos hwcdrv_lwp_fini (void) { }
133 1.1 christos
134 1.1 christos static hwcdrv_api_t hwcdrv_default = {
135 1.1 christos hwcdrv_init,
136 1.1 christos hwcdrv_get_info,
137 1.1 christos hwcdrv_enable_mt,
138 1.1 christos hwcdrv_get_descriptions,
139 1.1 christos hwcdrv_assign_regnos,
140 1.1 christos hwcdrv_create_counters,
141 1.1 christos hwcdrv_start,
142 1.1 christos hwcdrv_overflow,
143 1.1 christos hwcdrv_read_events,
144 1.1 christos hwcdrv_sighlr_restart,
145 1.1 christos hwcdrv_lwp_suspend,
146 1.1 christos hwcdrv_lwp_resume,
147 1.1 christos hwcdrv_free_counters,
148 1.1 christos hwcdrv_lwp_init,
149 1.1 christos hwcdrv_lwp_fini,
150 1.1 christos -1 // hwcdrv_init_status
151 1.1 christos };
152 1.1 christos
153 1.1 christos static hwcdrv_api_t *hwcdrv_driver = &hwcdrv_default;
154 1.1 christos
155 1.1 christos
156 1.1 christos /*---------------------------------------------------------------------------*/
157 1.1 christos /* misc */
158 1.1 christos
159 1.1 christos /* print a counter definition (for debugging) */
160 1.1 christos static void
161 1.1 christos ctrdefprint (int dbg_lvl, const char * hdr, Hwcentry*phwcdef)
162 1.1 christos {
163 1.1 christos TprintfT (dbg_lvl, "%s: name='%s', int_name='%s',"
164 1.1 christos " reg_num=%d, timecvt=%d, memop=%d, "
165 1.1.1.3 christos "interval=%d, tag=%u\n",
166 1.1 christos hdr, phwcdef->name, phwcdef->int_name, phwcdef->reg_num,
167 1.1 christos phwcdef->timecvt, phwcdef->memop, phwcdef->val,
168 1.1.1.3 christos phwcdef->sort_order);
169 1.1 christos }
170 1.1 christos
171 1.1 christos /*---------------------------------------------------------------------------*/
172 1.1 christos /* errmsg buffering */
173 1.1 christos
174 1.1 christos /* errmsg buffering is needed only because the most descriptive error
175 1.1 christos messages from CPC are delivered using a callback mechanism.
176 1.1 christos hwcfuncs_errmsg_get() should only be used during initialization, and
177 1.1 christos ideally, only to provide feedback to an end user when his counters can't
178 1.1 christos be bound to HW.
179 1.1 christos */
180 1.1 christos IS_GLOBAL char *
181 1.1 christos hwcfuncs_errmsg_get (char *buf, size_t bufsize, int enable)
182 1.1 christos {
183 1.1 christos hwcfuncs_errmsg_enabled = 0;
184 1.1 christos if (buf && bufsize)
185 1.1 christos {
186 1.1 christos if (hwcfuncs_errmsg_valid)
187 1.1 christos {
188 1.1 christos strncpy (buf, hwcfuncs_errmsg_buf, bufsize);
189 1.1 christos buf[bufsize - 1] = 0;
190 1.1 christos }
191 1.1 christos else
192 1.1 christos *buf = 0;
193 1.1 christos }
194 1.1 christos hwcfuncs_errmsg_buf[0] = 0;
195 1.1 christos hwcfuncs_errmsg_valid = 0;
196 1.1 christos hwcfuncs_errmsg_enabled = enable;
197 1.1 christos return buf;
198 1.1 christos }
199 1.1 christos
200 1.1 christos /* used by cpc to log an error */
201 1.1.1.3 christos static void
202 1.1 christos hwcfuncs_int_capture_errmsg (const char *fn, int subcode,
203 1.1 christos const char *fmt, va_list ap)
204 1.1 christos {
205 1.1 christos if (hwcfuncs_errmsg_enabled &&
206 1.1 christos !hwcfuncs_errmsg_valid)
207 1.1 christos {
208 1.1 christos vsnprintf (hwcfuncs_errmsg_buf, sizeof (hwcfuncs_errmsg_buf), fmt, ap);
209 1.1 christos TprintfT (DBG_LT0, "hwcfuncs: cpcN_capture_errmsg(): %s\n",
210 1.1 christos hwcfuncs_errmsg_buf);
211 1.1 christos hwcfuncs_errmsg_valid = 1;
212 1.1 christos }
213 1.1 christos return;
214 1.1 christos }
215 1.1 christos
216 1.1 christos /* Log an internal error to the CPC error buffer.
217 1.1 christos * Note: only call this during init functions.
218 1.1 christos * Note: when most cpc calls fail, they will call cpcN_capture_errmsg()
219 1.1 christos * directly, so only call logerr() when a non-cpc function fails.
220 1.1 christos */
221 1.1 christos IS_GLOBAL void
222 1.1 christos hwcfuncs_int_logerr (const char *format, ...)
223 1.1 christos {
224 1.1 christos va_list va;
225 1.1 christos va_start (va, format);
226 1.1 christos hwcfuncs_int_capture_errmsg ("logerr", 0, format, va);
227 1.1 christos va_end (va);
228 1.1 christos }
229 1.1 christos
230 1.1 christos /* utils to parse counter strings */
231 1.1 christos static void
232 1.1 christos clear_hwcdefs ()
233 1.1 christos {
234 1.1 christos for (unsigned idx = 0; idx < MAX_PICS; idx++)
235 1.1 christos {
236 1.1 christos static Hwcentry empty;
237 1.1 christos hwcdef[idx] = empty; // leaks strings and reg_list array
238 1.1 christos hwcdef[idx].reg_num = REGNO_ANY;
239 1.1 christos hwcdef[idx].val = -1;
240 1.1 christos hwcdef[idx].sort_order = -1;
241 1.1 christos }
242 1.1 christos }
243 1.1 christos
244 1.1 christos /* initialize hwcdef[] based on user's counter definitions */
245 1.1 christos static int
246 1.1 christos process_data_descriptor (const char *defstring)
247 1.1 christos {
248 1.1 christos /*
249 1.1 christos * <defstring> format should be of format
250 1.1 christos * :%s:%s:0x%x:%d:%lld:%d:%d:0x%x[,%s...repeat for each ctr]
251 1.1 christos * where the counter fields are:
252 1.1 christos * :<userName>:<internalCtr>:<register>:<timeoutVal>[:m<min_time>]:<tag>:<timecvt>:<memop>
253 1.1 christos * See Coll_Ctrl::build_data_desc().
254 1.1 christos */
255 1.1 christos int err = 0;
256 1.1 christos char *ds = NULL;
257 1.1 christos char *dsp = NULL;
258 1.1 christos unsigned idx;
259 1.1 christos
260 1.1 christos clear_hwcdefs ();
261 1.1 christos if (!defstring || !strlen (defstring))
262 1.1.1.2 christos return HWCFUNCS_ERROR_HWCARGS;
263 1.1 christos ds = strdup (defstring);
264 1.1 christos if (!ds)
265 1.1.1.2 christos return HWCFUNCS_ERROR_HWCINIT;
266 1.1 christos dsp = ds;
267 1.1 christos for (idx = 0; idx < MAX_PICS && *dsp; idx++)
268 1.1 christos {
269 1.1 christos char *name = NULL;
270 1.1 christos char *int_name = NULL;
271 1.1 christos regno_t reg = REGNO_ANY;
272 1.1 christos ABST_type memop = ABST_NONE;
273 1.1 christos int interval = 0;
274 1.1 christos int timecvt = 0;
275 1.1 christos unsigned sort_order = (unsigned) - 1;
276 1.1 christos
277 1.1.1.2 christos // Read use_perf_event_type, type, config
278 1.1.1.2 christos hwcdef[idx].use_perf_event_type = (int) strtol (dsp, &dsp, 0);
279 1.1.1.2 christos if (*dsp++ != ':')
280 1.1.1.2 christos {
281 1.1.1.2 christos err = HWCFUNCS_ERROR_HWCARGS;
282 1.1.1.2 christos break;
283 1.1.1.2 christos }
284 1.1.1.2 christos hwcdef[idx].type = (int) strtol (dsp, &dsp, 0);
285 1.1.1.2 christos if (*dsp++ != ':')
286 1.1.1.2 christos {
287 1.1.1.2 christos err = HWCFUNCS_ERROR_HWCARGS;
288 1.1.1.2 christos break;
289 1.1.1.2 christos }
290 1.1.1.2 christos hwcdef[idx].config = strtol (dsp, &dsp, 0);
291 1.1.1.2 christos if (*dsp++ != ':')
292 1.1.1.2 christos {
293 1.1.1.2 christos err = HWCFUNCS_ERROR_HWCARGS;
294 1.1.1.2 christos break;
295 1.1.1.2 christos }
296 1.1.1.3 christos hwcdef[idx].config1 = strtol (dsp, &dsp, 0);
297 1.1.1.3 christos if (*dsp++ != ':')
298 1.1.1.3 christos {
299 1.1.1.3 christos err = HWCFUNCS_ERROR_HWCARGS;
300 1.1.1.3 christos break;
301 1.1.1.3 christos }
302 1.1.1.2 christos
303 1.1 christos /* name */
304 1.1 christos name = dsp;
305 1.1 christos dsp = strchr (dsp, ':');
306 1.1 christos if (dsp == NULL)
307 1.1 christos {
308 1.1 christos err = HWCFUNCS_ERROR_HWCARGS;
309 1.1.1.2 christos break;
310 1.1 christos }
311 1.1 christos *dsp++ = (char) 0;
312 1.1 christos
313 1.1 christos /* int_name */
314 1.1 christos int_name = dsp;
315 1.1 christos dsp = strchr (dsp, ':');
316 1.1 christos if (dsp == NULL)
317 1.1 christos {
318 1.1 christos err = HWCFUNCS_ERROR_HWCARGS;
319 1.1.1.2 christos break;
320 1.1 christos }
321 1.1 christos *dsp++ = (char) 0;
322 1.1 christos
323 1.1 christos /* reg_num */
324 1.1 christos reg = (int) strtol (dsp, &dsp, 0);
325 1.1 christos if (*dsp++ != ':')
326 1.1 christos {
327 1.1 christos err = HWCFUNCS_ERROR_HWCARGS;
328 1.1.1.2 christos break;
329 1.1 christos }
330 1.1 christos if (reg < 0 && reg != -1)
331 1.1 christos {
332 1.1 christos err = HWCFUNCS_ERROR_HWCARGS;
333 1.1.1.2 christos break;
334 1.1 christos }
335 1.1 christos if (reg >= 0)
336 1.1 christos hwcdef[idx].reg_num = reg;
337 1.1 christos
338 1.1 christos /* val */
339 1.1 christos interval = (int) strtol (dsp, &dsp, 0);
340 1.1 christos if (*dsp++ != ':')
341 1.1 christos {
342 1.1 christos err = HWCFUNCS_ERROR_HWCARGS;
343 1.1.1.2 christos break;
344 1.1 christos }
345 1.1 christos if (interval < 0)
346 1.1 christos {
347 1.1 christos err = HWCFUNCS_ERROR_HWCARGS;
348 1.1.1.2 christos break;
349 1.1 christos }
350 1.1 christos hwcdef[idx].val = interval;
351 1.1 christos
352 1.1 christos /* min_time */
353 1.1 christos if (*dsp == 'm')
354 1.1 christos {
355 1.1 christos long long tmp_ll = 0;
356 1.1 christos dsp++;
357 1.1 christos tmp_ll = strtoll (dsp, &dsp, 0);
358 1.1 christos if (*dsp++ != ':')
359 1.1 christos {
360 1.1 christos err = HWCFUNCS_ERROR_HWCARGS;
361 1.1.1.2 christos break;
362 1.1 christos }
363 1.1 christos if (tmp_ll < 0)
364 1.1 christos {
365 1.1 christos err = HWCFUNCS_ERROR_HWCARGS;
366 1.1.1.2 christos break;
367 1.1 christos }
368 1.1 christos hwcdef[idx].min_time = tmp_ll;
369 1.1 christos }
370 1.1 christos else
371 1.1 christos hwcdef[idx].min_time = 0;
372 1.1 christos
373 1.1 christos /* sort_order */
374 1.1 christos sort_order = (int) strtoul (dsp, &dsp, 0);
375 1.1 christos if (*dsp++ != ':')
376 1.1 christos {
377 1.1 christos err = HWCFUNCS_ERROR_HWCARGS;
378 1.1.1.2 christos break;
379 1.1 christos }
380 1.1 christos hwcdef[idx].sort_order = sort_order;
381 1.1 christos
382 1.1 christos /* timecvt */
383 1.1 christos timecvt = (int) strtol (dsp, &dsp, 0);
384 1.1 christos if (*dsp++ != ':')
385 1.1 christos {
386 1.1 christos err = HWCFUNCS_ERROR_HWCARGS;
387 1.1.1.2 christos break;
388 1.1 christos }
389 1.1 christos hwcdef[idx].timecvt = timecvt;
390 1.1 christos
391 1.1 christos /* memop */
392 1.1 christos memop = (ABST_type) strtol (dsp, &dsp, 0);
393 1.1 christos if (*dsp != 0 && *dsp++ != ',')
394 1.1 christos {
395 1.1 christos err = HWCFUNCS_ERROR_HWCARGS;
396 1.1.1.2 christos break;
397 1.1 christos }
398 1.1 christos hwcdef[idx].memop = memop;
399 1.1 christos if (*name)
400 1.1 christos hwcdef[idx].name = strdup (name);
401 1.1 christos else
402 1.1 christos hwcdef[idx].name = strdup (int_name);
403 1.1 christos if (*int_name)
404 1.1 christos hwcdef[idx].int_name = strdup (int_name);
405 1.1 christos else
406 1.1 christos hwcdef[idx].int_name = strdup (name);
407 1.1 christos ctrdefprint (DBG_LT1, "hwcfuncs: process_data_descriptor", &hwcdef[idx]);
408 1.1 christos }
409 1.1 christos
410 1.1 christos if (*dsp)
411 1.1.1.2 christos err = HWCFUNCS_ERROR_HWCARGS;
412 1.1.1.2 christos if (err != 0)
413 1.1.1.2 christos logerr (GTXT ("Data descriptor syntax error near `%s'\n"), dsp);
414 1.1 christos else
415 1.1.1.2 christos hwcdef_cnt = idx;
416 1.1 christos free (ds);
417 1.1 christos return err;
418 1.1 christos }
419 1.1 christos
420 1.1 christos /* initialize hwcdef[] based on user's counter definitions */
421 1.1 christos static int
422 1.1 christos process_hwcentrylist (const Hwcentry* entries[], unsigned numctrs)
423 1.1 christos {
424 1.1 christos int err = 0;
425 1.1 christos clear_hwcdefs ();
426 1.1 christos if (numctrs > cpcN_npics)
427 1.1 christos {
428 1.1 christos logerr (GTXT ("More than %d counters were specified\n"), cpcN_npics); /*!*/
429 1.1 christos return HWCFUNCS_ERROR_HWCARGS;
430 1.1 christos }
431 1.1 christos for (unsigned idx = 0; idx < numctrs; idx++)
432 1.1 christos {
433 1.1 christos Hwcentry *phwcdef = &hwcdef[idx];
434 1.1 christos *phwcdef = *entries[idx];
435 1.1 christos if (phwcdef->name)
436 1.1 christos phwcdef->name = strdup (phwcdef->name);
437 1.1 christos else
438 1.1 christos phwcdef->name = "NULL";
439 1.1 christos if (phwcdef->int_name)
440 1.1 christos phwcdef->int_name = strdup (phwcdef->int_name);
441 1.1 christos else
442 1.1 christos phwcdef->int_name = "NULL";
443 1.1 christos if (phwcdef->val < 0)
444 1.1 christos {
445 1.1 christos logerr (GTXT ("Negative interval specified for HW counter `%s'\n"), /*!*/
446 1.1 christos phwcdef->name);
447 1.1 christos err = HWCFUNCS_ERROR_HWCARGS;
448 1.1 christos break;
449 1.1 christos }
450 1.1 christos ctrdefprint (DBG_LT1, "hwcfuncs: process_hwcentrylist", phwcdef);
451 1.1 christos }
452 1.1 christos if (!err)
453 1.1 christos hwcdef_cnt = numctrs;
454 1.1 christos return err;
455 1.1 christos }
456 1.1 christos
457 1.1 christos /* see hwcfuncs.h */
458 1.1 christos IS_GLOBAL void *
459 1.1 christos hwcfuncs_parse_attrs (const char *countername, hwcfuncs_attr_t attrs[],
460 1.1 christos unsigned max_attrs, uint_t *pnum_attrs, char**errstring)
461 1.1 christos {
462 1.1 christos char *head = NULL;
463 1.1 christos char *tail = NULL;
464 1.1 christos uint_t nattrs = 0;
465 1.1 christos char *counter_copy;
466 1.1 christos int success = 0;
467 1.1 christos char errbuf[512];
468 1.1 christos errbuf[0] = 0;
469 1.1 christos counter_copy = strdup (countername);
470 1.1 christos
471 1.1 christos /* advance pointer to first attribute */
472 1.1 christos tail = strchr (counter_copy, HWCFUNCS_PARSE_ATTR);
473 1.1 christos if (tail)
474 1.1 christos *tail = 0;
475 1.1 christos
476 1.1 christos /* remove regno and value, if supplied */
477 1.1 christos {
478 1.1 christos char *tmp = strchr (counter_copy, HWCFUNCS_PARSE_REGNUM);
479 1.1 christos if (tmp)
480 1.1 christos *tmp = 0;
481 1.1 christos tmp = strchr (counter_copy, HWCFUNCS_PARSE_VALUE);
482 1.1 christos if (tmp)
483 1.1 christos *tmp = 0;
484 1.1 christos }
485 1.1 christos
486 1.1 christos while (tail)
487 1.1 christos {
488 1.1 christos char *pch;
489 1.1 christos if (nattrs >= max_attrs)
490 1.1 christos {
491 1.1 christos snprintf (errbuf, sizeof (errbuf),
492 1.1 christos GTXT ("Too many attributes defined in `%s'"),
493 1.1 christos countername);
494 1.1 christos goto mycpc2_parse_attrs_end;
495 1.1 christos }
496 1.1 christos /* get attribute name */
497 1.1 christos head = tail + 1;
498 1.1 christos tail = strchr (head, HWCFUNCS_PARSE_EQUAL);
499 1.1 christos if (!tail)
500 1.1 christos {
501 1.1 christos snprintf (errbuf, sizeof (errbuf),
502 1.1 christos GTXT ("Missing value for attribute `%s' in `%s'"),
503 1.1 christos head, countername);
504 1.1 christos goto mycpc2_parse_attrs_end;
505 1.1 christos }
506 1.1 christos *tail = 0; /* null terminate current component */
507 1.1 christos attrs[nattrs].ca_name = head;
508 1.1 christos
509 1.1 christos /* get attribute value */
510 1.1 christos head = tail + 1;
511 1.1 christos tail = strchr (head, HWCFUNCS_PARSE_ATTR);
512 1.1 christos if (tail)
513 1.1 christos *tail = 0; /* null terminate current component */
514 1.1 christos attrs[nattrs].ca_val = strtoull (head, &pch, 0);
515 1.1 christos if (pch == head)
516 1.1 christos {
517 1.1 christos snprintf (errbuf, sizeof (errbuf),
518 1.1 christos GTXT ("Illegal value for attribute `%s' in `%s'"),
519 1.1 christos attrs[nattrs].ca_name, countername);
520 1.1 christos goto mycpc2_parse_attrs_end;
521 1.1 christos }
522 1.1 christos TprintfT (DBG_LT0, "hwcfuncs: pic_: '%s', attribute[%u]"
523 1.1 christos " '%s' = 0x%llx\n",
524 1.1 christos counter_copy, nattrs, attrs[nattrs].ca_name,
525 1.1 christos (long long unsigned int) attrs[nattrs].ca_val);
526 1.1 christos
527 1.1 christos nattrs++;
528 1.1 christos }
529 1.1 christos success = 1;
530 1.1 christos
531 1.1 christos mycpc2_parse_attrs_end:
532 1.1 christos *pnum_attrs = nattrs;
533 1.1 christos if (success)
534 1.1 christos {
535 1.1 christos if (errstring)
536 1.1 christos *errstring = NULL;
537 1.1 christos }
538 1.1 christos else
539 1.1 christos {
540 1.1 christos if (errstring)
541 1.1 christos *errstring = strdup (errbuf);
542 1.1 christos free (counter_copy);
543 1.1 christos counter_copy = NULL;
544 1.1 christos }
545 1.1 christos return counter_copy;
546 1.1 christos }
547 1.1 christos
548 1.1 christos IS_GLOBAL void
549 1.1 christos hwcfuncs_parse_ctr (const char *counter_def, int *pplus, char **pnameOnly,
550 1.1 christos char **pattrs, char **pregstr, regno_t *pregno)
551 1.1 christos {
552 1.1 christos char *nameptr, *copy, *slash, *attr_delim;
553 1.1 christos int plus;
554 1.1 christos regno_t regno;
555 1.1 christos nameptr = copy = strdup (counter_def);
556 1.1 christos
557 1.1 christos /* plus */
558 1.1 christos plus = 0;
559 1.1 christos if (nameptr[0] == HWCFUNCS_PARSE_BACKTRACK)
560 1.1 christos {
561 1.1 christos plus = 1;
562 1.1 christos nameptr++;
563 1.1 christos }
564 1.1 christos else if (nameptr[0] == HWCFUNCS_PARSE_BACKTRACK_OFF)
565 1.1 christos {
566 1.1 christos plus = -1;
567 1.1 christos nameptr++;
568 1.1 christos }
569 1.1 christos if (pplus)
570 1.1 christos *pplus = plus;
571 1.1 christos
572 1.1 christos /* regno */
573 1.1 christos regno = REGNO_ANY;
574 1.1 christos if (pregstr)
575 1.1 christos *pregstr = NULL;
576 1.1 christos slash = strchr (nameptr, HWCFUNCS_PARSE_REGNUM);
577 1.1 christos if (slash != NULL)
578 1.1 christos {
579 1.1 christos /* the remaining string should be a number > 0 */
580 1.1 christos if (pregstr)
581 1.1 christos *pregstr = strdup (slash);
582 1.1 christos char *endchar = NULL;
583 1.1 christos regno = (regno_t) strtol (slash + 1, &endchar, 0);
584 1.1 christos if (*endchar != 0)
585 1.1 christos regno = -2;
586 1.1 christos if (*(slash + 1) == '-')
587 1.1 christos regno = -2;
588 1.1 christos /* terminate previous element up to slash */
589 1.1 christos *slash = 0;
590 1.1 christos }
591 1.1 christos if (pregno)
592 1.1 christos *pregno = regno;
593 1.1 christos
594 1.1 christos /* attrs */
595 1.1 christos if (pattrs)
596 1.1 christos *pattrs = NULL;
597 1.1 christos attr_delim = strchr (nameptr, HWCFUNCS_PARSE_ATTR);
598 1.1 christos if (attr_delim != NULL)
599 1.1 christos {
600 1.1 christos if (pattrs)
601 1.1 christos *pattrs = strdup (attr_delim);
602 1.1 christos /* terminate previous element up to attr_delim */
603 1.1 christos *attr_delim++ = 0;
604 1.1 christos }
605 1.1 christos if (pnameOnly)
606 1.1 christos *pnameOnly = strdup (nameptr);
607 1.1 christos free (copy);
608 1.1 christos }
609 1.1 christos
610 1.1 christos /* create counters */
611 1.1 christos IS_GLOBAL int
612 1.1 christos hwcfuncs_bind_descriptor (const char *defstring)
613 1.1 christos {
614 1.1 christos int err = process_data_descriptor (defstring);
615 1.1 christos if (err)
616 1.1 christos {
617 1.1 christos TprintfT (DBG_LT0, "hwcfuncs: ERROR: hwcfuncs_bind_descriptor failed\n");
618 1.1 christos return err;
619 1.1 christos }
620 1.1 christos err = hwcdrv_driver->hwcdrv_create_counters (hwcdef_cnt, hwcdef);
621 1.1 christos return err;
622 1.1 christos }
623 1.1 christos
624 1.1 christos /* see hwcfuncs.h */
625 1.1 christos IS_GLOBAL int
626 1.1 christos hwcfuncs_bind_hwcentry (const Hwcentry* entries[], unsigned numctrs)
627 1.1 christos {
628 1.1 christos int err = -1;
629 1.1 christos err = process_hwcentrylist (entries, numctrs);
630 1.1 christos if (err)
631 1.1 christos {
632 1.1 christos TprintfT (DBG_LT0, "hwcfuncs: ERROR: hwcfuncs_bind_hwcentry\n");
633 1.1 christos return err;
634 1.1 christos }
635 1.1 christos err = hwcdrv_driver->hwcdrv_create_counters (hwcdef_cnt, hwcdef);
636 1.1 christos return err;
637 1.1 christos }
638 1.1 christos
639 1.1 christos /* see hwcfuncs.h */
640 1.1 christos IS_GLOBAL Hwcentry **
641 1.1 christos hwcfuncs_get_ctrs (unsigned *defcnt)
642 1.1 christos {
643 1.1 christos if (defcnt)
644 1.1 christos *defcnt = hwcdef_cnt;
645 1.1 christos return hwctable;
646 1.1 christos }
647 1.1 christos
648 1.1 christos extern hwcdrv_api_t hwcdrv_pcl_api;
649 1.1 christos static int hwcdrv_driver_inited = 0;
650 1.1 christos
651 1.1 christos hwcdrv_api_t *
652 1.1 christos get_hwcdrv ()
653 1.1 christos {
654 1.1 christos if (hwcdrv_driver_inited)
655 1.1 christos return hwcdrv_driver;
656 1.1 christos hwcdrv_driver_inited = 1;
657 1.1 christos cpcN_npics = 0;
658 1.1 christos for (int i = 0; i < MAX_PICS; i++)
659 1.1 christos hwctable[i] = &hwcdef[i];
660 1.1 christos hwcdrv_driver = &hwcdrv_pcl_api;
661 1.1 christos hwcdrv_driver->hwcdrv_init_status = hwcdrv_driver->hwcdrv_init (NULL, NULL);
662 1.1 christos if (hwcdrv_driver->hwcdrv_init_status == 0)
663 1.1 christos {
664 1.1 christos hwcdrv_driver->hwcdrv_get_info (NULL, NULL, &cpcN_npics, NULL, NULL);
665 1.1 christos return hwcdrv_driver;
666 1.1 christos }
667 1.1 christos hwcdrv_driver = &hwcdrv_default;
668 1.1 christos return hwcdrv_driver;
669 1.1 christos }
670