Juan,

Found the problem. It is in the example.
The reason you ceased to get notification is because the notification
queue is full.
For each notification a message is enqueued. When you get the notification, you
need to extract that message via a read(). So I think all that is
missing in your
program is.

pfarg_msg_t msg;
read(fd, &msg, sizeof(msg));

in the signal handler before pfm_restart();

In the case of trivial sampling, it is possible to request no
notification messages be
sent by setting a context flag.

ctx.ctx_flags = PFM_FL_OVFL_NO_MSG
pfm_create_context(&ctx, "default", .....)

In either case, you will getting infinite number of notifications.

On Thu, May 14, 2009 at 2:18 PM, stephane eranian
<eran...@googlemail.com> wrote:
> Juan,
>
> I am able to reproduce the problem with a modified mont_dear.c. There
> it stops after the
> 8th notification. This is quite strange given this is all self
> monitoring. Let me investigate.
> I also want to verify if this is IA-64 specific or not.
>
>
> On Thu, May 14, 2009 at 11:49 AM, Juan Angel Lorenzo
> <jalmailingli...@gmail.com> wrote:
>> Hi,
>>
>> El mié, 13-05-2009 a las 14:11 +0200, stephane eranian escribió:
>>
>>>
>>> > The number of notifications is the number of times the sampling buffer
>>> > overflowed, isn't it? So why does it look limited to 31? I mean, even if
>>>
>>> Yes, assuming your resume monitoring() via pfm_restart() at the end of
>>> each notification.
>>
>> Yes, as far as I saw, this is what the "mont_dear.c" code does. It
>> resumes monitoring every time a notification is handled. But it looks
>> there is a limit of 31 times the monitoring can be resumed. And then it
>> stops. I don't understand why. I thought this process could be done
>> infinite times. Could it be perhaps because of any limit in the
>> operating system settings?
>>
>>
>>> Did you read the pmds in the handler via pfm_read_pmds()?
>>>
>> Yes. Briefly, this is what I did (mixing code from mont_dear.c,
>> mont_rr.c and notify_self.c):
>>
>> #include <perfmon/perfmon.h>
>> #include <perfmon/perfmon_default_smpl.h>
>> #include <perfmon/pfmlib_montecito.h>
>>
>> #define SMPL_PERIOD     (40)
>> #define M_PMD(x)                (1UL<<(x))
>> #define DEAR_REGS_MASK          (M_PMD(32)|M_PMD(33)|M_PMD(36))
>>
>> typedef pfm_default_smpl_hdr_t     dear_hdr_t;
>> typedef pfm_default_smpl_entry_t   dear_entry_t;
>> typedef pfm_default_smpl_ctx_arg_t dear_ctx_t;
>>
>> static int ctx_fd;
>> static char *event1_name = "data_ear_cache_lat4";
>> static pfarg_reg_t pd[NUM_PMDS];
>>
>>
>> static void
>> sigio_handler(int n, struct siginfo *info, struct sigcontext *sc)
>> {
>>  pfm_msg_t msg;
>>  pfm_mont_pmd_reg_t reg;
>>  int fd = ctx_fd;
>>  int r;
>>
>>  if (fd != ctx_fd) {
>>    fatal_error("handler does not get valid file descriptor\n");
>>  }
>>
>>  if (event1_name && perfmonctl(fd, PFM_READ_PMDS, pd+1, 1) == -1) {
>>                fatal_error("PFM_READ_PMDS: %s", strerror(errno));
>>  }
>>
>>  r = read(fd, &msg, sizeof(msg));
>>  if (r != sizeof(msg)) {
>>    fatal_error("cannot read overflow message: %s\n", strerror(errno));
>>  }
>>
>>  printf("PMD pfarg_reg_t.reg_num: %u\n",pd[1].reg_num);
>>  printf("PMD pfarg_reg_t.reg_value: %lu\n",pd[1].reg_value);
>>  reg = (pfm_mont_pmd_reg_t)pd[1].reg_value;
>>  printf("PMD32: 0x%016lx\n", reg.pmd32_mont_reg.dear_daddr);
>>
>>  ........
>>
>>   /*
>>    * And resume monitoring
>>    */
>>    if (perfmonctl(fd, PFM_RESTART,NULL, 0) == -1) {
>>        fatal_error("PFM_RESTART: %s", strerror(errno));
>>    }
>> }
>>
>>
>>
>> int
>> main(int argc, char **argv)
>> {
>>
>>        pfarg_reg_t pc[NUM_PMCS];
>>        pfmlib_input_param_t inp;
>>        pfmlib_output_param_t outp;
>>        pfmlib_event_t ev;
>>        dear_ctx_t ctx;
>>        pfarg_load_t load_args;
>>        pfmlib_options_t pfmlib_options;
>>        struct sigaction act;
>>
>>        ......
>>        unsigned long range_start, range_end;
>>        pfmlib_mont_input_param_t mont_inp;
>>        pfmlib_mont_output_param_t mont_outp;
>>        pfarg_dbreg_t dbrs[8];
>>
>>        ......
>>
>>        if (pfm_find_full_event(event1_name, &ev) != PFMLIB_SUCCESS)
>>                fatal_error("cannot find event %s\n", event1_name);
>>
>>        inp.pfp_dfl_plm   = PFM_PLM3|PFM_PLM0;
>>
>>        /*
>>         * how many counters we use
>>         */
>>        inp.pfp_event_count = 1;
>>
>>        /*
>>         * propagate the event descriptor
>>         */
>>        inp.pfp_events[0] = ev;
>>
>>
>>        mont_inp.pfp_mont_drange.rr_used = 1;
>>        mont_inp.pfp_mont_drange.rr_limits[0].rr_start = range_start;
>>        mont_inp.pfp_mont_drange.rr_limits[0].rr_end   = range_end;
>>
>>        if ((ret=pfm_dispatch_events(&inp, &mont_inp,
>>             &outp,&mont_outp)) != PFMLIB_SUCCESS)
>>                fatal_error("cannot configure events: %s\n",
>>                                        pfm_strerror(ret));
>>
>>        /*
>>         * now create the context for self monitoring/per-task
>>         */
>>        if (perfmonctl(0, PFM_CREATE_CONTEXT, &ctx, 1) == -1 ) {
>>                if (errno == ENOSYS) {
>>                        fatal_error("Your kernel does not have
>>                        performance monitoring support!\n");
>>                }
>>                fatal_error("Can't create PFM context %s\n",
>>                                        strerror(errno));
>>        }
>>
>>        ctx_fd = ctx.ctx_arg.ctx_fd;
>>
>>
>>        for (i=0; i < outp.pfp_pmc_count; i++) {
>>                pc[i].reg_num   = outp.pfp_pmcs[i].reg_num;
>>                pc[i].reg_value = outp.pfp_pmcs[i].reg_value;
>>        }
>>
>>
>>        /*
>>         * figure out pmd mapping from output pmc
>>         */
>>        for (i=0; i < outp.pfp_pmd_count; i++)
>>                pd[i].reg_num   = outp.pfp_pmds[i].reg_num;
>>
>>        /*
>>         * We want to get notified when the counter used for our first
>>         * event overflows
>>         */
>>        pc[0].reg_flags         |= PFM_REGFL_OVFL_NOTIFY;
>>        pc[0].reg_reset_pmds[0] |= 1UL << outp.pfp_pmds[1].reg_num;
>>
>>
>>        /*
>>         * initialize the PMD and the sampling period
>>         */
>>        pd[0].reg_value       = - SMPL_PERIOD;
>>        pd[0].reg_long_reset  = - SMPL_PERIOD;
>>        pd[0].reg_short_reset = - SMPL_PERIOD;
>>
>>
>>        if (perfmonctl(ctx_fd, PFM_WRITE_DBRS, dbrs,
>>                        mont_outp.pfp_mont_drange.rr_nbr_used) == -1) {
>>                fatal_error( "child: perfmonctl error PFM_WRITE_DBRS
>>                                                errno %d\n",errno);
>>        }
>>
>>
>>        if (perfmonctl(ctx_fd, PFM_WRITE_PMCS, pc, outp.pfp_pmc_count))
>>                fatal_error("pfm_write_pmcs error errno %d\n",errno);
>>
>>        if (perfmonctl(ctx_fd, PFM_WRITE_PMDS, pd, outp.pfp_pmd_count))
>>                fatal_error("pfm_write_pmds error errno %d\n",errno);
>>
>>        /*
>>         * attach context to stopped task
>>         */
>>        load_args.load_pid = getpid();
>>        if (perfmonctl(ctx_fd, PFM_LOAD_CONTEXT, &load_args, 1))
>>                fatal_error("pfm_load_context error errno %d\n",errno);
>>
>>
>>        /*
>>         * setup asynchronous notification on the file descriptor
>>         */
>>        ret = fcntl(ctx_fd, F_SETFL, fcntl(ctx_fd, F_GETFL, 0) |
>>                                                        O_ASYNC);
>>
>>        /*
>>         * get ownership of the descriptor
>>         */
>>        ret = fcntl(ctx_fd, F_SETOWN, getpid());
>>
>>        /*
>>         * Let's roll now.
>>         */
>>        pfm_self_start(ctx_fd);
>>
>>        .......
>>
>>        pfm_self_stop(ctx_fd);
>>
>>        close(ctx_fd);
>>        return 0;
>> }
>>
>>
>> There's one thing I'm not sure is right. There was a line in
>> notify_self.c:
>>
>> pc[0].reg_reset_pmds[0] |= 1UL << outp.pfp_pmcs[1].reg_num;
>>
>> which gives me a "pfm_write_pmcs error errno 22" error in this code. I
>> think it intends to set the byte 32th in the reg_reset_pmds[0] field, so
>> I changed it to:
>>
>> pc[0].reg_reset_pmds[0] |= 1UL << outp.pfp_pmds[1].reg_num;
>>
>> So the code runs, but when I get a notification, the value of
>> pd[1].reg_value, in the sigio_handler, is always 0.
>>
>> Again, thanks for the help and apologies for the long email. If this
>> code is not clear enough, I can attach the whole file.
>>
>> Juan
>>
>>
>

------------------------------------------------------------------------------
The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your
production scanning environment may not be a perfect world - but thanks to
Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700
Series Scanner you'll get full speed at 300 dpi even with all image 
processing features enabled. http://p.sf.net/sfu/kodak-com
_______________________________________________
perfmon2-devel mailing list
perfmon2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/perfmon2-devel

Reply via email to