|
Packit |
577717 |
#include <sys/types.h>
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
#include <unistd.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <pthread.h>
|
|
Packit |
577717 |
#include <semaphore.h>
|
|
Packit |
577717 |
#include <inttypes.h>
|
|
Packit |
577717 |
#include <syscall.h>
|
|
Packit |
577717 |
#include <errno.h>
|
|
Packit |
577717 |
#include <stdarg.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include <perfmon/perfmon.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include "libpfms.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
//#define dprint(format, arg...) fprintf(stderr, "%s.%d: " format , __FUNCTION__ , __LINE__, ## arg)
|
|
Packit |
577717 |
#define dprint(format, arg...)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
typedef enum { CMD_NONE,
|
|
Packit |
577717 |
CMD_CTX,
|
|
Packit |
577717 |
CMD_LOAD,
|
|
Packit |
577717 |
CMD_UNLOAD,
|
|
Packit |
577717 |
CMD_WPMCS,
|
|
Packit |
577717 |
CMD_WPMDS,
|
|
Packit |
577717 |
CMD_RPMDS,
|
|
Packit |
577717 |
CMD_STOP,
|
|
Packit |
577717 |
CMD_START,
|
|
Packit |
577717 |
CMD_CLOSE
|
|
Packit |
577717 |
} pfms_cmd_t;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
typedef struct _barrier {
|
|
Packit |
577717 |
pthread_mutex_t mutex;
|
|
Packit |
577717 |
pthread_cond_t cond;
|
|
Packit |
577717 |
uint32_t counter;
|
|
Packit |
577717 |
uint32_t max;
|
|
Packit |
577717 |
uint64_t generation; /* avoid race condition on wake-up */
|
|
Packit |
577717 |
} barrier_t;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
typedef struct {
|
|
Packit |
577717 |
uint32_t cpu;
|
|
Packit |
577717 |
uint32_t fd;
|
|
Packit |
577717 |
void *smpl_vaddr;
|
|
Packit |
577717 |
size_t smpl_buf_size;
|
|
Packit |
577717 |
} pfms_cpu_t;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
typedef struct _pfms_thread {
|
|
Packit |
577717 |
uint32_t cpu;
|
|
Packit |
577717 |
pfms_cmd_t cmd;
|
|
Packit |
577717 |
void *data;
|
|
Packit |
577717 |
uint32_t ndata;
|
|
Packit |
577717 |
sem_t cmd_sem;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
pthread_t tid;
|
|
Packit |
577717 |
barrier_t *barrier;
|
|
Packit |
577717 |
} pfms_thread_t;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
typedef struct {
|
|
Packit |
577717 |
barrier_t barrier;
|
|
Packit |
577717 |
uint32_t ncpus;
|
|
Packit |
577717 |
} pfms_session_t;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static uint32_t ncpus;
|
|
Packit |
577717 |
static pfms_thread_t *tds;
|
|
Packit |
577717 |
static pthread_mutex_t tds_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
barrier_init(barrier_t *b, uint32_t count)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int r;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
r = pthread_mutex_init(&b->mutex, NULL);
|
|
Packit |
577717 |
if (r == -1) return -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
r = pthread_cond_init(&b->cond, NULL);
|
|
Packit |
577717 |
if (r == -1) return -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
b->max = b->counter = count;
|
|
Packit |
577717 |
b->generation = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
cleanup_barrier(void *arg)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
barrier_t *b = (barrier_t *)arg;
|
|
Packit |
577717 |
int r;
|
|
Packit |
577717 |
r = pthread_mutex_unlock(&b->mutex);
|
|
Packit |
577717 |
dprint("free barrier mutex r=%d\n", r);
|
|
Packit |
577717 |
(void) r;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
barrier_wait(barrier_t *b)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
uint64_t generation;
|
|
Packit |
577717 |
int oldstate;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pthread_cleanup_push(cleanup_barrier, b);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pthread_mutex_lock(&b->mutex);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pthread_testcancel();
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (--b->counter == 0) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* reset barrier */
|
|
Packit |
577717 |
b->counter = b->max;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* bump generation number, this avoids thread getting stuck in the
|
|
Packit |
577717 |
* wake up loop below in case a thread just out of the barrier goes
|
|
Packit |
577717 |
* back in right away before all the thread from the previous "round"
|
|
Packit |
577717 |
* have "escaped".
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
b->generation++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pthread_cond_broadcast(&b->cond);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
generation = b->generation;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while (b->counter != b->max && generation == b->generation) {
|
|
Packit |
577717 |
pthread_cond_wait(&b->cond, &b->mutex);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pthread_setcancelstate(oldstate, NULL);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
pthread_mutex_unlock(&b->mutex);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pthread_cleanup_pop(0);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* placeholder for pthread_setaffinity_np(). This stuff is ugly
|
|
Packit |
577717 |
* and I could not figure out a way to get it compiled while also preserving
|
|
Packit |
577717 |
* the pthread_*cancel(). There are issues with LinuxThreads and NPTL. I
|
|
Packit |
577717 |
* decided to quit on this and implement my own affinity call until this
|
|
Packit |
577717 |
* settles.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pin_cpu(uint32_t cpu)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
uint64_t *mask;
|
|
Packit |
577717 |
size_t size;
|
|
Packit |
577717 |
pid_t pid;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pid = syscall(__NR_gettid);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
size = ncpus * sizeof(uint64_t);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
mask = calloc(1, size);
|
|
Packit |
577717 |
if (mask == NULL) {
|
|
Packit |
577717 |
dprint("CPU%u: cannot allocate bitvector\n", cpu);
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
mask[cpu>>6] = 1ULL << (cpu & 63);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = syscall(__NR_sched_setaffinity, pid, size, mask);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
free(mask);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfms_thread_mainloop(void *arg)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
long k = (long )arg;
|
|
Packit |
577717 |
uint32_t mycpu = (uint32_t)k;
|
|
Packit |
577717 |
pfarg_ctx_t myctx, *ctx;
|
|
Packit |
577717 |
pfarg_load_t load_args;
|
|
Packit |
577717 |
int fd = -1;
|
|
Packit |
577717 |
pfms_thread_t *td;
|
|
Packit |
577717 |
sem_t *cmd_sem;
|
|
Packit |
577717 |
int ret = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&load_args, 0, sizeof(load_args));
|
|
Packit |
577717 |
load_args.load_pid = mycpu;
|
|
Packit |
577717 |
td = tds+mycpu;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pin_cpu(mycpu);
|
|
Packit |
577717 |
dprint("CPU%u wthread created and pinned ret=%d\n", mycpu, ret);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
cmd_sem = &tds[mycpu].cmd_sem;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(;;) {
|
|
Packit |
577717 |
dprint("CPU%u waiting for cmd\n", mycpu);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
sem_wait(cmd_sem);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
switch(td->cmd) {
|
|
Packit |
577717 |
case CMD_NONE:
|
|
Packit |
577717 |
ret = 0;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
case CMD_CTX:
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* copy context to get private fd
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ctx = td->data;
|
|
Packit |
577717 |
myctx = *ctx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
fd = pfm_create_context(&myctx, NULL, NULL, 0);
|
|
Packit |
577717 |
ret = fd < 0 ? -1 : 0;
|
|
Packit |
577717 |
dprint("CPU%u CMD_CTX ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
case CMD_LOAD:
|
|
Packit |
577717 |
ret = pfm_load_context(fd, &load_args);
|
|
Packit |
577717 |
dprint("CPU%u CMD_LOAD ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case CMD_UNLOAD:
|
|
Packit |
577717 |
ret = pfm_unload_context(fd);
|
|
Packit |
577717 |
dprint("CPU%u CMD_UNLOAD ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case CMD_START:
|
|
Packit |
577717 |
ret = pfm_start(fd, NULL);
|
|
Packit |
577717 |
dprint("CPU%u CMD_START ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case CMD_STOP:
|
|
Packit |
577717 |
ret = pfm_stop(fd);
|
|
Packit |
577717 |
dprint("CPU%u CMD_STOP ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case CMD_WPMCS:
|
|
Packit |
577717 |
ret = pfm_write_pmcs(fd,(pfarg_pmc_t *)td->data, td->ndata);
|
|
Packit |
577717 |
dprint("CPU%u CMD_WPMCS ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case CMD_WPMDS:
|
|
Packit |
577717 |
ret = pfm_write_pmds(fd,(pfarg_pmd_t *)td->data, td->ndata);
|
|
Packit |
577717 |
dprint("CPU%u CMD_WPMDS ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case CMD_RPMDS:
|
|
Packit |
577717 |
ret = pfm_read_pmds(fd,(pfarg_pmd_t *)td->data, td->ndata);
|
|
Packit |
577717 |
dprint("CPU%u CMD_RPMDS ret=%d errno=%d fd=%d\n", mycpu, ret, errno, fd);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case CMD_CLOSE:
|
|
Packit |
577717 |
dprint("CPU%u CMD_CLOSE fd=%d\n", mycpu, fd);
|
|
Packit |
577717 |
ret = close(fd);
|
|
Packit |
577717 |
fd = -1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
td->ret = ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
dprint("CPU%u td->ret=%d\n", mycpu, ret);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
barrier_wait(td->barrier);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
create_one_wthread(int cpu)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
sem_init(&tds[cpu].cmd_sem, 0, 0);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pthread_create(&tds[cpu].tid,
|
|
Packit |
577717 |
NULL,
|
|
Packit |
577717 |
(void *(*)(void *))pfms_thread_mainloop,
|
|
Packit |
577717 |
(void *)(long)cpu);
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* must be called with tds_lock held
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
create_wthreads(uint64_t *cpu_list, uint32_t n)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
uint64_t v;
|
|
Packit |
577717 |
uint32_t i,k, cpu;
|
|
Packit |
577717 |
int ret = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(k=0, cpu = 0; k < n; k++, cpu+= 64) {
|
|
Packit |
577717 |
v = cpu_list[k];
|
|
Packit |
577717 |
for(i=0; v && i < 63; i++, v>>=1, cpu++) {
|
|
Packit |
577717 |
if ((v & 0x1) && tds[cpu].tid == 0) {
|
|
Packit |
577717 |
ret = create_one_wthread(cpu);
|
|
Packit |
577717 |
if (ret) break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ret)
|
|
Packit |
577717 |
dprint("cannot create wthread on CPU%u\n", cpu);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfms_initialize(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
printf("cpu_t=%zu thread=%zu session_t=%zu\n",
|
|
Packit |
577717 |
sizeof(pfms_cpu_t),
|
|
Packit |
577717 |
sizeof(pfms_thread_t),
|
|
Packit |
577717 |
sizeof(pfms_session_t));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ncpus = (uint32_t)sysconf(_SC_NPROCESSORS_ONLN);
|
|
Packit |
577717 |
if (ncpus == -1) {
|
|
Packit |
577717 |
dprint("cannot retrieve number of online processors\n");
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
dprint("configured for %u CPUs\n", ncpus);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* XXX: assuming CPU are contiguously indexed
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
tds = calloc(ncpus, sizeof(*tds));
|
|
Packit |
577717 |
if (tds == NULL) {
|
|
Packit |
577717 |
dprint("cannot allocate thread descriptors\n");
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfms_create(uint64_t *cpu_list, size_t n, pfarg_ctx_t *ctx, pfms_ovfl_t *ovfl, void **desc)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
uint64_t v;
|
|
Packit |
577717 |
size_t k, i;
|
|
Packit |
577717 |
uint32_t num, cpu;
|
|
Packit |
577717 |
pfms_session_t *s;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (cpu_list == NULL || n == 0 || ctx == NULL || desc == NULL) {
|
|
Packit |
577717 |
dprint("invalid parameters\n");
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((ctx->ctx_flags & PFM_FL_SYSTEM_WIDE) == 0) {
|
|
Packit |
577717 |
dprint("only works for system wide\n");
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*desc = NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* XXX: assuming CPU are contiguously indexed
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
num = 0;
|
|
Packit |
577717 |
for(k=0, cpu = 0; k < n; k++, cpu+=64) {
|
|
Packit |
577717 |
v = cpu_list[k];
|
|
Packit |
577717 |
for(i=0; v && i < 63; i++, v>>=1, cpu++) {
|
|
Packit |
577717 |
if (v & 0x1) {
|
|
Packit |
577717 |
if (cpu >= ncpus) {
|
|
Packit |
577717 |
dprint("unavailable CPU%u\n", cpu);
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
num++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (num == 0)
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
s = calloc(1, sizeof(*s));
|
|
Packit |
577717 |
if (s == NULL) {
|
|
Packit |
577717 |
dprint("cannot allocate %u contexts\n", num);
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
s->ncpus = num;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
printf("%u-way session\n", num);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* +1 to account for main thread waiting
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = barrier_init(&s->barrier, num + 1);
|
|
Packit |
577717 |
if (ret) {
|
|
Packit |
577717 |
dprint("cannot init barrier\n");
|
|
Packit |
577717 |
goto error_free;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* lock thread descriptor table, no other create_session, close_session
|
|
Packit |
577717 |
* can occur
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pthread_mutex_lock(&tds_lock);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (create_wthreads(cpu_list, n))
|
|
Packit |
577717 |
goto error_free_unlock;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check all needed threads are available
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(k=0, cpu = 0; k < n; k++, cpu += 64) {
|
|
Packit |
577717 |
v = cpu_list[k];
|
|
Packit |
577717 |
for(i=0; v && i < 63; i++, v>>=1, cpu++) {
|
|
Packit |
577717 |
if (v & 0x1) {
|
|
Packit |
577717 |
if (tds[cpu].barrier) {
|
|
Packit |
577717 |
dprint("CPU%u already managing a session\n", cpu);
|
|
Packit |
577717 |
goto error_free_unlock;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* send create context order
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(k=0, cpu = 0; k < n; k++, cpu += 64) {
|
|
Packit |
577717 |
v = cpu_list[k];
|
|
Packit |
577717 |
for(i=0; v && i < 63; i++, v>>=1, cpu++) {
|
|
Packit |
577717 |
if (v & 0x1) {
|
|
Packit |
577717 |
tds[cpu].cmd = CMD_CTX;
|
|
Packit |
577717 |
tds[cpu].data = ctx;
|
|
Packit |
577717 |
tds[cpu].barrier = &s->barrier;
|
|
Packit |
577717 |
sem_post(&tds[cpu].cmd_sem);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
barrier_wait(&s->barrier);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check for errors
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(k=0; k < ncpus; k++) {
|
|
Packit |
577717 |
if (tds[k].barrier == &s->barrier) {
|
|
Packit |
577717 |
ret = tds[k].ret;
|
|
Packit |
577717 |
if (ret)
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* undo if error found
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (k < ncpus) {
|
|
Packit |
577717 |
for(k=0; k < ncpus; k++) {
|
|
Packit |
577717 |
if (tds[k].barrier == &s->barrier) {
|
|
Packit |
577717 |
if (tds[k].ret == 0) {
|
|
Packit |
577717 |
tds[k].cmd = CMD_CLOSE;
|
|
Packit |
577717 |
sem_post(&tds[k].cmd_sem);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/* mark as free */
|
|
Packit |
577717 |
tds[k].barrier = NULL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
pthread_mutex_unlock(&tds_lock);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ret == 0) *desc = s;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return ret ? -1 : 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
error_free_unlock:
|
|
Packit |
577717 |
pthread_mutex_unlock(&tds_lock);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
error_free:
|
|
Packit |
577717 |
free(s);
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfms_load(void *desc)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
uint32_t k;
|
|
Packit |
577717 |
pfms_session_t *s;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (desc == NULL) {
|
|
Packit |
577717 |
dprint("invalid parameters\n");
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
s = (pfms_session_t *)desc;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (s->ncpus == 0) {
|
|
Packit |
577717 |
dprint("invalid session content 0 CPUS\n");
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* send create context order
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(k=0; k < ncpus; k++) {
|
|
Packit |
577717 |
if (tds[k].barrier == &s->barrier) {
|
|
Packit |
577717 |
tds[k].cmd = CMD_LOAD;
|
|
Packit |
577717 |
sem_post(&tds[k].cmd_sem);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
barrier_wait(&s->barrier);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check for errors
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(k=0; k < ncpus; k++) {
|
|
Packit |
577717 |
if (tds[k].barrier == &s->barrier) {
|
|
Packit |
577717 |
ret = tds[k].ret;
|
|
Packit |
577717 |
if (ret) {
|
|
Packit |
577717 |
dprint("failure on CPU%u\n", k);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* if error, unload all others
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (k < ncpus) {
|
|
Packit |
577717 |
for(k=0; k < ncpus; k++) {
|
|
Packit |
577717 |
if (tds[k].barrier == &s->barrier) {
|
|
Packit |
577717 |
if (tds[k].ret == 0) {
|
|
Packit |
577717 |
tds[k].cmd = CMD_UNLOAD;
|
|
Packit |
577717 |
sem_post(&tds[k].cmd_sem);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return ret ? -1 : 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
__pfms_do_simple_cmd(pfms_cmd_t cmd, void *desc, void *data, uint32_t n)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
size_t k;
|
|
Packit |
577717 |
pfms_session_t *s;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (desc == NULL) {
|
|
Packit |
577717 |
dprint("invalid parameters\n");
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
s = (pfms_session_t *)desc;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (s->ncpus == 0) {
|
|
Packit |
577717 |
dprint("invalid session content 0 CPUS\n");
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* send create context order
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(k=0; k < ncpus; k++) {
|
|
Packit |
577717 |
if (tds[k].barrier == &s->barrier) {
|
|
Packit |
577717 |
tds[k].cmd = cmd;
|
|
Packit |
577717 |
tds[k].data = data;
|
|
Packit |
577717 |
tds[k].ndata = n;
|
|
Packit |
577717 |
sem_post(&tds[k].cmd_sem);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
barrier_wait(&s->barrier);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check for errors
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(k=0; k < ncpus; k++) {
|
|
Packit |
577717 |
if (tds[k].barrier == &s->barrier) {
|
|
Packit |
577717 |
ret = tds[k].ret;
|
|
Packit |
577717 |
if (ret) {
|
|
Packit |
577717 |
dprint("failure on CPU%zu\n", k);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* simple commands cannot be undone
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
return ret ? -1 : 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfms_unload(void *desc)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return __pfms_do_simple_cmd(CMD_UNLOAD, desc, NULL, 0);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfms_start(void *desc)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return __pfms_do_simple_cmd(CMD_START, desc, NULL, 0);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfms_stop(void *desc)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return __pfms_do_simple_cmd(CMD_STOP, desc, NULL, 0);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfms_write_pmcs(void *desc, pfarg_pmc_t *pmcs, uint32_t n)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return __pfms_do_simple_cmd(CMD_WPMCS, desc, pmcs, n);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfms_write_pmds(void *desc, pfarg_pmd_t *pmds, uint32_t n)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return __pfms_do_simple_cmd(CMD_WPMDS, desc, pmds, n);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfms_close(void *desc)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
size_t k;
|
|
Packit |
577717 |
pfms_session_t *s;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (desc == NULL) {
|
|
Packit |
577717 |
dprint("invalid parameters\n");
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
s = (pfms_session_t *)desc;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (s->ncpus == 0) {
|
|
Packit |
577717 |
dprint("invalid session content 0 CPUS\n");
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(k=0; k < ncpus; k++) {
|
|
Packit |
577717 |
if (tds[k].barrier == &s->barrier) {
|
|
Packit |
577717 |
tds[k].cmd = CMD_CLOSE;
|
|
Packit |
577717 |
sem_post(&tds[k].cmd_sem);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
barrier_wait(&s->barrier);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pthread_mutex_lock(&tds_lock);
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check for errors
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(k=0; k < ncpus; k++) {
|
|
Packit |
577717 |
if (tds[k].barrier == &s->barrier) {
|
|
Packit |
577717 |
if (tds[k].ret) {
|
|
Packit |
577717 |
dprint("failure on CPU%zu\n", k);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
ret |= tds[k].ret;
|
|
Packit |
577717 |
tds[k].barrier = NULL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pthread_mutex_unlock(&tds_lock);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
free(s);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* XXX: we cannot undo close
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
return ret ? -1 : 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfms_read_pmds(void *desc, pfarg_pmd_t *pmds, uint32_t n)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfms_session_t *s;
|
|
Packit |
577717 |
uint32_t k, pmds_per_cpu;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (desc == NULL) {
|
|
Packit |
577717 |
dprint("invalid parameters\n");
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
s = (pfms_session_t *)desc;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (s->ncpus == 0) {
|
|
Packit |
577717 |
dprint("invalid session content 0 CPUS\n");
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (n % s->ncpus) {
|
|
Packit |
577717 |
dprint("invalid number of pfarg_pmd_t provided, must be multiple of %u\n", s->ncpus);
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
pmds_per_cpu = n / s->ncpus;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
dprint("n=%u ncpus=%u per_cpu=%u\n", n, s->ncpus, pmds_per_cpu);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(k=0; k < ncpus; k++) {
|
|
Packit |
577717 |
if (tds[k].barrier == &s->barrier) {
|
|
Packit |
577717 |
tds[k].cmd = CMD_RPMDS;
|
|
Packit |
577717 |
tds[k].data = pmds;
|
|
Packit |
577717 |
tds[k].ndata= pmds_per_cpu;
|
|
Packit |
577717 |
sem_post(&tds[k].cmd_sem);
|
|
Packit |
577717 |
pmds += pmds_per_cpu;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
barrier_wait(&s->barrier);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check for errors
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(k=0; k < ncpus; k++) {
|
|
Packit |
577717 |
if (tds[k].barrier == &s->barrier) {
|
|
Packit |
577717 |
ret = tds[k].ret;
|
|
Packit |
577717 |
if (ret) {
|
|
Packit |
577717 |
dprint("failure on CPU%u\n", k);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* cannot undo pfm_read_pmds
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
return ret ? -1 : 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#if 0
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* beginning of test program
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#include <perfmon/pfmlib.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define NUM_PMCS PFMLIB_MAX_PMCS
|
|
Packit |
577717 |
#define NUM_PMDS PFMLIB_MAX_PMDS
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void fatal_error(char *fmt,...) __attribute__((noreturn));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
fatal_error(char *fmt, ...)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
va_list ap;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
va_start(ap, fmt);
|
|
Packit |
577717 |
vfprintf(stderr, fmt, ap);
|
|
Packit |
577717 |
va_end(ap);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
exit(1);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static uint32_t
|
|
Packit |
577717 |
popcount(uint64_t c)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
uint32_t count = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(; c; c>>=1) {
|
|
Packit |
577717 |
if (c & 0x1)
|
|
Packit |
577717 |
count++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return count;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
main(int argc, char **argv)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfarg_ctx_t ctx;
|
|
Packit |
577717 |
pfarg_pmc_t pc[NUM_PMCS];
|
|
Packit |
577717 |
pfarg_pmd_t *pd;
|
|
Packit |
577717 |
pfmlib_input_param_t inp;
|
|
Packit |
577717 |
pfmlib_output_param_t outp;
|
|
Packit |
577717 |
uint64_t cpu_list;
|
|
Packit |
577717 |
void *desc;
|
|
Packit |
577717 |
unsigned int num_counters;
|
|
Packit |
577717 |
uint32_t i, j, k, l, ncpus, npmds;
|
|
Packit |
577717 |
size_t len;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
char *name;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_initialize() != PFMLIB_SUCCESS)
|
|
Packit |
577717 |
fatal_error("cannot initialize libpfm\n");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfms_initialize())
|
|
Packit |
577717 |
fatal_error("cannot initialize libpfms\n");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_get_num_counters(&num_counters);
|
|
Packit |
577717 |
pfm_get_max_event_name_len(&len;;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
name = malloc(len+1);
|
|
Packit |
577717 |
if (name == NULL)
|
|
Packit |
577717 |
fatal_error("cannot allocate memory for event name\n");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&ctx, 0, sizeof(ctx));
|
|
Packit |
577717 |
memset(pc, 0, sizeof(pc));
|
|
Packit |
577717 |
memset(&inp,0, sizeof(inp));
|
|
Packit |
577717 |
memset(&outp,0, sizeof(outp));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
cpu_list = argc > 1 ? strtoul(argv[1], NULL, 0) : 0x3;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ncpus = popcount(cpu_list);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_get_cycle_event(&inp.pfp_events[0].event) != PFMLIB_SUCCESS)
|
|
Packit |
577717 |
fatal_error("cannot find cycle event\n");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_get_inst_retired_event(&inp.pfp_events[1].event) != PFMLIB_SUCCESS)
|
|
Packit |
577717 |
fatal_error("cannot find inst retired event\n");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
i = 2;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
inp.pfp_dfl_plm = PFM_PLM3|PFM_PLM0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (i > num_counters) {
|
|
Packit |
577717 |
i = num_counters;
|
|
Packit |
577717 |
printf("too many events provided (max=%d events), using first %d event(s)\n", num_counters, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* how many counters we use
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
inp.pfp_event_count = i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* indicate we are using the monitors for a system-wide session.
|
|
Packit |
577717 |
* This may impact the way the library sets up the PMC values.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
inp.pfp_flags = PFMLIB_PFP_SYSTEMWIDE;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* let the library figure out the values for the PMCS
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if ((ret=pfm_dispatch_events(&inp, NULL, &outp, NULL)) != PFMLIB_SUCCESS)
|
|
Packit |
577717 |
fatal_error("cannot configure events: %s\n", pfm_strerror(ret));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
npmds = ncpus * inp.pfp_event_count;
|
|
Packit |
577717 |
dprint("ncpus=%u npmds=%u\n", ncpus, npmds);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pd = calloc(npmds, sizeof(pfarg_pmd_t));
|
|
Packit |
577717 |
if (pd == NULL)
|
|
Packit |
577717 |
fatal_error("cannot allocate pd array\n");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i=0; i < outp.pfp_pmc_count; i++) {
|
|
Packit |
577717 |
pc[i].reg_num = outp.pfp_pmcs[i].reg_num;
|
|
Packit |
577717 |
pc[i].reg_value = outp.pfp_pmcs[i].reg_value;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(l=0, k = 0; l < ncpus; l++) {
|
|
Packit |
577717 |
for (i=0, j=0; i < inp.pfp_event_count; i++, k++) {
|
|
Packit |
577717 |
pd[k].reg_num = outp.pfp_pmcs[j].reg_pmd_num;
|
|
Packit |
577717 |
for(; j < outp.pfp_pmc_count; j++) if (outp.pfp_pmcs[j].reg_evt_idx != i) break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* create a context on all CPUs we asked for
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* libpfms only works for system-wide, so we set the flag in
|
|
Packit |
577717 |
* the master context. the context argument is not modified by
|
|
Packit |
577717 |
* call.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* desc is an opaque descriptor used to identify session.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ctx.ctx_flags = PFM_FL_SYSTEM_WIDE;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfms_create(&cpu_list, 1, &ctx, NULL, &desc);
|
|
Packit |
577717 |
if (ret == -1)
|
|
Packit |
577717 |
fatal_error("create error %d\n", ret);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* program the PMC registers on all CPUs of interest
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfms_write_pmcs(desc, pc, outp.pfp_pmc_count);
|
|
Packit |
577717 |
if (ret == -1)
|
|
Packit |
577717 |
fatal_error("write_pmcs error %d\n", ret);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* program the PMD registers on all CPUs of interest
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfms_write_pmds(desc, pd, inp.pfp_event_count);
|
|
Packit |
577717 |
if (ret == -1)
|
|
Packit |
577717 |
fatal_error("write_pmds error %d\n", ret);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* load context on all CPUs of interest
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfms_load(desc);
|
|
Packit |
577717 |
if (ret == -1)
|
|
Packit |
577717 |
fatal_error("load error %d\n", ret);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* start monitoring on all CPUs of interest
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfms_start(desc);
|
|
Packit |
577717 |
if (ret == -1)
|
|
Packit |
577717 |
fatal_error("start error %d\n", ret);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* simulate some work
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
sleep(10);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* stop monitoring on all CPUs of interest
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfms_stop(desc);
|
|
Packit |
577717 |
if (ret == -1)
|
|
Packit |
577717 |
fatal_error("stop error %d\n", ret);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* read the PMD registers on all CPUs of interest.
|
|
Packit |
577717 |
* The pd[] array must be organized such that to
|
|
Packit |
577717 |
* read 2 PMDs on each CPU you need:
|
|
Packit |
577717 |
* - 2 * number of CPUs of interest
|
|
Packit |
577717 |
* - the first 2 elements of pd[] read on 1st CPU
|
|
Packit |
577717 |
* - the next 2 elements of pd[] read on the 2nd CPU
|
|
Packit |
577717 |
* - and so on
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfms_read_pmds(desc, pd, npmds);
|
|
Packit |
577717 |
if (ret == -1)
|
|
Packit |
577717 |
fatal_error("read_pmds error %d\n", ret);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* pre per-CPU results
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(j=0, k= 0; j < ncpus; j++) {
|
|
Packit |
577717 |
for (i=0; i < inp.pfp_event_count; i++, k++) {
|
|
Packit |
577717 |
pfm_get_full_event_name(&inp.pfp_events[i], name, len);
|
|
Packit |
577717 |
printf("CPU%-3d PMD%u %20"PRIu64" %s\n",
|
|
Packit |
577717 |
j,
|
|
Packit |
577717 |
pd[k].reg_num,
|
|
Packit |
577717 |
pd[k].reg_value,
|
|
Packit |
577717 |
name);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* destroy context on all CPUs of interest.
|
|
Packit |
577717 |
* After this call desc is invalid
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfms_close(desc);
|
|
Packit |
577717 |
if (ret == -1)
|
|
Packit |
577717 |
fatal_error("close error %d\n", ret);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
free(name);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#endif
|