Re: perf_counters issue with enable_on_exec

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: stephane eranian
Date: Monday, August 24, 2009 - 8:44 am

On Mon, Aug 24, 2009 at 3:46 PM, Peter Zijlstra<a.p.zijlstra@chello.nl> wrote:

That's true. I knew about the missing synchro. But I think
the problem existed nonetheless.


then fail it.

True.

I have modified the program based on your changes. See new version attached.

All events in a group are scheduled together. If one event is not enabled
in a group, then the group is not dispatched. Setting enable_on_exec
just on leader makes sense. Then to enable the group on exec, you
enabled all events but the leader. The enable_on_exec will enable
the leader on exec and the group will be ready for dispatch. That's
how it should work in my mind.


As you indicated the issue is with the timing information and I think
it is not related to enable_on_exec. It is more related to the fact
that to enable a group with a single ioctl() you enable ALL BUT the
leader. But that means that the time_enabled for the !leader is
ticking. Thus scaling won't be as expected yet it is correct
given what happens internally.

I think there needs to be a distinction between 'enabled immediately
but cannot run because group is not totally enabled' and 'cannot run
because the group has been multiplexed out yet all could be dispatched
because all events were dispatched'. In the former, it seems you don't
want time_enabled to tick, while in the latter you do. In other words,
time_enabled ticks for each event if the group is 'dispatch-able' (or
runnable in your terminology) otherwise it does not. time_enabled reflects
the fact that the group could run but did not have access to the PMU
resource because of contention with other groups.


#include <sys/types.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <syscall.h>
#include <err.h>

#include <perfmon/pfmlib_perf_counter.h>


int
child(char **arg)
{
        int i;

        /* burn cycles to detect if monitoring start before exec */
        for(i=0; i < 5000000; i++) syscall(__NR_getpid);
        /*
         * execute the requested command
         */
        execvp(arg[0], arg);
        errx(1, "cannot exec: %s\n", arg[0]);
        /* not reached */
}

int
parent(char **arg)
{
        struct perf_counter_attr hw[2];
        char *name[2], buf;
        int fd[2];
        int status, ret, i;
        uint64_t values[3];
        pid_t pid;
        int ready[2], go[2];


        ret = pipe(ready);
        if (ret)
                err(1, "cannot create pipe ready");

        ret = pipe(go);
        if (ret)
                err(1, "cannot create pipe go");

        /*
         * Create the child task
         */
        if ((pid=fork()) == -1)
                err(1, "Cannot fork process");

        /*
         * and launch the child code
         */
        if (pid == 0) {
                close(ready[0]);
                close(go[1]);

                /*
                 * let the parent know we exist
                 */
               close(ready[1]);
               if (read(go[0], &buf, 1) == -1)
                       err(1, "unable to read go_pipe");

                close(go[0]);
                exit(child(arg));
        }

        close(ready[1]);
        close(go[0]);

        if (read(ready[0], &buf, 1) == -1)
               err(1, "unable to read child_ready_pipe");

        close(ready[0]);

        memset(hw, 0, sizeof(hw));

        name[0] = "PERF_COUNT_HW_CPU_CYCLES";
        hw[0].type = PERF_TYPE_HARDWARE;
        hw[0].config = PERF_COUNT_HW_CPU_CYCLES;
        hw[0].read_format =
PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING;
        hw[0].disabled = 1;
        hw[0].enable_on_exec = 1;

        name[1] = "PERF_COUNT_HW_CPU_CYCLES";
        hw[1].type = PERF_TYPE_HARDWARE;
        hw[1].config = PERF_COUNT_HW_CPU_CYCLES;
        hw[1].read_format =
PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING;
        hw[1].disabled = 0;
        hw[1].enable_on_exec = 0;

        fd[0] = perf_counter_open(&hw[0], pid, -1, -1, 0);
        if (fd[0] == -1)
                err(1, "cannot open event0");

        fd[1] = perf_counter_open(&hw[1], pid, -1, fd[0], 0);
        if (fd[1] == -1)
                err(1, "cannot open event1");


        close(go[1]);

        waitpid(pid, &status, 0);

        /*
         * the task has disappeared at this point but our session is still
         * present and contains all the latest counts.
         */

        /*
         * now simply read the results.
         */
        for(i=0; i < 2; i++) {
                ret = read(fd[i], values, sizeof(values));
                if (ret < sizeof(values))
                        err(1, "cannot read values event %s", name[i]);

                printf("%20"PRIu64" %s %ld %ld %f\n",
                        values[0],
                        name[i],
                        values[1], values[2],
                        values[2] ? (double)values[0] *
values[1]/values[2] : 0);

                close(fd[i]);
        }
        return 0;
}

int
main(int argc, char **argv)
{
        if (!argv[1])
                errx(1, "you must specify a command to execute\n");

        return parent(argv+1);
}
--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
perf_counters issue with enable_on_exec, stephane eranian, (Thu Aug 20, 6:49 am)
Re: perf_counters issue with enable_on_exec, Peter Zijlstra, (Mon Aug 24, 6:46 am)
Re: perf_counters issue with enable_on_exec, stephane eranian, (Mon Aug 24, 8:44 am)
Re: perf_counters issue with enable_on_exec, stephane eranian, (Mon Aug 24, 9:03 am)
Re: perf_counters issue with enable_on_exec, Peter Zijlstra, (Mon Aug 24, 9:06 am)
Re: perf_counters issue with enable_on_exec, stephane eranian, (Mon Aug 24, 9:16 am)
Re: perf_counters issue with enable_on_exec, Paul Mackerras, (Mon Aug 24, 2:35 pm)
Re: perf_counters issue with enable_on_exec, Paul Mackerras, (Mon Aug 24, 3:27 pm)
Re: perf_counters issue with enable_on_exec, stephane eranian, (Mon Aug 24, 3:30 pm)
Re: perf_counters issue with enable_on_exec, Paul Mackerras, (Mon Aug 24, 3:31 pm)
[tip:perfcounters/core] perf_counter: Start counting time ..., tip-bot for Paul Mac ..., (Tue Aug 25, 12:36 am)