All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai] select() unblocks when no data to read()
@ 2017-07-13 16:26 George Broz
  2017-07-13 20:39 ` George Broz
  0 siblings, 1 reply; 4+ messages in thread
From: George Broz @ 2017-07-13 16:26 UTC (permalink / raw)
  To: xenomai

Hi -

I'm using the UDD driver on Xenomai 3.0.4 / Linux 3.18.20 on an ARM SoC.

I use select() to block on read events. The problem is select() unblocks
twice in response to one interrupt event. The corresponding read()
to the second erroneous unblocked select() then blocks until the next
interrupt arrives.

The psuedo-code in user-space looks like this:

  while (active)
  {
    FD_ZERO (&FileDescSet);
    FD_SET (FileDesc, &FileDescSet);

    /* block until interrupt or timeout occurs */
    IsInterruptPending = select ((FileDesc + 1), &FileDescSet, NULL,
NULL, &Timeout);

    /* check timeout (0) and error cases (-1) */
    ...

    /* otherwise, process */
    if (IsInterruptPending && FD_ISSET(FileDesc, &FileDescSet))
    {
      err = read (FileDesc, &u32EventCount, sizeof (u32EventCount));
      ...
    }
  }


I have added debug to the UDD driver to verify udd_notify_event() is called
exactly once per interrupt event, and that the ur->event is properly
incremented.

In udd_read_rt(), debug showing ur->event and context->event_count do what
they should be doing - returning data when they mismatch and then setting
one equal to the other, or blocking when they are equal. This function would
be fine if select were working properly.

(One thing to note is that when ur->event and context->event_count are equal,
it takes two iterations of the for (;;) loop to actually block on
rtdm_event_wait().)

I added debug to udd_select(), but it doesn't work as expected. I had hoped
to see debug emitted for each user-space call to select(), but it seems only
one call is made to udd_select() the first time through the loop.

In an unsuccessful workaround, I tried issuing rtdm_event_init() in an
ioctl() called just before unmasking interrupts for the next iteration
of the loop.

Is there a possible bug in the RTDM select() handling? Is there a patch
or additional debug someone could suggest? Any input greatly appreciated.


Regards,

--George Broz
Moog Industrial Group


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Xenomai] select() unblocks when no data to read()
  2017-07-13 16:26 [Xenomai] select() unblocks when no data to read() George Broz
@ 2017-07-13 20:39 ` George Broz
  2017-07-17 16:37   ` Philippe Gerum
  0 siblings, 1 reply; 4+ messages in thread
From: George Broz @ 2017-07-13 20:39 UTC (permalink / raw)
  To: xenomai

On 13 July 2017 at 09:26, George Broz <brozgeo@gmail.com> wrote:
> Hi -
>
> I'm using the UDD driver on Xenomai 3.0.4 / Linux 3.18.20 on an ARM SoC.
>
> I use select() to block on read events. The problem is select() unblocks
> twice in response to one interrupt event. The corresponding read()
> to the second erroneous unblocked select() then blocks until the next
> interrupt arrives.
>
> The psuedo-code in user-space looks like this:
>
>   while (active)
>   {
>     FD_ZERO (&FileDescSet);
>     FD_SET (FileDesc, &FileDescSet);
>
>     /* block until interrupt or timeout occurs */
>     IsInterruptPending = select ((FileDesc + 1), &FileDescSet, NULL,
> NULL, &Timeout);
>
>     /* check timeout (0) and error cases (-1) */
>     ...
>
>     /* otherwise, process */
>     if (IsInterruptPending && FD_ISSET(FileDesc, &FileDescSet))
>     {
>       err = read (FileDesc, &u32EventCount, sizeof (u32EventCount));
>       ...
>     }
>   }
>
>
> I have added debug to the UDD driver to verify udd_notify_event() is called
> exactly once per interrupt event, and that the ur->event is properly
> incremented.
>
> In udd_read_rt(), debug showing ur->event and context->event_count do what
> they should be doing - returning data when they mismatch and then setting
> one equal to the other, or blocking when they are equal. This function would
> be fine if select were working properly.
>
> (One thing to note is that when ur->event and context->event_count are equal,
> it takes two iterations of the for (;;) loop to actually block on
> rtdm_event_wait().)
>
> I added debug to udd_select(), but it doesn't work as expected. I had hoped
> to see debug emitted for each user-space call to select(), but it seems only
> one call is made to udd_select() the first time through the loop.
>
> In an unsuccessful workaround, I tried issuing rtdm_event_init() in an
> ioctl() called just before unmasking interrupts for the next iteration
> of the loop.

However, if I add:

   rtdm_event_clear(&ur->pulse);

just before the return statement (return ret ?: sizeof(count);) in
udd_read_rt(),
then things to seem to work properly - select() unblocks only when there
is something to read...

>
> Is there a possible bug in the RTDM select() handling? Is there a patch
> or additional debug someone could suggest? Any input greatly appreciated.
>
>
> Regards,
>
> --George Broz
> Moog Industrial Group


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Xenomai] select() unblocks when no data to read()
  2017-07-13 20:39 ` George Broz
