Hello Phillippe,
thanks for the instant reply.

Here is the output of your test code:

# while `true`
> do
> ./simple_test
> done

t_create(tid=54) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=54) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=57) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=57) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=60) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=60) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=63) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=63) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=66) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=66) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=69) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=69) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=72) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=72) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=75) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 0, ev=0x3
t_start(tid=75) = 0
t_create(tid=78) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=78) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=81) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=81) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=84) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=84) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=87) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=87) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=90) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=90) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=93) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=93) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=96) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=96) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=99) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=99) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=102) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=102) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=105) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=105) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=108) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=108) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=111) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=111) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=114) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=114) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=117) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 0, ev=0x3
t_start(tid=117) = 0
t_create(tid=120) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=120) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=123) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 0, ev=0x3
t_start(tid=123) = 0
t_create(tid=126) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=126) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=129) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=129) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=132) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=132) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=135) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=135) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
t_create(tid=138) = 0
Started... (1, 2, 3, 4)
tm_evevery(4, 3, &tmid) => 0
tm_cancel(&tmid) => 0
t_start(tid=138) = 0
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0

As you can see, in some cases the event is received, even it the timeout
value is 4.
This is the same observation as I did in my code. I also see the event being
received with timeout values of 1 AND 2.

This is the testcode I have used. It is almost identical with the code you
have send me, I needed to change 2 things to make it work:
- "ret = ev_receive(4, EV_ANY|EV_WAIT, 10, &ev)" replaced by "ret =
ev_receive(3, EV_ANY|EV_WAIT, 10, &ev);"
- added a sleep at the end of main and foo to make the output printed on the
screen. If the sleep is not there, the last printf statement is not visible.

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <psos+/psos.h>

void foo (u_long a0, u_long a1, u_long a2, u_long a3)
{
        u_long ret, ev = 0, tmid;

        printf("Started... (%lu, %lu, %lu, %lu)\n", a0, a1, a2, a3);
        ret = tm_evevery(4, 3, &tmid);
        printf("tm_evevery(4, 3, &tmid) => %lu\n", ret);

        ret = tm_cancel(tmid);
        printf("tm_cancel(&tmid) => %lu\n", ret);

        ret = ev_receive(3, EV_ANY|EV_WAIT, 10, &ev);
        printf("ev_receive(3, EV_ANY|EV_WAIT, 10, &ev) => %lu, ev=0x%lx\n",
ret, ev);
        tm_wkafter(100);

}

int main (int ac, char **av)
{
        u_long ret, tid = 0, args[4];

        mlockall(MCL_CURRENT | MCL_FUTURE);

        ret = t_create("TEST", 1, 0, 0, 0, &tid);
        printf("t_create(tid=%lu) = %lu\n", tid, ret);
        args[0] = 1;
        args[1] = 2;
        args[2] = 3;
        args[3] = 4;
        ret = t_start(tid, 0, foo, args);
        printf("t_start(tid=%lu) = %lu\n", tid, ret);

        tm_wkafter(100);
        return 0;
}


About the pending question: I indeed recieve error code 60 (ERR_NOEVS) in
case no event is pending.

Best regards,
Ronny

On Wed, Nov 17, 2010 at 3:01 PM, Philippe Gerum <[email protected]> wrote:

