PAPI 7.1.0.0
Loading...
Searching...
No Matches
pfmlib_common.c
Go to the documentation of this file.
1/*
2 * pfmlib_common.c: set of functions common to all PMU models
3 *
4 * Copyright (c) 2001-2006 Hewlett-Packard Development Company, L.P.
5 * Contributed by Stephane Eranian <eranian@hpl.hp.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11 * of the Software, and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24#ifndef _GNU_SOURCE
25#define _GNU_SOURCE /* for getline */
26#endif
27#include <sys/types.h>
28#include <ctype.h>
29#include <string.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <stdarg.h>
33#include <limits.h>
34
35#include <perfmon/pfmlib.h>
36
37#include "pfmlib_priv.h"
38
40{
41
42#ifdef CONFIG_PFMLIB_ARCH_IA64
46 &generic_ia64_support, /* must always be last for IA-64 */
47#endif
48
49#ifdef CONFIG_PFMLIB_ARCH_X86_64
56 &gen_ia32_support, /* must always be last for x86-64 */
57#endif
58
59#ifdef CONFIG_PFMLIB_ARCH_I386
71 &gen_ia32_support, /* must always be last for i386 */
72#endif
73
74#ifdef CONFIG_PFMLIB_ARCH_MIPS64
76#endif
77
78#ifdef CONFIG_PFMLIB_ARCH_SICORTEX
80#endif
81
82#ifdef CONFIG_PFMLIB_ARCH_POWERPC
84#endif
85
86#ifdef CONFIG_PFMLIB_ARCH_SPARC
88#endif
89
90#ifdef CONFIG_PFMLIB_ARCH_CRAYX2
92#endif
93
94#ifdef CONFIG_PFMLIB_CELL
96#endif
97 NULL
98};
99
100/*
101 * contains runtime configuration options for the library.
102 * mostly for debug purposes.
103 */
105 .current = NULL
106};
107
109
110/*
111 * check environment variables for:
112 * LIBPFM_VERBOSE : enable verbose output (must be 1)
113 * LIBPFM_DEBUG : enable debug output (must be 1)
114 */
115static void
117{
118 char *str;
119
121
122 str = getenv("LIBPFM_VERBOSE");
123 if (str && *str >= '0' && *str <= '9') {
124 pfm_config.options.pfm_verbose = *str - '0';
126 }
127
128 str = getenv("LIBPFM_DEBUG");
129 if (str && *str >= '0' && *str <= '9') {
130 pfm_config.options.pfm_debug = *str - '0';
132 }
133
134 str = getenv("LIBPFM_DEBUG_STDOUT");
135 if (str)
137
138 str = getenv("LIBPFM_FORCE_PMU");
139 if (str)
140 forced_pmu = atoi(str);
141}
142
143int
145{
147 int ret;
148
150 /*
151 * syscall mapping, no failure on error
152 */
154
155 while(*p) {
156 DPRINT("trying %s\n", (*p)->pmu_name);
157 /*
158 * check for forced_pmu
159 * pmu_type can never be zero
160 */
161 if ((*p)->pmu_type == forced_pmu) {
162 __pfm_vbprintf("PMU forced to %s\n", (*p)->pmu_name);
163 goto found;
164 }
165
166 if (forced_pmu == PFMLIB_NO_PMU && (*p)->pmu_detect() == PFMLIB_SUCCESS)
167 goto found;
168 p++;
169 }
170 return PFMLIB_ERR_NOTSUPP;
171found:
172 DPRINT("found %s\n", (*p)->pmu_name);
173 /*
174 * run a few sanity checks
175 */
176 if ((*p)->pmc_count >= PFMLIB_MAX_PMCS)
177 return PFMLIB_ERR_NOTSUPP;
178
179 if ((*p)->pmd_count >= PFMLIB_MAX_PMDS)
180 return PFMLIB_ERR_NOTSUPP;
181
182 if ((*p)->pmu_init) {
183 ret = (*p)->pmu_init();
184 if (ret != PFMLIB_SUCCESS)
185 return ret;
186 }
187
188 pfm_current = *p;
189
190 return PFMLIB_SUCCESS;
191}
192
193int
195{
196 if (opt == NULL)
197 return PFMLIB_ERR_INVAL;
198 /*
199 * environment variables override program presets
200 */
202 pfm_config.options = *opt;
203
204 return PFMLIB_SUCCESS;
205}
206
207/*
208 * return the name corresponding to the pmu type. Only names
209 * of PMU actually compiled in the library will be returned.
210 */
211int
212pfm_get_pmu_name_bytype(int type, char *name, size_t maxlen)
213{
215
216 if (name == NULL || maxlen < 1) return PFMLIB_ERR_INVAL;
217
218 while (*p) {
219 if ((*p)->pmu_type == type) goto found;
220 p++;
221 }
222 return PFMLIB_ERR_INVAL;
223found:
224 strncpy(name, (*p)->pmu_name, maxlen-1);
225
226 /* make sure the string is null terminated */
227 name[maxlen-1] = '\0';
228
229 return PFMLIB_SUCCESS;
230}
231
232int
233pfm_list_supported_pmus(int (*pf)(const char *fmt,...))
234{
236
237 if (pf == NULL) return PFMLIB_ERR_INVAL;
238
239 (*pf)("supported PMU models: ");
240
241 for (p = supported_pmus; *p; p++) {
242 (*pf)("[%s] ", (*p)->pmu_name);;
243 }
244
245 (*pf)("\ndetected host PMU: %s\n", pfm_current ? pfm_current->pmu_name : "not detected yet");
246
247 return PFMLIB_SUCCESS;
248}
249
250int
251pfm_get_pmu_name(char *name, int maxlen)
252{
253 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
254
255 if (name == NULL || maxlen < 1) return PFMLIB_ERR_INVAL;
256
257 strncpy(name, pfm_current->pmu_name, maxlen-1);
258
259 name[maxlen-1] = '\0';
260
261 return PFMLIB_SUCCESS;
262}
263
264int
266{
267 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
268
269 if (type == NULL) return PFMLIB_ERR_INVAL;
270
271 *type = pfm_current->pmu_type;
272
273 return PFMLIB_SUCCESS;
274}
275
276/*
277 * boolean return value
278 */
279int
281{
283
284 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
285
286 while (*p) {
287 if ((*p)->pmu_type == type) return PFMLIB_SUCCESS;
288 p++;
289 }
290 return PFMLIB_ERR_NOTSUPP;
291}
292
293int
295{
297
298 while (*p) {
299 if ((*p)->pmu_type == type) goto found;
300 p++;
301 }
302 return PFMLIB_ERR_NOTSUPP;
303found:
304 pfm_current = *p;
305
306 return PFMLIB_SUCCESS;
307}
308
309int
310pfm_find_event_byname(const char *n, unsigned int *idx)
311{
312 char *p, *e;
313 unsigned int i;
314 size_t len;
315
316 if (PFMLIB_INITIALIZED() == 0)
317 return PFMLIB_ERR_NOINIT;
318
319 if (n == NULL || idx == NULL)
320 return PFMLIB_ERR_INVAL;
321
322 /*
323 * this function ignores any ':' separator
324 */
325 p = strchr(n, ':');
326 if (!p)
327 len = strlen(n);
328 else
329 len = p - n;
330
331 /*
332 * we do case insensitive comparisons
333 *
334 * event names must match completely
335 */
336 for(i=0; i < pfm_current->pme_count; i++) {
337 e = pfm_current->get_event_name(i);
338 if (!e)
339 continue;
340 if (!strncasecmp(e, n, len)
341 && len == strlen(e))
342 goto found;
343 }
344 return PFMLIB_ERR_NOTFOUND;
345found:
346 *idx = i;
347 return PFMLIB_SUCCESS;
348}
349
350int
351pfm_find_event_bycode(int code, unsigned int *idx)
352{
353 pfmlib_regmask_t impl_cnt;
354 unsigned int i, j, num_cnt;
355 int code2;
356
357 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
358
359 if (idx == NULL) return PFMLIB_ERR_INVAL;
360
361 if (pfm_current->flags & PFMLIB_MULT_CODE_EVENT) {
362 pfm_current->get_impl_counters(&impl_cnt);
363 num_cnt = pfm_current->num_cnt;
364
365 for(i=0; i < pfm_current->pme_count; i++) {
366 for(j=0; num_cnt; j++) {
367 if (pfm_regmask_isset(&impl_cnt, j)) {
368 pfm_current->get_event_code(i, j, &code2);
369 if (code2 == code)
370 goto found;
371 num_cnt--;
372 }
373 }
374 }
375 } else {
376 for(i=0; i < pfm_current->pme_count; i++) {
377 pfm_current->get_event_code(i, PFMLIB_CNT_FIRST, &code2);
378 if (code2 == code) goto found;
379 }
380 }
381 return PFMLIB_ERR_NOTFOUND;
382found:
383 *idx = i;
384 return PFMLIB_SUCCESS;
385}
386
387int
388pfm_find_event(const char *v, unsigned int *ev)
389{
390 unsigned long number;
391 char *endptr = NULL;
392 int ret = PFMLIB_ERR_INVAL;
393
394 if (PFMLIB_INITIALIZED() == 0)
395 return PFMLIB_ERR_NOINIT;
396
397 if (v == NULL || ev == NULL)
398 return PFMLIB_ERR_INVAL;
399
400 if (isdigit((int)*v)) {
401 number = strtoul(v,&endptr, 0);
402 /* check for errors */
403 if (*endptr!='\0')
404 return PFMLIB_ERR_INVAL;
405
406 if (number <= INT_MAX) {
407 int the_int_number = (int)number;
408 ret = pfm_find_event_bycode(the_int_number, ev);
409 }
410 } else
411 ret = pfm_find_event_byname(v, ev);
412 return ret;
413}
414
415int
416pfm_find_event_bycode_next(int code, unsigned int i, unsigned int *next)
417{
418 int code2;
419
420 if (PFMLIB_INITIALIZED() == 0)
421 return PFMLIB_ERR_NOINIT;
422
423 if (!next)
424 return PFMLIB_ERR_INVAL;
425
426 for(++i; i < pfm_current->pme_count; i++) {
427 pfm_current->get_event_code(i, PFMLIB_CNT_FIRST, &code2);
428 if (code2 == code) goto found;
429 }
430 return PFMLIB_ERR_NOTFOUND;
431found:
432 *next = i;
433 return PFMLIB_SUCCESS;
434}
435
436static int
437pfm_do_find_event_mask(unsigned int ev, const char *str, unsigned int *mask_idx)
438{
439 unsigned int i, c, num_masks = 0;
440 unsigned long mask_val = -1;
441 char *endptr = NULL;
442 char *mask_name;
443
444 /* empty mask name */
445 if (*str == '\0')
446 return PFMLIB_ERR_UMASK;
447
448 num_masks = pfm_num_masks(ev);
449 for (i = 0; i < num_masks; i++) {
450 mask_name = pfm_current->get_event_mask_name(ev, i);
451 if (!mask_name)
452 continue;
453 if (strcasecmp(mask_name, str))
454 continue;
455 *mask_idx = i;
456 return PFMLIB_SUCCESS;
457 }
458 /* don't give up yet; check for a exact numerical value */
459 mask_val = strtoul(str, &endptr, 0);
460 if (mask_val != ULONG_MAX && endptr && *endptr == '\0') {
461 for (i = 0; i < num_masks; i++) {
462 pfm_current->get_event_mask_code(ev, i, &c);
463 if (mask_val == c) {
464 *mask_idx = i;
465 return PFMLIB_SUCCESS;
466 }
467 }
468 }
469 return PFMLIB_ERR_UMASK;
470}
471
472int
473pfm_find_event_mask(unsigned int ev, const char *str, unsigned int *mask_idx)
474{
475 if (PFMLIB_INITIALIZED() == 0)
476 return PFMLIB_ERR_NOINIT;
477
478 if (str == NULL || mask_idx == NULL || ev >= pfm_current->pme_count)
479 return PFMLIB_ERR_INVAL;
480
481 return pfm_do_find_event_mask(ev, str, mask_idx);
482}
483
484/*
485 * check if unit mask is not already present
486 */
487static inline int
489{
490 unsigned int j;
491
492 for(j=0; j < e->num_masks; j++) {
493 if (e->unit_masks[j] == u)
494 return PFMLIB_ERR_UMASK;
495 }
496 return PFMLIB_SUCCESS;
497}
498
499static int
501{
502 unsigned int i, j, c;
503 unsigned int num_masks = 0;
504 unsigned long mask_val = -1, m = 0;
505 char *endptr = NULL;
506 int ret = PFMLIB_ERR_UMASK;
507
508 /* empty mask name */
509 if (*str == '\0')
510 return PFMLIB_ERR_UMASK;
511
512 num_masks = pfm_num_masks(e->event);
513
514 /*
515 * add to the existing list of unit masks
516 */
517 j = e->num_masks;
518
519 /*
520 * use unsigned long to benefit from radix wildcard
521 * and error checking of strtoul()
522 */
523 mask_val = strtoul(str, &endptr, 0);
524 if (endptr && *endptr != '\0')
525 return PFMLIB_ERR_UMASK;
526
527 /*
528 * look for a numerical match
529 */
530 for (i = 0; i < num_masks; i++) {
531 pfm_current->get_event_mask_code(e->event, i, &c);
532 if ((mask_val & c) == (unsigned long)c) {
533 /* ignore duplicates */
536 ret = PFMLIB_ERR_TOOMANY;
537 break;
538 }
539 e->unit_masks[j++] = i;
540 }
541 m |= c;
542 }
543 }
544
545 /*
546 * all bits accounted for
547 */
548 if (mask_val == m) {
549 e->num_masks = j;
550 return PFMLIB_SUCCESS;
551 }
552
553 /*
554 * extra bits left over;
555 * reset and flag error
556 */
557 for (i = e->num_masks; i < j; i++)
558 e->unit_masks[i] = 0;
559
560 return ret;
561}
562
563int
564pfm_get_event_name(unsigned int i, char *name, size_t maxlen)
565{
566 size_t l, j;
567 char *str;
568
569 if (PFMLIB_INITIALIZED() == 0)
570 return PFMLIB_ERR_NOINIT;
571
572 if (i >= pfm_current->pme_count || name == NULL || maxlen < 1)
573 return PFMLIB_ERR_INVAL;
574
575 str = pfm_current->get_event_name(i);
576 if (!str)
577 return PFMLIB_ERR_BADHOST;
578 l = strlen(str);
579
580 /*
581 * we fail if buffer is too small, simply because otherwise we
582 * get partial names which are useless for subsequent calls
583 * users mus invoke pfm_get_event_name_max_len() to correctly size
584 * the buffer for this call
585 */
586 if ((maxlen-1) < l)
587 return PFMLIB_ERR_INVAL;
588
589 for(j=0; j < l; j++)
590 name[j] = (char)toupper(str[j]);
591
592 name[l] = '\0';
593
594 return PFMLIB_SUCCESS;
595}
596
597int
598pfm_get_event_code(unsigned int i, int *code)
599{
600 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
601
602 if (i >= pfm_current->pme_count || code == NULL) return PFMLIB_ERR_INVAL;
603
604 return pfm_current->get_event_code(i, PFMLIB_CNT_FIRST, code);
605
606}
607
608int
609pfm_get_event_code_counter(unsigned int i, unsigned int cnt, int *code)
610{
611 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
612
613 if (i >= pfm_current->pme_count || code == NULL) return PFMLIB_ERR_INVAL;
614
615 return pfm_current->get_event_code(i, cnt, code);
616}
617
618int
620{
621 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
622
623 if (i >= pfm_current->pme_count) return PFMLIB_ERR_INVAL;
624
625 pfm_current->get_event_counters(i, counters);
626
627 return PFMLIB_SUCCESS;
628}
629
630int
631pfm_get_event_mask_name(unsigned int ev, unsigned int mask, char *name, size_t maxlen)
632{
633 char *str;
634 unsigned int num;
635 size_t l, j;
636
637 if (PFMLIB_INITIALIZED() == 0)
638 return PFMLIB_ERR_NOINIT;
639
640 if (ev >= pfm_current->pme_count || name == NULL || maxlen < 1)
641 return PFMLIB_ERR_INVAL;
642
643 num = pfm_num_masks(ev);
644 if (num == 0)
645 return PFMLIB_ERR_NOTSUPP;
646
647 if (mask >= num)
648 return PFMLIB_ERR_INVAL;
649
650 str = pfm_current->get_event_mask_name(ev, mask);
651 if (!str)
652 return PFMLIB_ERR_BADHOST;
653 l = strlen(str);
654 if (l >= (maxlen-1))
655 return PFMLIB_ERR_FULL;
656
657 strcpy(name, str);
658
659 /*
660 * present nice uniform names
661 */
662 l = strlen(name);
663 for(j=0; j < l; j++)
664 if (islower(name[j]))
665 name[j] = (char)toupper(name[j]);
666 return PFMLIB_SUCCESS;
667}
668
669int
671{
672 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
673
674 if (count == NULL) return PFMLIB_ERR_INVAL;
675
676 *count = pfm_current->pme_count;
677
678 return PFMLIB_SUCCESS;
679}
680
681int
682pfm_get_num_event_masks(unsigned int ev, unsigned int *count)
683{
684 if (PFMLIB_INITIALIZED() == 0)
685 return PFMLIB_ERR_NOINIT;
686
687 if (ev >= pfm_current->pme_count || count == NULL)
688 return PFMLIB_ERR_INVAL;
689
690 *count = pfm_num_masks(ev);
691
692 return PFMLIB_SUCCESS;
693}
694
695#if 0
696/*
697 * check that the unavailable PMCs registers correspond
698 * to implemented PMC registers
699 */
700static int
701pfm_check_unavail_pmcs(pfmlib_regmask_t *pmcs)
702{
703 pfmlib_regmask_t impl_pmcs;
704 pfm_current->get_impl_pmcs(&impl_pmcs);
705 unsigned int i;
706
707 for (i=0; i < PFMLIB_REG_BV; i++) {
708 if ((pmcs->bits[i] & impl_pmcs.bits[i]) != pmcs->bits[i])
709 return PFMLIB_ERR_INVAL;
710 }
711 return PFMLIB_SUCCESS;
712}
713#endif
714
715
716/*
717 * we do not check if pfp_unavail_pmcs contains only implemented PMC
718 * registers. In other words, invalid registers are ignored
719 */
720int
722 pfmlib_input_param_t *inp, void *model_in,
723 pfmlib_output_param_t *outp, void *model_out)
724{
725 unsigned count;
726 unsigned int i;
727 int ret;
728
729 if (PFMLIB_INITIALIZED() == 0)
730 return PFMLIB_ERR_NOINIT;
731
732 /* at least one input and one output set must exist */
733 if (!inp && !model_in)
734 return PFMLIB_ERR_INVAL;
735 if (!outp && !model_out)
736 return PFMLIB_ERR_INVAL;
737
738 if (!inp)
739 count = 0;
740 else if (inp->pfp_dfl_plm == 0)
741 /* the default priv level must be set to something */
742 return PFMLIB_ERR_INVAL;
743 else if (inp->pfp_event_count >= PFMLIB_MAX_PMCS)
744 return PFMLIB_ERR_INVAL;
745 else if (inp->pfp_event_count > pfm_current->num_cnt)
746 return PFMLIB_ERR_NOASSIGN;
747 else
748 count = inp->pfp_event_count;
749
750 /*
751 * check that event and unit masks descriptors are correct
752 */
753 for (i=0; i < count; i++) {
754 ret = __pfm_check_event(inp->pfp_events+i);
755 if (ret != PFMLIB_SUCCESS)
756 return ret;
757 }
758
759 /* reset output data structure */
760 if (outp)
761 memset(outp, 0, sizeof(*outp));
762
763 return pfm_current->dispatch_events(inp, model_in, outp, model_out);
764}
765
766/*
767 * more or less obosleted by pfm_get_impl_counters()
768 */
769int
770pfm_get_num_counters(unsigned int *num)
771{
772 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
773
774 if (num == NULL) return PFMLIB_ERR_INVAL;
775
776 *num = pfm_current->num_cnt;
777
778 return PFMLIB_SUCCESS;
779}
780
781int
782pfm_get_num_pmcs(unsigned int *num)
783{
784 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
785
786 if (num == NULL) return PFMLIB_ERR_INVAL;
787
788 *num = pfm_current->pmc_count;
789
790 return PFMLIB_SUCCESS;
791}
792
793int
794pfm_get_num_pmds(unsigned int *num)
795{
796 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
797
798 if (num == NULL) return PFMLIB_ERR_INVAL;
799
800 *num = pfm_current->pmd_count;
801
802 return PFMLIB_SUCCESS;
803}
804
805int
807{
808 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
809 if (impl_pmcs == NULL) return PFMLIB_ERR_INVAL;
810
811 memset(impl_pmcs , 0, sizeof(*impl_pmcs));
812
813 pfm_current->get_impl_pmcs(impl_pmcs);
814
815 return PFMLIB_SUCCESS;
816}
817
818int
820{
821 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
822 if (impl_pmds == NULL) return PFMLIB_ERR_INVAL;
823
824 memset(impl_pmds, 0, sizeof(*impl_pmds));
825
826 pfm_current->get_impl_pmds(impl_pmds);
827
828 return PFMLIB_SUCCESS;
829}
830
831int
833{
834 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
835 if (impl_counters == NULL) return PFMLIB_ERR_INVAL;
836
837 memset(impl_counters, 0, sizeof(*impl_counters));
838
839 pfm_current->get_impl_counters(impl_counters);
840
841 return PFMLIB_SUCCESS;
842}
843
844int
845pfm_get_hw_counter_width(unsigned int *width)
846{
847 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
848 if (width == NULL) return PFMLIB_ERR_INVAL;
849
850 pfm_current->get_hw_counter_width(width);
851
852 return PFMLIB_SUCCESS;
853}
854
855
856/* sorry, only English supported at this point! */
857static char *pfmlib_err_list[]=
858{
859 "success",
860 "not supported",
861 "invalid parameters",
862 "pfmlib not initialized",
863 "event not found",
864 "cannot assign events to counters",
865 "buffer is full or too small",
866 "event used more than once",
867 "invalid model specific magic number",
868 "invalid combination of model specific features",
869 "incompatible event sets",
870 "incompatible events combination",
871 "too many events or unit masks",
872 "code range too big",
873 "empty code range",
874 "invalid code range",
875 "too many code ranges",
876 "invalid data range",
877 "too many data ranges",
878 "not supported by host cpu",
879 "code range is not bundle-aligned",
880 "code range requires some flags in rr_flags",
881 "invalid or missing unit mask",
882 "out of memory"
883};
884static size_t pfmlib_err_count = sizeof(pfmlib_err_list)/sizeof(char *);
885
886char *
888{
889 code = -code;
890 if (code <0 || code >= pfmlib_err_count) return "unknown error code";
891 return pfmlib_err_list[code];
892}
893
894int
896{
897 if (version == NULL) return PFMLIB_ERR_INVAL;
899 return 0;
900}
901
902int
904{
905 unsigned int i, j, num_masks;
906 size_t max = 0, l;
907 char *str;
908
909 if (PFMLIB_INITIALIZED() == 0)
910 return PFMLIB_ERR_NOINIT;
911 if (len == NULL)
912 return PFMLIB_ERR_INVAL;
913
914 for(i=0; i < pfm_current->pme_count; i++) {
915 str = pfm_current->get_event_name(i);
916 if (!str)
917 continue;
918 l = strlen(str);
919 if (l > max) max = l;
920
921 num_masks = pfm_num_masks(i);
922 /*
923 * we need to add up all length because unit masks can
924 * be combined typically. We add 1 to account for ':'
925 * which is inserted as the unit mask separator
926 */
927 for (j = 0; j < num_masks; j++) {
928 str = pfm_current->get_event_mask_name(i, j);
929 if (!str)
930 continue;
931 l += 1 + strlen(str);
932 }
933 if (l > max) max = l;
934 }
935 *len = max;
936 return PFMLIB_SUCCESS;
937}
938
939/*
940 * return the index of the event that counts elapsed cycles
941 */
942int
944{
945 if (PFMLIB_INITIALIZED() == 0)
946 return PFMLIB_ERR_NOINIT;
947 if (e == NULL)
948 return PFMLIB_ERR_INVAL;
949
950 if (!pfm_current->get_cycle_event)
951 return PFMLIB_ERR_NOTSUPP;
952
953 memset(e, 0, sizeof(*e));
954
955 return pfm_current->get_cycle_event(e);
956}
957
958/*
959 * return the index of the event that retired instructions
960 */
961int
963{
964 if (PFMLIB_INITIALIZED() == 0)
965 return PFMLIB_ERR_NOINIT;
966 if (e == NULL)
967 return PFMLIB_ERR_INVAL;
968
969 if (!pfm_current->get_inst_retired_event)
970 return PFMLIB_ERR_NOTSUPP;
971
972 memset(e, 0, sizeof(*e));
973
974 return pfm_current->get_inst_retired_event(e);
975}
976
977int
978pfm_get_event_description(unsigned int i, char **str)
979{
980 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
981
982 if (i >= pfm_current->pme_count || str == NULL) return PFMLIB_ERR_INVAL;
983
984 if (pfm_current->get_event_desc == NULL) {
985 *str = strdup("no description available");
986 return PFMLIB_SUCCESS;
987 }
988 return pfm_current->get_event_desc(i, str);
989}
990
991int
992pfm_get_event_mask_description(unsigned int event_idx, unsigned int mask_idx, char **desc)
993{
994 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
995
996 if (event_idx >= pfm_current->pme_count || desc == NULL) return PFMLIB_ERR_INVAL;
997
998 if (pfm_current->get_event_mask_desc == NULL) {
999 *desc = strdup("no description available");
1000 return PFMLIB_SUCCESS;
1001 }
1002 if (mask_idx >= pfm_current->get_num_event_masks(event_idx))
1003 return PFMLIB_ERR_INVAL;
1004
1005 return pfm_current->get_event_mask_desc(event_idx, mask_idx, desc);
1006}
1007
1008int
1009pfm_get_event_mask_code(unsigned int event_idx, unsigned int mask_idx, unsigned int *code)
1010{
1011 if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
1012
1013 if (event_idx >= pfm_current->pme_count || code == NULL) return PFMLIB_ERR_INVAL;
1014
1015 if (pfm_current->get_event_mask_code == NULL) {
1016 *code = 0;
1017 return PFMLIB_SUCCESS;
1018 }
1019 if (mask_idx >= pfm_current->get_num_event_masks(event_idx))
1020 return PFMLIB_ERR_INVAL;
1021
1022 return pfm_current->get_event_mask_code(event_idx, mask_idx, code);
1023}
1024
1025int
1027{
1028 char *str;
1029 size_t l, j;
1030 int ret;
1031
1032 if (PFMLIB_INITIALIZED() == 0)
1033 return PFMLIB_ERR_NOINIT;
1034
1035 if (e == NULL || name == NULL || maxlen < 1)
1036 return PFMLIB_ERR_INVAL;
1037
1038 ret = __pfm_check_event(e);
1039 if (ret != PFMLIB_SUCCESS)
1040 return ret;
1041
1042 /*
1043 * make sure the string is at least empty
1044 * important for programs that do not check return value
1045 * from this function!
1046 */
1047 *name = '\0';
1048
1049 str = pfm_current->get_event_name(e->event);
1050 if (!str)
1051 return PFMLIB_ERR_BADHOST;
1052 l = strlen(str);
1053 if (l > (maxlen-1))
1054 return PFMLIB_ERR_FULL;
1055
1056 strcpy(name, str);
1057 maxlen -= l + 1;
1058 for(j=0; j < e->num_masks; j++) {
1059 str = pfm_current->get_event_mask_name(e->event, e->unit_masks[j]);
1060 if (!str)
1061 continue;
1062 l = strlen(str);
1063 if (l > (maxlen-1))
1064 return PFMLIB_ERR_FULL;
1065
1066 strcat(name, ":");
1067 strcat(name, str);
1068 maxlen -= l + 1;
1069 }
1070 /*
1071 * present nice uniform names
1072 */
1073 l = strlen(name);
1074 for(j=0; j < l; j++)
1075 if (islower(name[j]))
1076 name[j] = (char)toupper(name[j]);
1077 return PFMLIB_SUCCESS;
1078}
1079
1080int
1082{
1083 char *str, *p, *q;
1084 unsigned int j, mask;
1085 int ret = PFMLIB_SUCCESS;
1086
1087 if (PFMLIB_INITIALIZED() == 0)
1088 return PFMLIB_ERR_NOINIT;
1089
1090 if (v == NULL || e == NULL)
1091 return PFMLIB_ERR_INVAL;
1092
1093 memset(e, 0, sizeof(*e));
1094
1095 /*
1096 * must copy string because we modify it when parsing
1097 */
1098 str = strdup(v);
1099 if (!str)
1100 return PFMLIB_ERR_NOMEM;
1101
1102 /*
1103 * find event. this function ignores ':' separator
1104 */
1105 ret = pfm_find_event_byname(str, &e->event);
1106 if (ret)
1107 goto error;
1108
1109 /*
1110 * get number of unit masks for event
1111 */
1112 j = pfm_num_masks(e->event);
1113
1114 /*
1115 * look for colon (unit mask separator)
1116 */
1117 p = strchr(str, ':');
1118
1119 /* If no unit masks available and none specified, we're done */
1120
1121 if ((j == 0) && (p == NULL)) {
1122 free(str);
1123 return PFMLIB_SUCCESS;
1124 }
1125
1126 ret = PFMLIB_ERR_UMASK;
1127 /*
1128 * error if:
1129 * - event has no unit mask and at least one is passed
1130 */
1131 if (p && !j)
1132 goto error;
1133
1134 /*
1135 * error if:
1136 * - event has unit masks, no default unit mask, and none is passed
1137 */
1138 if (j && !p) {
1139 if (pfm_current->has_umask_default
1140 && pfm_current->has_umask_default(e->event)) {
1141 free(str);
1142 return PFMLIB_SUCCESS;
1143 }
1144 goto error;
1145 }
1146
1147 /* skip : */
1148 p++;
1149 /*
1150 * separator is passed but there is nothing behind it
1151 */
1152 if (!*p)
1153 goto error;
1154
1155 /* parse unit masks */
1156 for( q = p; q ; p = q) {
1157
1158 q = strchr(p,':');
1159 if (q)
1160 *q++ = '\0';
1161
1162 /*
1163 * text or exact unit mask value match
1164 */
1165 ret = pfm_do_find_event_mask(e->event, p, &mask);
1166 if (ret == PFMLIB_ERR_UMASK) {
1167 ret = pfm_add_numeric_masks(e, p);
1168 if (ret != PFMLIB_SUCCESS)
1169 break;
1170 } else if (ret == PFMLIB_SUCCESS) {
1171 /*
1172 * ignore duplicates
1173 */
1174 ret = pfm_check_duplicates(e, mask);
1175 if (ret != PFMLIB_SUCCESS) {
1176 ret = PFMLIB_SUCCESS;
1177 continue;
1178 }
1179
1181 ret = PFMLIB_ERR_TOOMANY;
1182 break;
1183 }
1184 e->unit_masks[e->num_masks] = mask;
1185 e->num_masks++;
1186 }
1187 }
1188error:
1189 free(str);
1190 return ret;
1191}
int i
static long count
static double c[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:40
uint8_t version
uint16_t type
FILE * stdout
FILE * stderr
#define PFMLIB_VERSION
Definition: pfmlib.h:34
#define PFMLIB_MAX_PMCS
Definition: pfmlib.h:41
#define PFMLIB_ERR_BADHOST
Definition: pfmlib.h:303
#define PFMLIB_ERR_UMASK
Definition: pfmlib.h:306
#define PFMLIB_SUCCESS
Definition: pfmlib.h:283
#define PFMLIB_MAX_MASKS_PER_EVENT
Definition: pfmlib.h:80
#define PFMLIB_MAX_PMDS
Definition: pfmlib.h:42
#define PFMLIB_NO_PMU
Definition: pfmlib.h:221
#define PFMLIB_ERR_NOMEM
Definition: pfmlib.h:307
#define PFMLIB_ERR_NOTFOUND
Definition: pfmlib.h:287
#define PFMLIB_ERR_INVAL
Definition: pfmlib.h:285
#define PFMLIB_ERR_TOOMANY
Definition: pfmlib.h:295
#define PFMLIB_ERR_NOINIT
Definition: pfmlib.h:286
static int pfm_regmask_isset(pfmlib_regmask_t *h, unsigned int b)
Definition: pfmlib.h:313
#define PFMLIB_ERR_NOASSIGN
Definition: pfmlib.h:288
#define PFMLIB_ERR_NOTSUPP
Definition: pfmlib.h:284
#define PFMLIB_ERR_FULL
Definition: pfmlib.h:289
#define PFMLIB_REG_BV
Definition: pfmlib.h:72
pfm_pmu_support_t amd64_support
Definition: pfmlib_amd64.c:98
pfm_pmu_support_t cell_support
Definition: pfmlib_cell.c:675
int pfm_get_version(unsigned int *version)
int pfm_get_event_mask_description(unsigned int event_idx, unsigned int mask_idx, char **desc)
int pfm_list_supported_pmus(int(*pf)(const char *fmt,...))
char * pfm_strerror(int code)
int pfm_get_event_code_counter(unsigned int i, unsigned int cnt, int *code)
int pfm_initialize(void)
int pfm_get_num_pmcs(unsigned int *num)
int pfm_find_event_bycode(int code, unsigned int *idx)
int pfm_get_event_counters(unsigned int i, pfmlib_regmask_t *counters)
int pfm_find_full_event(const char *v, pfmlib_event_t *e)
int pfm_get_pmu_name_bytype(int type, char *name, size_t maxlen)
int pfm_get_inst_retired_event(pfmlib_event_t *e)
static char * pfmlib_err_list[]
int pfm_dispatch_events(pfmlib_input_param_t *inp, void *model_in, pfmlib_output_param_t *outp, void *model_out)
int pfm_find_event_mask(unsigned int ev, const char *str, unsigned int *mask_idx)
int pfm_get_event_description(unsigned int i, char **str)
int pfm_get_num_event_masks(unsigned int ev, unsigned int *count)
int pfm_get_max_event_name_len(size_t *len)
int pfm_find_event(const char *v, unsigned int *ev)
static int pfm_add_numeric_masks(pfmlib_event_t *e, const char *str)
static void pfm_check_debug_env(void)
int pfm_get_num_counters(unsigned int *num)
int pfm_get_event_mask_name(unsigned int ev, unsigned int mask, char *name, size_t maxlen)
int pfm_find_event_byname(const char *n, unsigned int *idx)
static int pfm_check_duplicates(pfmlib_event_t *e, unsigned int u)
int pfm_find_event_bycode_next(int code, unsigned int i, unsigned int *next)
pfm_config_t pfm_config
int pfm_is_pmu_supported(int type)
int pfm_get_impl_counters(pfmlib_regmask_t *impl_counters)
int pfm_get_num_events(unsigned int *count)
int pfm_get_impl_pmds(pfmlib_regmask_t *impl_pmds)
int pfm_get_event_code(unsigned int i, int *code)
int pfm_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs)
int pfm_get_hw_counter_width(unsigned int *width)
int pfm_get_cycle_event(pfmlib_event_t *e)
static pfm_pmu_support_t * supported_pmus[]
Definition: pfmlib_common.c:39
int pfm_set_options(pfmlib_options_t *opt)
int pfm_get_num_pmds(unsigned int *num)
int forced_pmu
int pfm_get_event_name(unsigned int i, char *name, size_t maxlen)
int pfm_get_pmu_name(char *name, int maxlen)
static int pfm_do_find_event_mask(unsigned int ev, const char *str, unsigned int *mask_idx)
int pfm_force_pmu(int type)
static size_t pfmlib_err_count
int pfm_get_pmu_type(int *type)
int pfm_get_full_event_name(pfmlib_event_t *e, char *name, size_t maxlen)
int pfm_get_event_mask_code(unsigned int event_idx, unsigned int mask_idx, unsigned int *code)
pfm_pmu_support_t core_support
Definition: pfmlib_core.c:903
pfm_pmu_support_t coreduo_support
pfm_pmu_support_t crayx2_support
pfm_pmu_support_t gen_ia32_support
pfm_pmu_support_t generic_ia64_support
pfm_pmu_support_t generic_mips64_support
pfm_pmu_support_t gen_powerpc_support
pfm_pmu_support_t i386_pii_support
pfm_pmu_support_t i386_pm_support
pfm_pmu_support_t i386_ppro_support
pfm_pmu_support_t i386_p6_support
pfm_pmu_support_t intel_atom_support
pfm_pmu_support_t intel_nhm_support
pfm_pmu_support_t intel_wsm_support
pfm_pmu_support_t itanium2_support
pfm_pmu_support_t itanium_support
pfm_pmu_support_t montecito_support
void pfm_init_syscalls(void)
pfm_pmu_support_t pentium4_support
void __pfm_vbprintf(const char *fmt,...)
Definition: pfmlib_priv.c:52
int __pfm_check_event(pfmlib_event_t *e)
Definition: pfmlib_priv.c:65
FILE * libpfm_fp
Definition: pfmlib_priv.c:42
#define PFMLIB_INITIALIZED()
Definition: pfmlib_priv.h:72
pfm_pmu_support_t sparc_support
Definition: pfmlib_sparc.c:519
#define pfm_current
Definition: pfmlib_priv.h:78
static unsigned int pfm_num_masks(int e)
Definition: pfmlib_priv.h:125
#define DPRINT(fmt, a...)
Definition: pfmlib_priv.h:90
pfm_pmu_support_t sicortex_support
#define PFMLIB_MULT_CODE_EVENT
Definition: pfmlib_priv.h:60
#define PFMLIB_CNT_FIRST
Definition: pfmlib_priv.h:62
const char * fmt
Definition: pscanf.h:10
const char * name
Definition: rocs.c:225
int
Definition: sde_internal.h:89
int options_env_set
Definition: pfmlib_priv.h:69
pfm_pmu_support_t * current
Definition: pfmlib_priv.h:68
pfmlib_options_t options
Definition: pfmlib_priv.h:67
unsigned int num_masks
Definition: pfmlib.h:90
unsigned int unit_masks[PFMLIB_MAX_MASKS_PER_EVENT]
Definition: pfmlib.h:89
unsigned int event
Definition: pfmlib.h:86
unsigned int pfp_dfl_plm
Definition: pfmlib.h:110
pfmlib_event_t pfp_events[PFMLIB_MAX_PMCS]
Definition: pfmlib.h:113
unsigned int pfp_event_count
Definition: pfmlib.h:109
unsigned int pfm_verbose
Definition: pfmlib.h:139
unsigned int pfm_debug
Definition: pfmlib.h:138
pfmlib_regmask_bits_t bits[PFMLIB_REG_BV]
Definition: pfmlib.h:76