@ 2017-07-17 16:37   ` Philippe Gerum
  2017-07-18  7:21     ` Philippe Gerum
  0 siblings, 1 reply; 4+ messages in thread
From: Philippe Gerum @ 2017-07-17 16:37 UTC (permalink / raw)
  To: George Broz, xenomai

On 07/13/2017 10:39 PM, George Broz wrote:
> On 13 July 2017 at 09:26, George Broz <brozgeo@gmail.com> wrote:
>> Hi -
>>
>> I'm using the UDD driver on Xenomai 3.0.4 / Linux 3.18.20 on an ARM SoC.
>>
>> I use select() to block on read events. The problem is select() unblocks
>> twice in response to one interrupt event. The corresponding read()
>> to the second erroneous unblocked select() then blocks until the next
>> interrupt arrives.
>>
>> The psuedo-code in user-space looks like this:
>>
>>   while (active)
>>   {
>>     FD_ZERO (&FileDescSet);
>>     FD_SET (FileDesc, &FileDescSet);
>>
>>     /* block until interrupt or timeout occurs */
>>     IsInterruptPending = select ((FileDesc + 1), &FileDescSet, NULL,
>> NULL, &Timeout);
>>
>>     /* check timeout (0) and error cases (-1) */
>>     ...
>>
>>     /* otherwise, process */
>>     if (IsInterruptPending && FD_ISSET(FileDesc, &FileDescSet))
>>     {
>>       err = read (FileDesc, &u32EventCount, sizeof (u32EventCount));
>>       ...
>>     }
>>   }
>>
>>
>> I have added debug to the UDD driver to verify udd_notify_event() is called
>> exactly once per interrupt event, and that the ur->event is properly
>> incremented.
>>
>> In udd_read_rt(), debug showing ur->event and context->event_count do what
>> they should be doing - returning data when they mismatch and then setting
>> one equal to the other, or blocking when they are equal. This function would
>> be fine if select were working properly.
>>
>> (One thing to note is that when ur->event and context->event_count are equal,
>> it takes two iterations of the for (;;) loop to actually block on
>> rtdm_event_wait().)
>>
>> I added debug to udd_select(), but it doesn't work as expected. I had hoped
>> to see debug emitted for each user-space call to select(), but it seems only
>> one call is made to udd_select() the first time through the loop.
>>
>> In an unsuccessful workaround, I tried issuing rtdm_event_init() in an
>> ioctl() called just before unmasking interrupts for the next iteration
>> of the loop.
> 
> However, if I add:
> 
>    rtdm_event_clear(&ur->pulse);
> 
> just before the return statement (return ret ?: sizeof(count);) in
> udd_read_rt(),
> then things to seem to work properly - select() unblocks only when there
> is something to read...
> 