> On Wed, 2010-11-17 at 14:49 +0100, ronny meeus wrote:
> > Hello
> >
> > I did some more tests on QEMU since the behavior on Simics is
> > identical to the behavior I see on QEMU.
> > This is the testcode I have used:
> >
> > void test_timer_cancel(void)
> > {
> >         unsigned long tmr_id,ev,ret,i;
> >         unsigned long failed = 0;
> >
> >         for (i=1;i<3;i++)
> >         {
> >                 ret = tm_evevery(i,1,&tmr_id);
> >                 ut_printf("tm_evevery(%lu,1,&tmr_id) => %lu\n",
> > i,ret);
> >
> >                 ret = tm_cancel(tmr_id);
> >                 ut_printf("tm_cancel(&tmid) => %lu\n", ret);
> >
> >                 ev = 0;
> >                 ret = ev_receive(1, EV_ANY|EV_WAIT, 200, &ev);
> >                 ut_printf("ev_receive(1, EV_ANY|EV_WAIT, 10, &ev) => %
> > lu, ev=0x%lx\n", ret, ev);
> >
> >                 tm_wkafter(2);
> >
> >                 if (ret == 0)
> >                         failed++;
> >         }
> >         ut_printf("#events received after cancel %lu (loopcount=%lu)\n
> > \n",failed,i);
> > }
> >
> > void run_test(void)
> > {
> >         test_timer_cancel();
> > }
> >
> > static void task_body_wrapper(unsigned long func,unsigned long
> > count,unsigned long smid,unsigned long d)
> > {
> >     unsigned long i;
> >     ut_printf("In task_body_wrapper\n");
> >     test_function test = (test_function)func;
> >     for (i=0;i<count;i++)
> >         test();
> >     sm_v(smid);
> > }
> >
> > static void task_wrapper(test_function f,unsigned long count)
> > {
> >         unsigned long tid,smid;
> >         unsigned long args[4] = {(unsigned long)f,count,0,0};
> >
> >         sm_create("BLOC",0,SM_PRIOR,&smid);
> >         args[2] = smid;
> >
> >         t_create("TEST",25,16000,16000,0,&tid);
> >         t_start(tid,0,task_body_wrapper,args);
> >
> >        sm_p(smid,SM_WAIT,0);
> >        sm_delete(smid);
> >
> >        t_delete(tid);
> > }
> >
> > int main(int argc, char **argv)
> > {
> >     unsigned long rnid,rsize,i;
> >
> >     mlockall(MCL_CURRENT|MCL_FUTURE);
> >     rt_print_auto_init(1);
> >
> >     /* Body of the test goes here */
> >     while (1)
> >     {
> >         task_wrapper(run_test,1);
> >
> >         for (i=0;i<1;i++)
> >             run_test();
> >
> >         task_wrapper(run_test,1);
> >     }
> > }
> >
> > (The ut_printf function is mapped on rt_printf.)
> > So this test is identical to the test you proposed.
>
> No, the reason I sent you this frag, is because we are currently
> assuming that no tick will happen between tm_evevery() and ev_receive(),
> which is wrong, at least in theory. So this small frag is actually
> reducing the complexity to the bare minimum, so that we don't chase wild
> gooses uselessly.
>
> The clock is not synchronized with your application in periodic mode, so
> you can't be sure that a pending tick won't hit the kernel - and thus
> deliver the event - prior to entering ev_receive(). The odds of being
> preempted by ev_send() on behalf of the tick handler before entering
> ev_receive() is even higher with a period set to one tick, like in your
> example, which is therefore wrong once again. Slowing down the code with
> trace output may introduce variations if timing is involved.
>
> Besides, you did not answer to the question regarding ERR_NOEVS, which
> might be useful to assess where the problem might be.
>
> > The function "test_timer_cancel" is called both from the context of
> > the main thread and a TEST thread.
> >
> > This is the output I get when running the test:
> >
> > In task_body_wrapper
> > tm_evevery(1,1,&tmr_id) => 0
> > tm_cancel(&tmid) => 0
> > ev_receive(1, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
> > tm_evevery(2,1,&tmr_id) => 0
> > tm_cancel(&tmid) => 0
> > ev_receive(1, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
> > #events received after cancel 0 (loopcount=3)
> >
> > tm_evevery(1,1,&tmr_id) => 0
> > tm_cancel(&tmid) => 0
> > ev_receive(1, EV_ANY|EV_WAIT, 10, &ev) => 0, ev=0x1
> > tm_evevery(2,1,&tmr_id) => 0
> > tm_cancel(&tmid) => 0
> > ev_receive(1, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
> > #events received after cancel 1 (loopcount=3)
> >
> > In task_body_wrapper
> > tm_evevery(1,1,&tmr_id) => 0
> > tm_cancel(&tmid) => 0
> > ev_receive(1, EV_ANY|EV_WAIT, 10, &ev) => 0, ev=0x1
> > tm_evevery(2,1,&tmr_id) => 0
> > tm_cancel(&tmid) => 0
> > ev_receive(1, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
> > #events received after cancel 1 (loopcount=3)
> >
> > In task_body_wrapper
> > tm_evevery(1,1,&tmr_id) => 0
> > tm_cancel(&tmid) => 0
> > ev_receive(1, EV_ANY|EV_WAIT, 10, &ev) => 1, ev=0x0
> > tm_evevery(2,1,&tmr_id) => 0
> > tm_cancel(&tmid) => 0
> >
> > As you can see in most of the cases the system behaves correctly.
> > In some cases, the event is received. This is the case both from the
> > context of the main thread and the special thread.
> > I just copy-pasted a part of the output. In most cases, the event is
> > not received. I think something like 1 times out of 50 I see the event
> > being received.
> >
> > It looks like, if it happens, it is always the first iteration of the
> > loop (the one with a timeout of 1 tick). Even if I change the initial
> > timeout value to 2, the event is also received sporadically.
> >
> > [ Phillippe, please note that in your test code, you have also swapped
> > the parameters. You send event 3 and lateron check whether you have
> > received event 4. :-) ]
> >
> > Another observation is that after removing the ut_printf statements, I
> > do not see the issue anymore.
> > It looks like the printf/rt_printf has an impact on the system
> > behavior.
> >
> > I had a quick look to the LTTng as well, but I need to fix the patches
> > before I will be able to integrate.
> > I think this will be my next step.
> >
> > Best regards,
> > Ronny
> >
> >
> > On Mon, Nov 15, 2010 at 10:30 AM, Philippe Gerum <[email protected]>
> > wrote:
> >         On Sun, 2010-11-14 at 01:24 +0100, ronny meeus wrote:
> >         > Hello
> >         >
> >         > I'm currently fighting with a problem in the pSOS+ skin.
> >         > This my system information:
> >         >
> >         > [    2.314676] pci 0000:00:01.0: Activating ISA DMA hang
> >         workarounds
> >         > [    2.416025] I-pipe: Domain Xenomai registered.
> >         > [    2.418183] Xenomai: hal/i386 started.
> >         > [    2.422780] Xenomai: scheduling class idle registered.
> >         > [    2.424116] Xenomai: scheduling class rt registered.
> >         > [    2.566737] Xenomai: real-time nucleus v2.5.4 (Sleep
> >         Walk) loaded.
> >         > [    2.590628] Xenomai: starting native API services.
> >         > [    2.604491] Xenomai: starting pSOS+ services.
> >         > [    2.619941] HugeTLB registered 4 MB page size,
> >         pre-allocated 0
> >         > pages
> >         >
> >         > This is a piece of testcode I have created:
> >         >
> >         >         check("tm_evevery",tm_evevery(4,3,&tmr_id),0);
> >         >         check("tm_cancel",tm_cancel(tmr_id),0);
> >         >         ev_rcvd = 0;
> >         >         ret = ev_receive(4,EV_ANY|EV_WAIT,10,&ev_rcvd);
> >         >         check("ev_receive",ret,ERR_TIMEOUT);
> >         >
> >         > I just start a periodic timer that expires every 3 ticks and
> >         at expiry
> >         > sends event 4 to my task.
> >
> >
> >         You test rather arms a timer for sending event_list=0x3 each 4
> >         ticks.
> >
> >         > I want to check the cancel of the timer, so I cancel it and
> >         I would
> >         > expect not to receive any event.
> >         >
> >         > What I observe is that this code is not working: I
> >         immediately receive
> >         > the event after starting the timer.
> >
> >
> >         Please try this test code as well:
> >
> >         #include <stdio.h>
> >         #include <unistd.h>
> >         #include <sys/types.h>
> >         #include <sys/mman.h>
> >         #include <psos+/psos.h>
> >
> >         void foo (u_long a0, u_long a1, u_long a2, u_long a3)
> >         {
> >                u_long ret, ev = 0, tmid;
> >
> >                printf("Started... (%lu, %lu, %lu, %lu)\n", a0, a1, a2,
> >         a3);
> >                ret = tm_evevery(4, 3, &tmid);
> >                printf("tm_evevery(4, 3, &tmid) => %lu\n", ret);
> >
> >                ret = tm_cancel(tmid);
> >                printf("tm_cancel(&tmid) => %lu\n", ret);
> >
> >                ret = ev_receive(4, EV_ANY|EV_WAIT, 10, &ev);
> >                printf("ev_receive(4, EV_ANY|EV_WAIT, 10, &ev) => %lu,
> >         ev=0x%lx\n", ret, ev);
> >         }
> >
> >         int main (int ac, char **av)
> >         {
> >                u_long ret, tid = 0, args[4];
> >
> >                mlockall(MCL_CURRENT | MCL_FUTURE);
> >
> >                ret = t_create("TEST", 1, 0, 0, 0, &tid);
> >                printf("t_create(tid=%lu) = %lu\n", tid, ret);
> >                args[0] = 1;
> >                args[1] = 2;
> >                args[2] = 3;
> >                args[3] = 4;
> >                ret = t_start(tid, 0, foo, args);
> >                printf("t_start(tid=%lu) = %lu\n", tid, ret);
> >
> >                return 0;
> >         }
> >
> >         > If I change the code like shown below (I added the
> >         ev_receive with the
> >         > NO_WAIT option after starting the timer), the code works
> >         fine.
> >         >
> >         >         check("tm_evevery",tm_evevery(4,3,&tmr_id),0);
> >         >         ret = ev_receive(4,EV_ANY|EV_NOWAIT,0,&ev_rcvd);
> >
> >
> >         Do you receive ERR_NOEVS as expected here?
> >
> >         >         check("tm_cancel",tm_cancel(tmr_id),0);
> >         >         ev_rcvd = 0;
> >         >         ret = ev_receive(4,EV_ANY|EV_WAIT,10,&ev_rcvd);
> >         >         check("ev_receive",ret,ERR_TIMEOUT);
> >         >
> >
> >
> >         > Now my question is: how do I investigate an issue like this?
> >         In other
> >         > words, which are the best tools since this code involves
> >         both user and
> >         > kernel space debugging.
> >         > Are there some trace tools available that are able to
> >         generate a kind
> >         > of sequence / trace of what is happing over time.
> >         >
> >         > I also have other issues that are not consistently
> >         reproducible. For
> >         > this kind of problems trace tools would also be useful.
> >         >
> >
> >
> >         If you want to validate the pSOS emulation core, the best tool
> >         is the
> >         simulator. Unfortunately, this tools still requires to be
> >         built with an
> >         antiquated C++ toolchain, so the only sane way to enable it
> >         nowadays is
> >         via qemu. You would need ~2 hours to set this up.
> >
> >         If you want to try this, I can help. Otherwise, other
> >         suggestions you
> >         already got on this list will do.
> >
> >         > Thanks
> >         > Ronny
> >         > _______________________________________________
> >         > Xenomai-help mailing list
> >         > [email protected]
> >         > https://mail.gna.org/listinfo/xenomai-help
> >
> >
> >         --
> >         Philippe.
> >
> >
> >
>
> --
> Philippe.
>
>
>
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help

Reply via email to