PAPI 7.1.0.0
Loading...
Searching...
No Matches
libpfms.c
Go to the documentation of this file.
1#include <sys/types.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <unistd.h>
5#include <string.h>
6#include <pthread.h>
7#include <semaphore.h>
8#include <inttypes.h>
9#include <syscall.h>
10#include <errno.h>
11#include <stdarg.h>
12
13#include <perfmon/perfmon.h>
14
15#include "libpfms.h"
16
17//#define dprint(format, arg...) fprintf(stderr, "%s.%d: " format , __FUNCTION__ , __LINE__, ## arg)
18#define dprint(format, arg...)
19
20typedef enum { CMD_NONE,
31
32typedef struct _barrier {
35 uint32_t counter;
36 uint32_t max;
37 uint64_t generation; /* avoid race condition on wake-up */
38} barrier_t;
39
40typedef struct {
41 uint32_t cpu;
42 uint32_t fd;
46
47typedef struct _pfms_thread {
48 uint32_t cpu;
50 void *data;
51 uint32_t ndata;
52 sem_t cmd_sem;
53 int ret;
57
58typedef struct {
60 uint32_t ncpus;
62
63static uint32_t ncpus;
65static pthread_mutex_t tds_lock = PTHREAD_MUTEX_INITIALIZER;
66
67static int
69{
70 int r;
71
72 r = pthread_mutex_init(&b->mutex, NULL);
73 if (r == -1) return -1;
74
75 r = pthread_cond_init(&b->cond, NULL);
76 if (r == -1) return -1;
77
78 b->max = b->counter = count;
79 b->generation = 0;
80
81 return 0;
82}
83
84static void
86{
87 barrier_t *b = (barrier_t *)arg;
88 int r;
89 r = pthread_mutex_unlock(&b->mutex);
90 dprint("free barrier mutex r=%d\n", r);
91 (void) r;
92}
93
94static int
96{
97 uint64_t generation;
98 int oldstate;
99
100 pthread_cleanup_push(cleanup_barrier, b);
101
102 pthread_mutex_lock(&b->mutex);
103
104 pthread_testcancel();
105
106 if (--b->counter == 0) {
107
108 /* reset barrier */
109 b->counter = b->max;
110 /*
111 * bump generation number, this avoids thread getting stuck in the
112 * wake up loop below in case a thread just out of the barrier goes
113 * back in right away before all the thread from the previous "round"
114 * have "escaped".
115 */
116 b->generation++;
117
118 pthread_cond_broadcast(&b->cond);
119 } else {
120
121 generation = b->generation;
122
123 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
124
125 while (b->counter != b->max && generation == b->generation) {
126 pthread_cond_wait(&b->cond, &b->mutex);
127 }
128
129 pthread_setcancelstate(oldstate, NULL);
130 }
131 pthread_mutex_unlock(&b->mutex);
132
133 pthread_cleanup_pop(0);
134
135 return 0;
136}
137
138/*
139 * placeholder for pthread_setaffinity_np(). This stuff is ugly
140 * and I could not figure out a way to get it compiled while also preserving
141 * the pthread_*cancel(). There are issues with LinuxThreads and NPTL. I
142 * decided to quit on this and implement my own affinity call until this
143 * settles.
144 */
145static int
146pin_cpu(uint32_t cpu)
147{
148 uint64_t *mask;
149 size_t size;
150 pid_t pid;
151 int ret;
152
153 pid = syscall(__NR_gettid);
154
155 size = ncpus * sizeof(uint64_t);
156
157 mask = calloc(1, size);
158 if (mask == NULL) {
159 dprint("CPU%u: cannot allocate bitvector\n", cpu);
160 return -1;
161 }
162 mask[cpu>>6] = 1ULL << (cpu & 63);
163
164 ret = syscall(__NR_sched_setaffinity, pid, size, mask);
165
166 free(mask);
167
168 return ret;
169}
170
171static void
173{
174 long k = (long )arg;
175 uint32_t mycpu = (uint32_t)k;
176 pfarg_ctx_t myctx, *ctx;
177 pfarg_load_t load_args;
178 int fd = -1;
179 pfms_thread_t *td;
180 sem_t *cmd_sem;
181 int ret = 0;
182
183 memset(&load_args, 0, sizeof(load_args));
184 load_args.load_pid = mycpu;
185 td = tds+mycpu;
186
187 ret = pin_cpu(mycpu);
188 dprint("CPU%u wthread created and pinned ret=%d\n", mycpu, ret);
189
190 cmd_sem = &tds[mycpu].cmd_sem;
191
192 for(;;) {
193 dprint("CPU%u waiting for cmd\n", mycpu);
194
195 sem_wait(cmd_sem);
196
197 switch(td->cmd) {
198 case CMD_NONE:
199 ret = 0;
200 break;
201
202 case CMD_CTX:
203
204 /*
205 * copy context to get private fd
206 */
207 ctx = td->data;
208 myctx = *ctx;
209
210 fd = pfm_create_context(&myctx, NULL, NULL, 0);
211 ret = fd < 0 ? -1 : 0;
212 dprint("CPU%u CMD_CTX ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
213 break;
214
215 case CMD_LOAD:
216 ret = pfm_load_context(fd, &load_args);
217 dprint("CPU%u CMD_LOAD ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
218 break;
219 case CMD_UNLOAD:
220 ret = pfm_unload_context(fd);
221 dprint("CPU%u CMD_UNLOAD ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
222 break;
223 case CMD_START:
224 ret = pfm_start(fd, NULL);
225 dprint("CPU%u CMD_START ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
226 break;
227 case CMD_STOP:
228 ret = pfm_stop(fd);
229 dprint("CPU%u CMD_STOP ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
230 break;
231 case CMD_WPMCS:
232 ret = pfm_write_pmcs(fd,(pfarg_pmc_t *)td->data, td->ndata);
233 dprint("CPU%u CMD_WPMCS ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
234 break;
235 case CMD_WPMDS:
236 ret = pfm_write_pmds(fd,(pfarg_pmd_t *)td->data, td->ndata);
237 dprint("CPU%u CMD_WPMDS ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
238 break;
239 case CMD_RPMDS:
240 ret = pfm_read_pmds(fd,(pfarg_pmd_t *)td->data, td->ndata);
241 dprint("CPU%u CMD_RPMDS ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
242 break;
243 case CMD_CLOSE:
244 dprint("CPU%u CMD_CLOSE fd=%d\n", mycpu, fd);
245 ret = close(fd);
246 fd = -1;
247 break;
248 default:
249 break;
250 }
251 td->ret = ret;
252
253 dprint("CPU%u td->ret=%d\n", mycpu, ret);
254
256 }
257}
258
259static int
261{
262 int ret;
263
264 sem_init(&tds[cpu].cmd_sem, 0, 0);
265
266 ret = pthread_create(&tds[cpu].tid,
267 NULL,
268 (void *(*)(void *))pfms_thread_mainloop,
269 (void *)(long)cpu);
270 return ret;
271}
272
273/*
274 * must be called with tds_lock held
275 */
276static int
277create_wthreads(uint64_t *cpu_list, uint32_t n)
278{
279 uint64_t v;
280 uint32_t i,k, cpu;
281 int ret = 0;
282
283 for(k=0, cpu = 0; k < n; k++, cpu+= 64) {
284 v = cpu_list[k];
285 for(i=0; v && i < 63; i++, v>>=1, cpu++) {
286 if ((v & 0x1) && tds[cpu].tid == 0) {
287 ret = create_one_wthread(cpu);
288 if (ret) break;
289 }
290 }
291 }
292
293 if (ret)
294 dprint("cannot create wthread on CPU%u\n", cpu);
295
296 return ret;
297}
298
299int
301{
302 printf("cpu_t=%zu thread=%zu session_t=%zu\n",
303 sizeof(pfms_cpu_t),
304 sizeof(pfms_thread_t),
305 sizeof(pfms_session_t));
306
307 ncpus = (uint32_t)sysconf(_SC_NPROCESSORS_ONLN);
308 if (ncpus == -1) {
309 dprint("cannot retrieve number of online processors\n");
310 return -1;
311 }
312
313 dprint("configured for %u CPUs\n", ncpus);
314
315 /*
316 * XXX: assuming CPU are contiguously indexed
317 */
318 tds = calloc(ncpus, sizeof(*tds));
319 if (tds == NULL) {
320 dprint("cannot allocate thread descriptors\n");
321 return -1;
322 }
323 return 0;
324}
325
326int
327pfms_create(uint64_t *cpu_list, size_t n, pfarg_ctx_t *ctx, pfms_ovfl_t *ovfl, void **desc)
328{
329 uint64_t v;
330 size_t k, i;
331 uint32_t num, cpu;
333 int ret;
334
335 if (cpu_list == NULL || n == 0 || ctx == NULL || desc == NULL) {
336 dprint("invalid parameters\n");
337 return -1;
338 }
339
340 if ((ctx->ctx_flags & PFM_FL_SYSTEM_WIDE) == 0) {
341 dprint("only works for system wide\n");
342 return -1;
343 }
344
345 *desc = NULL;
346
347 /*
348 * XXX: assuming CPU are contiguously indexed
349 */
350 num = 0;
351 for(k=0, cpu = 0; k < n; k++, cpu+=64) {
352 v = cpu_list[k];
353 for(i=0; v && i < 63; i++, v>>=1, cpu++) {
354 if (v & 0x1) {
355 if (cpu >= ncpus) {
356 dprint("unavailable CPU%u\n", cpu);
357 return -1;
358 }
359 num++;
360 }
361 }
362 }
363
364 if (num == 0)
365 return 0;
366
367 s = calloc(1, sizeof(*s));
368 if (s == NULL) {
369 dprint("cannot allocate %u contexts\n", num);
370 return -1;
371 }
372 s->ncpus = num;
373
374 printf("%u-way session\n", num);
375
376 /*
377 * +1 to account for main thread waiting
378 */
379 ret = barrier_init(&s->barrier, num + 1);
380 if (ret) {
381 dprint("cannot init barrier\n");
382 goto error_free;
383 }
384
385 /*
386 * lock thread descriptor table, no other create_session, close_session
387 * can occur
388 */
389 pthread_mutex_lock(&tds_lock);
390
391 if (create_wthreads(cpu_list, n))
392 goto error_free_unlock;
393
394 /*
395 * check all needed threads are available
396 */
397 for(k=0, cpu = 0; k < n; k++, cpu += 64) {
398 v = cpu_list[k];
399 for(i=0; v && i < 63; i++, v>>=1, cpu++) {
400 if (v & 0x1) {
401 if (tds[cpu].barrier) {
402 dprint("CPU%u already managing a session\n", cpu);
403 goto error_free_unlock;
404 }
405
406 }
407 }
408 }
409
410 /*
411 * send create context order
412 */
413 for(k=0, cpu = 0; k < n; k++, cpu += 64) {
414 v = cpu_list[k];
415 for(i=0; v && i < 63; i++, v>>=1, cpu++) {
416 if (v & 0x1) {
417 tds[cpu].cmd = CMD_CTX;
418 tds[cpu].data = ctx;
419 tds[cpu].barrier = &s->barrier;
420 sem_post(&tds[cpu].cmd_sem);
421 }
422 }
423 }
424 barrier_wait(&s->barrier);
425
426 ret = 0;
427
428 /*
429 * check for errors
430 */
431 for(k=0; k < ncpus; k++) {
432 if (tds[k].barrier == &s->barrier) {
433 ret = tds[k].ret;
434 if (ret)
435 break;
436 }
437 }
438 /*
439 * undo if error found
440 */
441 if (k < ncpus) {
442 for(k=0; k < ncpus; k++) {
443 if (tds[k].barrier == &s->barrier) {
444 if (tds[k].ret == 0) {
445 tds[k].cmd = CMD_CLOSE;
446 sem_post(&tds[k].cmd_sem);
447 }
448 /* mark as free */
449 tds[k].barrier = NULL;
450 }
451 }
452 }
453 pthread_mutex_unlock(&tds_lock);
454
455 if (ret == 0) *desc = s;
456
457 return ret ? -1 : 0;
458
459error_free_unlock:
460 pthread_mutex_unlock(&tds_lock);
461
462error_free:
463 free(s);
464 return -1;
465}
466
467int
468pfms_load(void *desc)
469{
470 uint32_t k;
472 int ret;
473
474 if (desc == NULL) {
475 dprint("invalid parameters\n");
476 return -1;
477 }
478 s = (pfms_session_t *)desc;
479
480 if (s->ncpus == 0) {
481 dprint("invalid session content 0 CPUS\n");
482 return -1;
483 }
484 /*
485 * send create context order
486 */
487 for(k=0; k < ncpus; k++) {
488 if (tds[k].barrier == &s->barrier) {
489 tds[k].cmd = CMD_LOAD;
490 sem_post(&tds[k].cmd_sem);
491 }
492 }
493
494 barrier_wait(&s->barrier);
495
496 ret = 0;
497
498 /*
499 * check for errors
500 */
501 for(k=0; k < ncpus; k++) {
502 if (tds[k].barrier == &s->barrier) {
503 ret = tds[k].ret;
504 if (ret) {
505 dprint("failure on CPU%u\n", k);
506 break;
507 }
508 }
509 }
510
511 /*
512 * if error, unload all others
513 */
514 if (k < ncpus) {
515 for(k=0; k < ncpus; k++) {
516 if (tds[k].barrier == &s->barrier) {
517 if (tds[k].ret == 0) {
518 tds[k].cmd = CMD_UNLOAD;
519 sem_post(&tds[k].cmd_sem);
520 }
521 }
522 }
523 }
524 return ret ? -1 : 0;
525}
526
527static int
528__pfms_do_simple_cmd(pfms_cmd_t cmd, void *desc, void *data, uint32_t n)
529{
530 size_t k;
532 int ret;
533
534 if (desc == NULL) {
535 dprint("invalid parameters\n");
536 return -1;
537 }
538 s = (pfms_session_t *)desc;
539
540 if (s->ncpus == 0) {
541 dprint("invalid session content 0 CPUS\n");
542 return -1;
543 }
544 /*
545 * send create context order
546 */
547 for(k=0; k < ncpus; k++) {
548 if (tds[k].barrier == &s->barrier) {
549 tds[k].cmd = cmd;
550 tds[k].data = data;
551 tds[k].ndata = n;
552 sem_post(&tds[k].cmd_sem);
553 }
554 }
555 barrier_wait(&s->barrier);
556
557 ret = 0;
558
559 /*
560 * check for errors
561 */
562 for(k=0; k < ncpus; k++) {
563 if (tds[k].barrier == &s->barrier) {
564 ret = tds[k].ret;
565 if (ret) {
566 dprint("failure on CPU%zu\n", k);
567 break;
568 }
569 }
570 }
571 /*
572 * simple commands cannot be undone
573 */
574 return ret ? -1 : 0;
575}
576
577int
578pfms_unload(void *desc)
579{
580 return __pfms_do_simple_cmd(CMD_UNLOAD, desc, NULL, 0);
581}
582
583int
584pfms_start(void *desc)
585{
586 return __pfms_do_simple_cmd(CMD_START, desc, NULL, 0);
587}
588
589int
590pfms_stop(void *desc)
591{
592 return __pfms_do_simple_cmd(CMD_STOP, desc, NULL, 0);
593}
594
595int
596pfms_write_pmcs(void *desc, pfarg_pmc_t *pmcs, uint32_t n)
597{
598 return __pfms_do_simple_cmd(CMD_WPMCS, desc, pmcs, n);
599}
600
601int
602pfms_write_pmds(void *desc, pfarg_pmd_t *pmds, uint32_t n)
603{
604 return __pfms_do_simple_cmd(CMD_WPMDS, desc, pmds, n);
605}
606
607int
608pfms_close(void *desc)
609{
610 size_t k;
612 int ret;
613
614 if (desc == NULL) {
615 dprint("invalid parameters\n");
616 return -1;
617 }
618 s = (pfms_session_t *)desc;
619
620 if (s->ncpus == 0) {
621 dprint("invalid session content 0 CPUS\n");
622 return -1;
623 }
624
625 for(k=0; k < ncpus; k++) {
626 if (tds[k].barrier == &s->barrier) {
627 tds[k].cmd = CMD_CLOSE;
628 sem_post(&tds[k].cmd_sem);
629 }
630 }
631 barrier_wait(&s->barrier);
632
633 ret = 0;
634
635 pthread_mutex_lock(&tds_lock);
636 /*
637 * check for errors
638 */
639 for(k=0; k < ncpus; k++) {
640 if (tds[k].barrier == &s->barrier) {
641 if (tds[k].ret) {
642 dprint("failure on CPU%zu\n", k);
643 }
644 ret |= tds[k].ret;
645 tds[k].barrier = NULL;
646 }
647 }
648
649 pthread_mutex_unlock(&tds_lock);
650
651 free(s);
652
653 /*
654 * XXX: we cannot undo close
655 */
656 return ret ? -1 : 0;
657}
658
659int
660pfms_read_pmds(void *desc, pfarg_pmd_t *pmds, uint32_t n)
661{
663 uint32_t k, pmds_per_cpu;
664 int ret;
665
666 if (desc == NULL) {
667 dprint("invalid parameters\n");
668 return -1;
669 }
670 s = (pfms_session_t *)desc;
671
672 if (s->ncpus == 0) {
673 dprint("invalid session content 0 CPUS\n");
674 return -1;
675 }
676 if (n % s->ncpus) {
677 dprint("invalid number of pfarg_pmd_t provided, must be multiple of %u\n", s->ncpus);
678 return -1;
679 }
680 pmds_per_cpu = n / s->ncpus;
681
682 dprint("n=%u ncpus=%u per_cpu=%u\n", n, s->ncpus, pmds_per_cpu);
683
684 for(k=0; k < ncpus; k++) {
685 if (tds[k].barrier == &s->barrier) {
686 tds[k].cmd = CMD_RPMDS;
687 tds[k].data = pmds;
688 tds[k].ndata= pmds_per_cpu;
689 sem_post(&tds[k].cmd_sem);
690 pmds += pmds_per_cpu;
691 }
692 }
693 barrier_wait(&s->barrier);
694
695 ret = 0;
696
697 /*
698 * check for errors
699 */
700 for(k=0; k < ncpus; k++) {
701 if (tds[k].barrier == &s->barrier) {
702 ret = tds[k].ret;
703 if (ret) {
704 dprint("failure on CPU%u\n", k);
705 break;
706 }
707 }
708 }
709 /*
710 * cannot undo pfm_read_pmds
711 */
712 return ret ? -1 : 0;
713}
714#if 0
715
716/*
717 * beginning of test program
718 */
719#include <perfmon/pfmlib.h>
720
721#define NUM_PMCS PFMLIB_MAX_PMCS
722#define NUM_PMDS PFMLIB_MAX_PMDS
723
724static void fatal_error(char *fmt,...) __attribute__((noreturn));
725
726static void
727fatal_error(char *fmt, ...)
728{
729 va_list ap;
730
731 va_start(ap, fmt);
732 vfprintf(stderr, fmt, ap);
733 va_end(ap);
734
735 exit(1);
736}
737
738static uint32_t
739popcount(uint64_t c)
740{
741 uint32_t count = 0;
742
743 for(; c; c>>=1) {
744 if (c & 0x1)
745 count++;
746 }
747 return count;
748}
749
750int
751main(int argc, char **argv)
752{
753 pfarg_ctx_t ctx;
755 pfarg_pmd_t *pd;
758 uint64_t cpu_list;
759 void *desc;
760 unsigned int num_counters;
761 uint32_t i, j, k, l, ncpus, npmds;
762 size_t len;
763 int ret;
764 char *name;
765
767 fatal_error("cannot initialize libpfm\n");
768
769 if (pfms_initialize())
770 fatal_error("cannot initialize libpfms\n");
771
772 pfm_get_num_counters(&num_counters);
774
775 name = malloc(len+1);
776 if (name == NULL)
777 fatal_error("cannot allocate memory for event name\n");
778
779 memset(&ctx, 0, sizeof(ctx));
780 memset(pc, 0, sizeof(pc));
781 memset(&inp,0, sizeof(inp));
782 memset(&outp,0, sizeof(outp));
783
784 cpu_list = argc > 1 ? strtoul(argv[1], NULL, 0) : 0x3;
785
786 ncpus = popcount(cpu_list);
787
789 fatal_error("cannot find cycle event\n");
790
792 fatal_error("cannot find inst retired event\n");
793
794 i = 2;
795
797
798 if (i > num_counters) {
799 i = num_counters;
800 printf("too many events provided (max=%d events), using first %d event(s)\n", num_counters, i);
801 }
802 /*
803 * how many counters we use
804 */
805 inp.pfp_event_count = i;
806
807 /*
808 * indicate we are using the monitors for a system-wide session.
809 * This may impact the way the library sets up the PMC values.
810 */
812
813 /*
814 * let the library figure out the values for the PMCS
815 */
816 if ((ret=pfm_dispatch_events(&inp, NULL, &outp, NULL)) != PFMLIB_SUCCESS)
817 fatal_error("cannot configure events: %s\n", pfm_strerror(ret));
818
819 npmds = ncpus * inp.pfp_event_count;
820 dprint("ncpus=%u npmds=%u\n", ncpus, npmds);
821
822 pd = calloc(npmds, sizeof(pfarg_pmd_t));
823 if (pd == NULL)
824 fatal_error("cannot allocate pd array\n");
825
826 for (i=0; i < outp.pfp_pmc_count; i++) {
827 pc[i].reg_num = outp.pfp_pmcs[i].reg_num;
828 pc[i].reg_value = outp.pfp_pmcs[i].reg_value;
829 }
830
831 for(l=0, k = 0; l < ncpus; l++) {
832 for (i=0, j=0; i < inp.pfp_event_count; i++, k++) {
833 pd[k].reg_num = outp.pfp_pmcs[j].reg_pmd_num;
834 for(; j < outp.pfp_pmc_count; j++) if (outp.pfp_pmcs[j].reg_evt_idx != i) break;
835 }
836 }
837
838 /*
839 * create a context on all CPUs we asked for
840 *
841 * libpfms only works for system-wide, so we set the flag in
842 * the master context. the context argument is not modified by
843 * call.
844 *
845 * desc is an opaque descriptor used to identify session.
846 */
848
849 ret = pfms_create(&cpu_list, 1, &ctx, NULL, &desc);
850 if (ret == -1)
851 fatal_error("create error %d\n", ret);
852
853 /*
854 * program the PMC registers on all CPUs of interest
855 */
856 ret = pfms_write_pmcs(desc, pc, outp.pfp_pmc_count);
857 if (ret == -1)
858 fatal_error("write_pmcs error %d\n", ret);
859
860 /*
861 * program the PMD registers on all CPUs of interest
862 */
863 ret = pfms_write_pmds(desc, pd, inp.pfp_event_count);
864 if (ret == -1)
865 fatal_error("write_pmds error %d\n", ret);
866
867 /*
868 * load context on all CPUs of interest
869 */
870 ret = pfms_load(desc);
871 if (ret == -1)
872 fatal_error("load error %d\n", ret);
873
874 /*
875 * start monitoring on all CPUs of interest
876 */
877 ret = pfms_start(desc);
878 if (ret == -1)
879 fatal_error("start error %d\n", ret);
880
881 /*
882 * simulate some work
883 */
884 sleep(10);
885
886 /*
887 * stop monitoring on all CPUs of interest
888 */
889 ret = pfms_stop(desc);
890 if (ret == -1)
891 fatal_error("stop error %d\n", ret);
892
893 /*
894 * read the PMD registers on all CPUs of interest.
895 * The pd[] array must be organized such that to
896 * read 2 PMDs on each CPU you need:
897 * - 2 * number of CPUs of interest
898 * - the first 2 elements of pd[] read on 1st CPU
899 * - the next 2 elements of pd[] read on the 2nd CPU
900 * - and so on
901 */
902 ret = pfms_read_pmds(desc, pd, npmds);
903 if (ret == -1)
904 fatal_error("read_pmds error %d\n", ret);
905
906 /*
907 * pre per-CPU results
908 */
909 for(j=0, k= 0; j < ncpus; j++) {
910 for (i=0; i < inp.pfp_event_count; i++, k++) {
912 printf("CPU%-3d PMD%u %20"PRIu64" %s\n",
913 j,
914 pd[k].reg_num,
915 pd[k].reg_value,
916 name);
917 }
918 }
919
920 /*
921 * destroy context on all CPUs of interest.
922 * After this call desc is invalid
923 */
924 ret = pfms_close(desc);
925 if (ret == -1)
926 fatal_error("close error %d\n", ret);
927
928 free(name);
929
930 return 0;
931}
932#endif
int i
int close(int fd)
Definition: appio.c:179
int errno
double s
Definition: byte_profile.c:36
static long count
static double b[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:39
static double c[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:40
#define PFM_FL_SYSTEM_WIDE
int pfms_write_pmcs(void *desc, pfarg_pmc_t *pmcs, uint32_t n)
Definition: libpfms.c:596
static pfms_thread_t * tds
Definition: libpfms.c:64
static int pin_cpu(uint32_t cpu)
Definition: libpfms.c:146
static void cleanup_barrier(void *arg)
Definition: libpfms.c:85
int pfms_unload(void *desc)
Definition: libpfms.c:578
int pfms_write_pmds(void *desc, pfarg_pmd_t *pmds, uint32_t n)
Definition: libpfms.c:602
static int create_wthreads(uint64_t *cpu_list, uint32_t n)
Definition: libpfms.c:277
int pfms_create(uint64_t *cpu_list, size_t n, pfarg_ctx_t *ctx, pfms_ovfl_t *ovfl, void **desc)
Definition: libpfms.c:327
static uint32_t ncpus
Definition: libpfms.c:63
static int barrier_init(barrier_t *b, uint32_t count)
Definition: libpfms.c:68
int pfms_stop(void *desc)
Definition: libpfms.c:590
int pfms_load(void *desc)
Definition: libpfms.c:468
pfms_cmd_t
Definition: libpfms.c:20
@ CMD_RPMDS
Definition: libpfms.c:26
@ CMD_STOP
Definition: libpfms.c:27
@ CMD_CTX
Definition: libpfms.c:21
@ CMD_WPMDS
Definition: libpfms.c:25
@ CMD_UNLOAD
Definition: libpfms.c:23
@ CMD_CLOSE
Definition: libpfms.c:29
@ CMD_LOAD
Definition: libpfms.c:22
@ CMD_NONE
Definition: libpfms.c:20
@ CMD_WPMCS
Definition: libpfms.c:24
@ CMD_START
Definition: libpfms.c:28
int pfms_close(void *desc)
Definition: libpfms.c:608
static int create_one_wthread(int cpu)
Definition: libpfms.c:260
int pfms_initialize(void)
Definition: libpfms.c:300
int pfms_read_pmds(void *desc, pfarg_pmd_t *pmds, uint32_t n)
Definition: libpfms.c:660
static int barrier_wait(barrier_t *b)
Definition: libpfms.c:95
#define dprint(format, arg...)
Definition: libpfms.c:18
static int __pfms_do_simple_cmd(pfms_cmd_t cmd, void *desc, void *data, uint32_t n)
Definition: libpfms.c:528
int pfms_start(void *desc)
Definition: libpfms.c:584
static pthread_mutex_t tds_lock
Definition: libpfms.c:65
static void pfms_thread_mainloop(void *arg)
Definition: libpfms.c:172
int(* pfms_ovfl_t)(pfarg_msg_t *msg)
Definition: libpfms.h:31
unsigned long AO_t __attribute__((__aligned__(4)))
Definition: m68k.h:21
unsigned long int pthread_t
__gnuc_va_list va_list
FILE * stderr
#define NUM_PMCS
Definition: perfmon-ia64.h:66
os_err_t pfm_stop(int fd)
os_err_t pfm_write_pmds(int fd, pfarg_pmd_t *pmds, int count)
os_err_t pfm_unload_context(int fd)
os_err_t pfm_write_pmcs(int fd, pfarg_pmc_t *pmcs, int count)
os_err_t pfm_start(int fd, pfarg_start_t *start)
os_err_t pfm_create_context(pfarg_ctx_t *ctx, char *smpl_name, void *smpl_arg, size_t smpl_size)
os_err_t pfm_load_context(int fd, pfarg_load_t *load)
os_err_t pfm_read_pmds(int fd, pfarg_pmd_t *pmds, int count)
int main()
Definition: pernode.c:20
pfm_err_t pfm_get_inst_retired_event(pfmlib_event_t *e)
char * pfm_strerror(int code)
pfm_err_t pfm_dispatch_events(pfmlib_input_param_t *p, void *model_in, pfmlib_output_param_t *q, void *model_out)
#define PFMLIB_SUCCESS
Definition: pfmlib.h:283
#define PFM_PLM3
Definition: pfmlib.h:53
pfm_err_t pfm_get_full_event_name(pfmlib_event_t *e, char *name, size_t maxlen)
pfm_err_t pfm_get_cycle_event(pfmlib_event_t *e)
#define PFM_PLM0
Definition: pfmlib.h:50
pfm_err_t pfm_initialize(void)
pfm_err_t pfm_get_max_event_name_len(size_t *len)
#define PFMLIB_PFP_SYSTEMWIDE
Definition: pfmlib.h:121
pfm_err_t pfm_get_num_counters(unsigned int *num)
const char * fmt
Definition: pscanf.h:10
va_end(arg_list)
va_start(arg_list, fmt)
const char * name
Definition: rocs.c:225
long long int long long
Definition: sde_internal.h:85
static int pid
uint64_t generation
Definition: libpfms.c:37
pthread_cond_t cond
Definition: libpfms.c:34
uint32_t counter
Definition: libpfms.c:35
uint32_t max
Definition: libpfms.c:36
pthread_mutex_t mutex
Definition: libpfms.c:33
uint32_t ctx_flags
Definition: perfmon_v2.h:19
uint32_t load_pid
Definition: perfmon_v2.h:69
uint16_t reg_num
Definition: perfmon_v2.h:28
uint64_t reg_value
Definition: perfmon_v2.h:31
uint16_t reg_num
Definition: perfmon_v2.h:39
unsigned int event
Definition: pfmlib.h:86
unsigned int pfp_dfl_plm
Definition: pfmlib.h:110
unsigned int pfp_flags
Definition: pfmlib.h:111
pfmlib_event_t pfp_events[PFMLIB_MAX_PMCS]
Definition: pfmlib.h:113
unsigned int pfp_event_count
Definition: pfmlib.h:109
pfmlib_reg_t pfp_pmcs[PFMLIB_MAX_PMCS]
Definition: pfmlib.h:129
unsigned int pfp_pmc_count
Definition: pfmlib.h:127
unsigned long long reg_value
Definition: pfmlib.h:98
unsigned int reg_num
Definition: pfmlib.h:100
size_t smpl_buf_size
Definition: libpfms.c:44
void * smpl_vaddr
Definition: libpfms.c:43
uint32_t cpu
Definition: libpfms.c:41
uint32_t fd
Definition: libpfms.c:42
uint32_t ncpus
Definition: libpfms.c:60
barrier_t barrier
Definition: libpfms.c:59
uint32_t ndata
Definition: libpfms.c:51
barrier_t * barrier
Definition: libpfms.c:55
pfms_cmd_t cmd
Definition: libpfms.c:49
sem_t cmd_sem
Definition: libpfms.c:52
uint32_t cpu
Definition: libpfms.c:48
void * data
Definition: libpfms.c:50
pthread_t tid
Definition: libpfms.c:54
static void fatal_error(char *fmt,...) __attribute__((noreturn))
Definition: syst_smp.c:47
static uint32_t popcount(uint64_t c)
Definition: syst_smp.c:59