The rtdm_event_select() interface is broken. The portion signaling the
state changes (e.g. IRQ pending <-> no IRQ pending) is simply missing...
I'll have a look, thanks.

For the time being, clearing the event manually will do the trick
although this may be racy.

-- 
Philippe.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Xenomai] select() unblocks when no data to read()
  2017-07-17 16:37   ` Philippe Gerum
@ 2017-07-18  7:21     ` Philippe Gerum
  0 siblings, 0 replies; 4+ messages in thread
From: Philippe Gerum @ 2017-07-18  7:21 UTC (permalink / raw)
  To: George Broz, xenomai

On 07/17/2017 06:37 PM, Philippe Gerum wrote:
> On 07/13/2017 10:39 PM, George Broz wrote:
>> On 13 July 2017 at 09:26, George Broz <brozgeo@gmail.com> wrote:
>>> Hi -
>>>
>>> I'm using the UDD driver on Xenomai 3.0.4 / Linux 3.18.20 on an ARM SoC.
>>>
>>> I use select() to block on read events. The problem is select() unblocks
>>> twice in response to one interrupt event. The corresponding read()
>>> to the second erroneous unblocked select() then blocks until the next
>>> interrupt arrives.
>>>
>>> The psuedo-code in user-space looks like this:
>>>
>>>   while (active)
>>>   {
>>>     FD_ZERO (&FileDescSet);
>>>     FD_SET (FileDesc, &FileDescSet);
>>>
>>>     /* block until interrupt or timeout occurs */
>>>     IsInterruptPending = select ((FileDesc + 1), &FileDescSet, NULL,
>>> NULL, &Timeout);
>>>
>>>     /* check timeout (0) and error cases (-1) */
>>>     ...
>>>
>>>     /* otherwise, process */
>>>     if (IsInterruptPending && FD_ISSET(FileDesc, &FileDescSet))
>>>     {
>>>       err = read (FileDesc, &u32EventCount, sizeof (u32EventCount));
>>>       ...
>>>     }
>>>   }
>>>
>>>
>>> I have added debug to the UDD driver to verify udd_notify_event() is called
>>> exactly once per interrupt event, and that the ur->event is properly
>>> incremented.
>>>
>>> In udd_read_rt(), debug showing ur->event and context->event_count do what
>>> they should be doing - returning data when they mismatch and then setting
>>> one equal to the other, or blocking when they are equal. This function would
>>> be fine if select were working properly.
>>>
>>> (One thing to note is that when ur->event and context->event_count are equal,
>>> it takes two iterations of the for (;;) loop to actually block on
>>> rtdm_event_wait().)
>>>
>>> I added debug to udd_select(), but it doesn't work as expected. I had hoped
>>> to see debug emitted for each user-space call to select(), but it seems only
>>> one call is made to udd_select() the first time through the loop.
>>>
>>> In an unsuccessful workaround, I tried issuing rtdm_event_init() in an
>>> ioctl() called just before unmasking interrupts for the next iteration
>>> of the loop.
>>
>> However, if I add:
>>
>>    rtdm_event_clear(&ur->pulse);
>>
>> just before the return statement (return ret ?: sizeof(count);) in
>> udd_read_rt(),
>> then things to seem to work properly - select() unblocks only when there
>> is something to read...
>>
> 
> The rtdm_event_select() interface is broken. The portion signaling the
> state changes (e.g. IRQ pending <-> no IRQ pending) is simply missing...

Nah, it's there. I was looking for the wrong pattern. Ok, on the todo list.

-- 
Philippe.


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-07-18  7:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-13 16:26 [Xenomai] select() unblocks when no data to read() George Broz
2017-07-13 20:39 ` George Broz
2017-07-17 16:37   ` Philippe Gerum
2017-07-18  7:21     ` Philippe Gerum

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.