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