All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai-help] Creation of a rt-queue from the user space
@ 2005-11-10 21:05 ROSSIER Daniel
  2005-11-11  9:30 ` [Xenomai-help] printk Ignacio García Pérez
  2005-11-11 14:08 ` [Xenomai-help] Creation of a rt-queue from the user space Jan Kiszka
  0 siblings, 2 replies; 53+ messages in thread
From: ROSSIER Daniel @ 2005-11-10 21:05 UTC (permalink / raw)
  To: xenomai


Hello everyone,

I've recently posted a message in this mailing list about an issue regarding the use of realtime queue in xenomai from the user space. 

I didn't make any significant progress regarding this issue. I've upgraded to linux 2.6.12; everything works in the user/kernel space except the queue. If I correctly understood, it's necessary to have a /dev/rtheap in order to set up a shared memory segment between user and kernel space. 
If this entry does not exist, we get an error at the queue creation time. 

I've observed that if I'm creating manually the entry in /dev, I get the same error and the entry disappears from /dev. Then, I've transfered the udev/rtheap.rules located in the xenomai/nucleus directory into /etc/udev/rules.d. But the system totally freezes after xeno-load.

I've put the segment of code (very simple) for the creation of a simple rt-queue.

----------------

int main(int argc, char *argv[]) {

  printf("Now starting: %s\n", argv[0]);

  /* Timer initialization */
  err = rt_timer_start(1000000);   /* So, one tick will be equal to 1 ms */
  if (err != 0) {
    printf("Error timer: %d\n", err);
    clean_exit(0);
  }

  /* Create the mailbox */
  err = rt_queue_create(&mailbox, "MAILBOX", 80, 1, Q_FIFO);
  if (err != 0) {
    printf("mbox creation failed: %d\n", err);
    clean_exit(0);
  }

------------

Thanks for any support.

Regards
Daniel


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

* [Xenomai-help] printk
  2005-11-10 21:05 [Xenomai-help] Creation of a rt-queue from the user space ROSSIER Daniel
@ 2005-11-11  9:30 ` Ignacio García Pérez
  2005-11-11 11:07   ` Dmitry Adamushko
                     ` (2 more replies)
  2005-11-11 14:08 ` [Xenomai-help] Creation of a rt-queue from the user space Jan Kiszka
  1 sibling, 3 replies; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-11  9:30 UTC (permalink / raw)
  To: xenomai

Hi,

I'm porting an app from RTAI to Xenomai, and when it came to the
rt_printk function, I had to replace it with plain printk (the
xnarch_log* functions all use printk).

What I want to know if:

1- Is totally safe to call the standard kernel printk function from a
real time task?

2- Even if it's safe, can it affect the performance of a real time task?
(or can it block under *any* conceivable condition?)

Thanks.

Nacho.




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

* Re: [Xenomai-help] printk
  2005-11-11  9:30 ` [Xenomai-help] printk Ignacio García Pérez
@ 2005-11-11 11:07   ` Dmitry Adamushko
  2005-11-14 10:52     ` Ignacio García Pérez
  2005-11-12 19:45   ` [Xenomai-help] printk Philippe Gerum
  2005-11-14 10:47   ` [Xenomai-help] Invalid characters in task's names Ignacio García Pérez
  2 siblings, 1 reply; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-11 11:07 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 1654 bytes --]


xenomai-help-bounces@domain.hid wrote on 11.11.2005 10:30:26:

> Hi,
>
> I'm porting an app from RTAI to Xenomai, and when it came to the
> rt_printk function, I had to replace it with plain printk (the
> xnarch_log* functions all use printk).
>
> What I want to know if:
>
> 1- Is totally safe to call the standard kernel printk function from a
> real time task?

Actually, the adeos/ipipe patches make some changes to the vanilla kernel's
printk() mechanism.

There are 2 possible modes of printk() being issued from the primary
domain.

1) asynchronous:

all data is written into the protected buffer and the __ipipe_printk_virq
virq is risen for the secondary domain. So the data will be printed out
when the linux gets control next time.

Although, here is, well, a tiny race because of the fact that the virq
handler doesn't lock a buffer-related data (like __ipipe_printk_fill) so a
loss of data may occur under some circumstances.

2) synchronous (IPIPE_SPRINTK_FLAG)

in this case, a normal linux vprintk() call is issued. Oops, this one, in
turn, calls spin_lock_irqsave(&logbuf_lock, flags); in real-time context
and that lock may be already held by a preempted non-rt task on the same
CPU.

Houston? :o)

>
> 2- Even if it's safe, can it affect the performance of a real time task?
> (or can it block under *any* conceivable condition?)

It gives some overhead since data must be copied to the buffer and at that
time the interrupts are off.
Blocked? No, if not taking into account a possible "hang up" with the
synchronous mode (ok, as always there is still a hope that I can be wrong
):)

>
> Thanks.
>
> Nacho.
>

---
Best regards,
Dmitry

[-- Attachment #2: Type: text/html, Size: 2159 bytes --]

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

* Re: [Xenomai-help] Creation of a rt-queue from the user space
  2005-11-10 21:05 [Xenomai-help] Creation of a rt-queue from the user space ROSSIER Daniel
  2005-11-11  9:30 ` [Xenomai-help] printk Ignacio García Pérez
@ 2005-11-11 14:08 ` Jan Kiszka
  1 sibling, 0 replies; 53+ messages in thread
From: Jan Kiszka @ 2005-11-11 14:08 UTC (permalink / raw)
  To: ROSSIER Daniel; +Cc: xenomai-help

[-- Attachment #1: Type: text/plain, Size: 1779 bytes --]

ROSSIER Daniel wrote:
> Hello everyone,
> 
> I've recently posted a message in this mailing list about an issue regarding the use of realtime queue in xenomai from the user space. 
> 
> I didn't make any significant progress regarding this issue. I've upgraded to linux 2.6.12; everything works in the user/kernel space except the queue. If I correctly understood, it's necessary to have a /dev/rtheap in order to set up a shared memory segment between user and kernel space. 
> If this entry does not exist, we get an error at the queue creation time. 
> 
> I've observed that if I'm creating manually the entry in /dev, I get the same error and the entry disappears from /dev. Then, I've transfered the udev/rtheap.rules located in the xenomai/nucleus directory into /etc/udev/rules.d. But the system totally freezes after xeno-load.
> 
> I've put the segment of code (very simple) for the creation of a simple rt-queue.
> 
> ----------------
> 
> int main(int argc, char *argv[]) {
> 
>   printf("Now starting: %s\n", argv[0]);
> 
>   /* Timer initialization */
>   err = rt_timer_start(1000000);   /* So, one tick will be equal to 1 ms */
>   if (err != 0) {
>     printf("Error timer: %d\n", err);
>     clean_exit(0);
>   }
> 
>   /* Create the mailbox */
>   err = rt_queue_create(&mailbox, "MAILBOX", 80, 1, Q_FIFO);
>   if (err != 0) {
>     printf("mbox creation failed: %d\n", err);
>     clean_exit(0);
>   }
> 
> ------------
> 
> Thanks for any support.
> 
> Regards
> Daniel
> 

Everything's fine here with your test on 2.6.13.4-ipipe-1.0.09 + Xenomai
SVN + /dev/rtheap. Moreover, I don't see a reason why your manually
created device node should disappear. Maybe your build is inconsistent
in some subtle way.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 250 bytes --]

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

* Re: [Xenomai-help] printk
  2005-11-11  9:30 ` [Xenomai-help] printk Ignacio García Pérez
  2005-11-11 11:07   ` Dmitry Adamushko
@ 2005-11-12 19:45   ` Philippe Gerum
  2005-11-14 10:47   ` [Xenomai-help] Invalid characters in task's names Ignacio García Pérez
  2 siblings, 0 replies; 53+ messages in thread
From: Philippe Gerum @ 2005-11-12 19:45 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

Ignacio García Pérez wrote:
> Hi,
> 
> I'm porting an app from RTAI to Xenomai, and when it came to the
> rt_printk function, I had to replace it with plain printk (the
> xnarch_log* functions all use printk).
> 
> What I want to know if:
> 
> 1- Is totally safe to call the standard kernel printk function from a
> real time task?
> 

Yes.

> 2- Even if it's safe, can it affect the performance of a real time task?
> (or can it block under *any* conceivable condition?)
>

No.

> Thanks.
> 
> Nacho.
> 
> 
> 
> _______________________________________________
> Xenomai-help mailing list
> Xenomai-help@domain.hid
> https://mail.gna.org/listinfo/xenomai-help
> 


-- 

Philippe.


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

* [Xenomai-help] Invalid characters in task's names
  2005-11-11  9:30 ` [Xenomai-help] printk Ignacio García Pérez
  2005-11-11 11:07   ` Dmitry Adamushko
  2005-11-12 19:45   ` [Xenomai-help] printk Philippe Gerum
@ 2005-11-14 10:47   ` Ignacio García Pérez
  2005-11-14 11:39     ` Philippe Gerum
  2 siblings, 1 reply; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-14 10:47 UTC (permalink / raw)
  To: xenomai

Hi,

I just noticed "/" is not a valid character for a task's name. Probably
something to do with the clever use that xeno makes of the /proc
filesystem. Anyway:

1- Are there any other "forbidden" characters?

2- Does this limitation apply to the other named objects?

3- Shouldn't those characters be internally escaped somehow to overcome
this limitation?

4- If (2) is not possible, shouldn't this limitation be mentioned in the
API documentation.

Thanks.


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

* Re: [Xenomai-help] printk
  2005-11-11 11:07   ` Dmitry Adamushko
@ 2005-11-14 10:52     ` Ignacio García Pérez
  2005-11-14 11:26       ` Philippe Gerum
  2005-11-14 12:15       ` [Xenomai-help] xn_pipe_create [minor] Ignacio García Pérez
  0 siblings, 2 replies; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-14 10:52 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: xenomai

Dmitry Adamushko wrote:

>
> xenomai-help-bounces@domain.hid wrote on 11.11.2005 10:30:26:
>
> > Hi,
> >
> > I'm porting an app from RTAI to Xenomai, and when it came to the
> > rt_printk function, I had to replace it with plain printk (the
> > xnarch_log* functions all use printk).
> >
> > What I want to know if:
> >
> > 1- Is totally safe to call the standard kernel printk function from a
> > real time task?
>
> Actually, the adeos/ipipe patches make some changes to the vanilla
> kernel's printk() mechanism.
>
> There are 2 possible modes of printk() being issued from the primary
> domain.
>
> 1) asynchronous:
>
> all data is written into the protected buffer and the
> __ipipe_printk_virq virq is risen for the secondary domain. So the
> data will be printed out when the linux gets control next time.
>
> Although, here is, well, a tiny race because of the fact that the virq
> handler doesn't lock a buffer-related data (like __ipipe_printk_fill)
> so a loss of data may occur under some circumstances.
>
> 2) synchronous (IPIPE_SPRINTK_FLAG)
>
> in this case, a normal linux vprintk() call is issued. Oops, this one,
> in turn, calls spin_lock_irqsave(&logbuf_lock, flags); in real-time
> context and that lock may be already held by a preempted non-rt task
> on the same CPU.
>
> Houston? :o)
>
(2) is unacceptable. Losing some data would be acceptable if it is
caused by too much printk output, but not because of a race condition.
This should be fixed. I guess a simple FIFO with proper locking should
be in place. printk would discard data only if there is no space left.

>
> >
> > 2- Even if it's safe, can it affect the performance of a real time task?
> > (or can it block under *any* conceivable condition?)
>
> It gives some overhead since data must be copied to the buffer and at
> that time the interrupts are off.
> Blocked? No, if not taking into account a possible "hang up" with the
> synchronous mode (ok, as always there is still a hope that I can be
> wrong ):)
>
If you are right, then it's unacceptable. An RT task would be blocked by
a non-RT task.

>
> >
> > Thanks.
> >
> > Nacho.
> >
>
> ---
> Best regards,
> Dmitry
>
>------------------------------------------------------------------------
>
>No virus found in this incoming message.
>Checked by AVG Free Edition.
>Version: 7.1.362 / Virus Database: 267.13.0/167 - Release Date: 11/11/2005
>  
>



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

* Re: [Xenomai-help] printk
  2005-11-14 10:52     ` Ignacio García Pérez
@ 2005-11-14 11:26       ` Philippe Gerum
  2005-11-14 12:03         ` Dmitry Adamushko
  2005-11-14 12:15       ` [Xenomai-help] xn_pipe_create [minor] Ignacio García Pérez
  1 sibling, 1 reply; 53+ messages in thread
From: Philippe Gerum @ 2005-11-14 11:26 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

Ignacio García Pérez wrote:
> Dmitry Adamushko wrote:
> 
> 
>>xenomai-help-bounces@domain.hid wrote on 11.11.2005 10:30:26:
>>
>>
>>>Hi,
>>>
>>>I'm porting an app from RTAI to Xenomai, and when it came to the
>>>rt_printk function, I had to replace it with plain printk (the
>>>xnarch_log* functions all use printk).
>>>
>>>What I want to know if:
>>>
>>>1- Is totally safe to call the standard kernel printk function from a
>>>real time task?
>>
>>Actually, the adeos/ipipe patches make some changes to the vanilla
>>kernel's printk() mechanism.
>>
>>There are 2 possible modes of printk() being issued from the primary
>>domain.
>>
>>1) asynchronous:
>>
>>all data is written into the protected buffer and the
>>__ipipe_printk_virq virq is risen for the secondary domain. So the
>>data will be printed out when the linux gets control next time.
>>
>>Although, here is, well, a tiny race because of the fact that the virq
>>handler doesn't lock a buffer-related data (like __ipipe_printk_fill)
>>so a loss of data may occur under some circumstances.
>>

Nope. __ipipe_printk_fill and friends are manipulated under hw irq spinlocking 
in printk(), and under Linux domain stalling protection in __ipipe_flush_printk 
since it's a virq handler, and finally, printk() cannot preempt 
__ipipe_flush_printk under normal operation mode (i.e. async mode). AFAICS, 
there's no race here.

>>2) synchronous (IPIPE_SPRINTK_FLAG)
>>
>>in this case, a normal linux vprintk() call is issued. Oops, this one,
>>in turn, calls spin_lock_irqsave(&logbuf_lock, flags); in real-time
>>context and that lock may be already held by a preempted non-rt task
>>on the same CPU.
>>
>>Houston? :o)
>>
> 
> (2) is unacceptable. Losing some data would be acceptable if it is
> caused by too much printk output, but not because of a race condition.
> This should be fixed. I guess a simple FIFO with proper locking should
> be in place. printk would discard data only if there is no space left.
> 
> 
>>>2- Even if it's safe, can it affect the performance of a real time task?
>>>(or can it block under *any* conceivable condition?)
>>
>>It gives some overhead since data must be copied to the buffer and at
>>that time the interrupts are off.
>>Blocked? No, if not taking into account a possible "hang up" with the
>>synchronous mode (ok, as always there is still a hope that I can be
>>wrong ):)
>>
> 
> If you are right, then it's unacceptable. An RT task would be blocked by
> a non-RT task.
> 

Please people, keep things simple and easy: synchronous printk mode is an 
_emergency_ configuration which is of no use under normal runtime conditions. It 
is only there as a desperate debugging help for Adeos/Xeno core development in 
order to force the printk output regardless of the current domain, so it might 
work, but it it doesn't and hits any of the obvious races that the asynchronous 
mode solves, well, nobody is going to complain because it's just a last resort 
bypass in order to get some ultimate traces before the box jumps out of the 
window anyway. IOW, if one keeps using the default and normal async printk mode 
which prevents domain clashes, everything will be fine.

Regarding the overhead induced by a temporary copy of the printk data, if one 
starts having problem with this, then the issue is first caused by spamming the 
kernel log with such amount of information. IOW, cure the real bug, not its 
consequences.

-- 

Philippe.


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

* Re: [Xenomai-help] Invalid characters in task's names
  2005-11-14 10:47   ` [Xenomai-help] Invalid characters in task's names Ignacio García Pérez
@ 2005-11-14 11:39     ` Philippe Gerum
  0 siblings, 0 replies; 53+ messages in thread
From: Philippe Gerum @ 2005-11-14 11:39 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

Ignacio García Pérez wrote:
> Hi,
> 
> I just noticed "/" is not a valid character for a task's name. Probably
> something to do with the clever use that xeno makes of the /proc
> filesystem.:
>

It's strictly /procfs related, yes.

> 1- Are there any other "forbidden" characters?

No.

> 
> 2- Does this limitation apply to the other named objects?
> 

Yes. Everything that goes through the registry support.

> 3- Shouldn't those characters be internally escaped somehow to overcome
> this limitation?
> 

At some point in time, especially the day we add distributed computing 
facilities, we could find an interesting use of this single reserved character 
to express object hierarchies too.

> 4- If (2) is not possible, shouldn't this limitation be mentioned in the
> API documentation.
> 

It is actually. Excerpt from rt_registry_enter()'s documentation:

  * - -EINVAL is returned if @a key or @a objaddr are NULL, or if @a
  * key constains an invalid '/' character.

The connection between any object creation routine and the registry is clearly 
stated throughout the documentation, but the indirect use of rt_registry_enter 
might not be explicitely mentioned though.

> Thanks.
> 
> _______________________________________________
> Xenomai-help mailing list
> Xenomai-help@domain.hid
> https://mail.gna.org/listinfo/xenomai-help
> 


-- 

Philippe.


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

* Re: [Xenomai-help] printk
  2005-11-14 11:26       ` Philippe Gerum
@ 2005-11-14 12:03         ` Dmitry Adamushko
  2005-11-14 13:22           ` Philippe Gerum
  0 siblings, 1 reply; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-14 12:03 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 1577 bytes --]


Philippe Gerum <rpm@xenomai.org> wrote on 14.11.2005 12:26:08:

> >>
> >>Although, here is, well, a tiny race because of the fact that the virq
> >>handler doesn't lock a buffer-related data (like __ipipe_printk_fill)
> >>so a loss of data may occur under some circumstances.
> >>
>
> Nope. __ipipe_printk_fill and friends are manipulated under hw irq
> spinlocking
> in printk(), and under Linux domain stalling protection in
> __ipipe_flush_printk
> since it's a virq handler,

So what prevents some activity from the primary domain from preempting
__ipipe_flush_printk() and calling printk() when _only_ the Linux domain is
stalled?

let's say at the (*) point

void __ipipe_flush_printk (unsigned virq)
{
       char *p = __ipipe_printk_buf;
       int out = 0, len;

       clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);

       while (out < __ipipe_printk_fill) {
               len = strlen(p) + 1;
               printk("%s",p);
               p += len;
               out += len;
       }
      (*)   <---------------------------- preempted
       __ipipe_printk_fill = 0;
}

When linux gets controll back the virq continues its execution and sets
__ipipe_printk_fill up to 0.

This cannot happen only if virqs are manipulated with the primary domain
being stalled as well. But you told "and under __Linux domain___ stalling
protection in __ipipe_flush_printk since it's a virq handler".


> and finally, printk() cannot preempt
> __ipipe_flush_printk under normal operation mode (i.e. async mode).
AFAICS,
> there's no race here.


---
Best regards,
Dmitry

[-- Attachment #2: Type: text/html, Size: 2348 bytes --]

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

* [Xenomai-help] xn_pipe_create [minor]
  2005-11-14 10:52     ` Ignacio García Pérez
  2005-11-14 11:26       ` Philippe Gerum
@ 2005-11-14 12:15       ` Ignacio García Pérez
  2005-11-14 13:53         ` Dmitry Adamushko
  1 sibling, 1 reply; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-14 12:15 UTC (permalink / raw)
  To: xenomai

Hi,

The registry system is great, allows to forget about agreeing about an
arbitrary minor number for pipes. But as far as I ca see, you still have
to pass an unique "minor" number to rt_pipe_create.

What if you have several rt modules?... you must make sure you assign
different minor numbers to each pipe!.

Wouldn't be useful to have a way to let the rt_pipe_create decide which
minor to use? (a free one, of course)

Nacho.




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

* Re: [Xenomai-help] printk
  2005-11-14 12:03         ` Dmitry Adamushko
@ 2005-11-14 13:22           ` Philippe Gerum
  2005-11-14 13:47             ` Philippe Gerum
  0 siblings, 1 reply; 53+ messages in thread
From: Philippe Gerum @ 2005-11-14 13:22 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: xenomai

Dmitry Adamushko wrote:
> Philippe Gerum <rpm@xenomai.org> wrote on 14.11.2005 12:26:08:
> 
>  > >>
>  > >>Although, here is, well, a tiny race because of the fact that the virq
>  > >>handler doesn't lock a buffer-related data (like __ipipe_printk_fill)
>  > >>so a loss of data may occur under some circumstances.
>  > >>
>  >
>  > Nope. __ipipe_printk_fill and friends are manipulated under hw irq
>  > spinlocking
>  > in printk(), and under Linux domain stalling protection in
>  > __ipipe_flush_printk
>  > since it's a virq handler,
> 
> So what prevents some activity from the primary domain from preempting 
> __ipipe_flush_printk() and calling printk() when _only_ the Linux domain 
> is stalled?

This cannot happen in async mode, since the output would be buffered and 
printk() never called on behalf of the preempted handler.

> 
> let's say at the (*) point
> 
> void __ipipe_flush_printk (unsigned virq)
> {
>       char *p = __ipipe_printk_buf;
>       int out = 0, len;
> 
>       clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);
> 
>       while (out < __ipipe_printk_fill) {
>               len = strlen(p) + 1;
>               printk("%s",p);
>               p += len;
>               out += len;
>       }
> (*) <---------------------------- preempted
>       __ipipe_printk_fill = 0;
> }
> 
> When linux gets controll back the virq continues its execution and sets 
> __ipipe_printk_fill up to 0.
> 
> This cannot happen only if virqs are manipulated with the primary domain 
> being stalled as well. But you told "and under __Linux domain___ 
> stalling protection in __ipipe_flush_printk since it's a virq handler".
> 
> 
>  > and finally, printk() cannot preempt
>  > __ipipe_flush_printk under normal operation mode (i.e. async mode). 
> AFAICS,
>  > there's no race here.
> 
> 
> ---
> Best regards,
> Dmitry
> 


-- 

Philippe.


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

* Re: [Xenomai-help] printk
  2005-11-14 13:22           ` Philippe Gerum
@ 2005-11-14 13:47             ` Philippe Gerum
  2005-11-14 14:50               ` [Xenomai-core] " Dmitry Adamushko
  0 siblings, 1 reply; 53+ messages in thread
From: Philippe Gerum @ 2005-11-14 13:47 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai

Philippe Gerum wrote:
> Dmitry Adamushko wrote:
> 
>> Philippe Gerum <rpm@xenomai.org> wrote on 14.11.2005 12:26:08:
>>
>>  > >>
>>  > >>Although, here is, well, a tiny race because of the fact that the 
>> virq
>>  > >>handler doesn't lock a buffer-related data (like 
>> __ipipe_printk_fill)
>>  > >>so a loss of data may occur under some circumstances.
>>  > >>
>>  >
>>  > Nope. __ipipe_printk_fill and friends are manipulated under hw irq
>>  > spinlocking
>>  > in printk(), and under Linux domain stalling protection in
>>  > __ipipe_flush_printk
>>  > since it's a virq handler,
>>
>> So what prevents some activity from the primary domain from preempting 
>> __ipipe_flush_printk() and calling printk() when _only_ the Linux 
>> domain is stalled?
> 
> 
> This cannot happen in async mode, since the output would be buffered and 
> printk() never called on behalf of the preempted handler.
> 
>>
>> let's say at the (*) point
>>
>> void __ipipe_flush_printk (unsigned virq)
>> {
>>       char *p = __ipipe_printk_buf;
>>       int out = 0, len;
>>
>>       clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);
>>
>>       while (out < __ipipe_printk_fill) {
>>               len = strlen(p) + 1;
>>               printk("%s",p);
>>               p += len;
>>               out += len;
>>       }
>> (*) <---------------------------- preempted
>>       __ipipe_printk_fill = 0;
>> }
>>
>> When linux gets controll back the virq continues its execution and 
>> sets __ipipe_printk_fill up to 0.
>>
>> This cannot happen only if virqs are manipulated with the primary 
>> domain being stalled as well. But you told "and under __Linux 
>> domain___ stalling protection in __ipipe_flush_printk since it's a 
>> virq handler".
>>
>>
>>  > and finally, printk() cannot preempt
>>  > __ipipe_flush_printk under normal operation mode (i.e. async mode). 
>> AFAICS,
>>  > there's no race here.

Mea culpa, Dmitry is right, in the above situation he depicted, we could drop a 
portion of the output buffer. A way to fix this would be to hw lock a test and 
decrement section of __ipipe_printk_fill in the flush handler.

-- 

Philippe.


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

* Re: [Xenomai-help] xn_pipe_create [minor]
  2005-11-14 12:15       ` [Xenomai-help] xn_pipe_create [minor] Ignacio García Pérez
@ 2005-11-14 13:53         ` Dmitry Adamushko
  2005-11-14 16:28           ` Ignacio García Pérez
  0 siblings, 1 reply; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-14 13:53 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 1269 bytes --]


xenomai-help-bounces@domain.hid wrote on 14.11.2005 13:15:07:

> Hi,
>
> The registry system is great, allows to forget about agreeing about an
> arbitrary minor number for pipes. But as far as I ca see, you still have
> to pass an unique "minor" number to rt_pipe_create.
>
> What if you have several rt modules?... you must make sure you assign
> different minor numbers to each pipe!.
>
> Wouldn't be useful to have a way to let the rt_pipe_create decide which
> minor to use? (a free one, of course)

It can be done and that would work if both sides of the communication
channel are real-time threads so a rt_pipe_create/bind() pair may be used
to establish a connection.

But what should be done if another side is a linux task and uses a mere
open() call?

Currently, a naming convention is a "/dev/rtpN", N - is a minor being used
by rt_pipe_create() and both sides of the channel must be aware of it.

Moreover, a client side of the connection may be open even in case there is
no server side yet (the one that calls rt_pipe_create) at the mement. In
that case, the client is blocked in open().

So the only convention between both sides can be a minor number +
pre-created /dev/rtp[0, OPT_PIPE_NRDEV] character devices.

>
> Nacho.
>

---
Best regards,
Dmitry

[-- Attachment #2: Type: text/html, Size: 1580 bytes --]

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

* [Xenomai-core] Re: [Xenomai-help] printk
  2005-11-14 13:47             ` Philippe Gerum
@ 2005-11-14 14:50               ` Dmitry Adamushko
  2005-11-14 15:56                 ` [Xenomai-core] rt_pipe_* usage Ignacio García Pérez
  2005-11-15  9:38                 ` [Xenomai-core] Re: [Xenomai-help] printk Philippe Gerum
  0 siblings, 2 replies; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-14 14:50 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai, xenomai

[-- Attachment #1: Type: text/plain, Size: 3426 bytes --]


> > ...
> >
> > This cannot happen in async mode, since the output would be buffered
and
> > printk() never called on behalf of the preempted handler.
> >
> >>
> >> let's say at the (*) point
> >>
> >> void __ipipe_flush_printk (unsigned virq)
> >> {
> >>       char *p = __ipipe_printk_buf;
> >>       int out = 0, len;
> >>
> >>       clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);
> >>
> >>       while (out < __ipipe_printk_fill) {
> >>               len = strlen(p) + 1;
> >>               printk("%s",p);
> >>               p += len;
> >>               out += len;
> >>       }
> >> (*) <---------------------------- preempted
> >>       __ipipe_printk_fill = 0;
> >> }
> >>
> >> When linux gets controll back the virq continues its execution and
> >> sets __ipipe_printk_fill up to 0.
> >>
> >> This cannot happen only if virqs are manipulated with the primary
> >> domain being stalled as well. But you told "and under __Linux
> >> domain___ stalling protection in __ipipe_flush_printk since it's a
> >> virq handler".
> >>
> >>
> >>  > and finally, printk() cannot preempt
> >>  > __ipipe_flush_printk under normal operation mode (i.e. async mode).

> >> AFAICS,
> >>  > there's no race here.
>
> Mea culpa, Dmitry is right, in the above situation he depicted, we
> could drop a
> portion of the output buffer. A way to fix this would be to hw lock
> a test and
> decrement section of __ipipe_printk_fill in the flush handler.
>

Something like that (just a draft) would work probably but I suppose
something a bit more graceful would be implemented. Actually, with a small
optimization of IPIPE_PRINTK_FLAG.

void __ipipe_flush_printk (unsigned virq)
{
       char *p = __ipipe_printk_buf;
-       int out = 0, len;
+       int out = 0, len, used;

...
-       clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);
...

+ spin_lock_irqsave_hw(&__ipipe_printk_lock,flags);
+ used = __ipipe_printk_fill;
+ spin_unlock_irqrestore_hw(&__ipipe_printk_lock,flags);

+ oncemore:

       while (out < used) {
               len = strlen(p) + 1;
               printk("%s",p);
               p += len;
               out += len;
       }

+ spin_lock_irqsave_hw(&__ipipe_printk_lock,flags);
+ if (__ipipe_printk_fill == used)
+     {
-       __ipipe_printk_fill = 0;

+     used = __ipipe_printk_fill = 0;

+     // when everything is done
+      clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);

+     }
+ else
+     used = __ipipe_printk_fill;
+ spin_unlock_irqrestore_hw(&__ipipe_printk_lock,flags);

+ if (used)
+     goto oncemore;

...
}

and

asmlinkage int printk(const char *fmt, ...)
{
+      int virq_is_active;
...

       spin_lock_irqsave_hw(&__ipipe_printk_lock,flags);

       fbytes = __LOG_BUF_LEN - __ipipe_printk_fill;

       if (fbytes > 1) {
               r = vscnprintf(__ipipe_printk_buf + __ipipe_printk_fill,
                              fbytes, fmt, args) + 1; /* account for the
null byte */
               __ipipe_printk_fill += r;
       } else
               r = 0;

+      virq_is_active =
test_and_set_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);

       spin_unlock_irqrestore_hw(&__ipipe_printk_lock,flags);

-      if (!test_and_set_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags))
+      if (!virq_is_active)
               ipipe_trigger_irq(__ipipe_printk_virq);
out:
       va_end(args);

       return r;
}

> --
>
> Philippe.

---
Best regards,
Dmitry

[-- Attachment #2: Type: text/html, Size: 5816 bytes --]

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

* [Xenomai-core] rt_pipe_* usage
  2005-11-14 14:50               ` [Xenomai-core] " Dmitry Adamushko
@ 2005-11-14 15:56                 ` Ignacio García Pérez
  2005-11-14 16:15                   ` [Xenomai-core] More on rt pipes usage Ignacio García Pérez
  2005-11-14 16:23                   ` [Xenomai-core] rt_pipe_* usage Dmitry Adamushko
  2005-11-15  9:38                 ` [Xenomai-core] Re: [Xenomai-help] printk Philippe Gerum
  1 sibling, 2 replies; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-14 15:56 UTC (permalink / raw)
  To: xenomai

Hi,

I'm having now my first contact with the pipe framework, an have some
comments about it that might be of interest to the core developers:

While the documentation is overall *great*, I fould it a bit lacking
regarding the pipes. Would be good to have some examples of general usage.

As far as I can tell, there is no mention of the usage of P_MSGPTR and
P_MSGSIZE. I had to learn about them in the headers.

At first sight, the rt_pipe_send call is confusing: why should I pass
the data size since it is supposed to be embedded in the RT_PIPE_MSG
structure?.

This is what I first did:

RT_PIPE_MSG *m = rt_pipe_alloc(sizeof(mystruct));
P_MSGPTR(m) = &mystruct;
P_MSGSIZE(m) = sizeof(mystruct)
rt_pipe_send(&mypipe, m, sizeof(mystruct), P_NORMAL);

Which is obviously wrong. Please correct me if I'm wrong:

P_MSGPTR and P_MSGSIZE are intended not to be used as an lvalue (is
there a way to define these macros to generate a compile error if they
are?).

So, the correct way would be something like this (again, correct me if
I'm wrong)::

RT_PIPE_MSG *m = rt_pipe_alloc(sizeof(mystruct_t));
mystruct_t *p = (mystruct_t *)P_MSGPTR(m);
p->whatever1 = X;
p->whatever2 = X;
rt_pipe_send(&mypipe, m, sizeof(mystruct_t), P_NORMAL);

If this is correct, why do I have to specify the size of mystruct_t
*twice*. Can't it be initialized by rt_pipe_alloc ?.

Nacho.











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

* [Xenomai-core] More on rt pipes usage
  2005-11-14 15:56                 ` [Xenomai-core] rt_pipe_* usage Ignacio García Pérez
@ 2005-11-14 16:15                   ` Ignacio García Pérez
  2005-11-15 13:24                     ` Philippe Gerum
  2005-11-14 16:23                   ` [Xenomai-core] rt_pipe_* usage Dmitry Adamushko
  1 sibling, 1 reply; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-14 16:15 UTC (permalink / raw)
  To: xenomai

Hi,

Suppose I have a kernel rt task that samples data at a certain rate and
writes it as messages into a rt pipe, from which it is read by a user
space non rt program.

I want to limit the number of messages that are put into the pipe,
because otherwise if the user space program dies, it will grow endlessly
till it exausts the rt heap.

What I want to do is to have a pipe that can hold a limited number of
messages such that rt_pipe_write will fail if it is full.

Is there a way to know how many messages are there in the pipe?

Even if there is a way, to prevent a (harmless) race condition, I would
need to lock the pipe between checking the number of messages and
calling rt_pipe_write. As far as I know, pipe locking belongs to the
nucleus and I'd like to stay in the native skin as much as possible.

Another method would be to count how many messages I write, but then I'd
need some hook that notifies me when the user space program reads a
message so I can decrement the count.

Any ideas?

Nacho.


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

* Re: [Xenomai-core] rt_pipe_* usage
  2005-11-14 15:56                 ` [Xenomai-core] rt_pipe_* usage Ignacio García Pérez
  2005-11-14 16:15                   ` [Xenomai-core] More on rt pipes usage Ignacio García Pérez
@ 2005-11-14 16:23                   ` Dmitry Adamushko
  2005-11-14 16:36                     ` Ignacio García Pérez
  1 sibling, 1 reply; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-14 16:23 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 2425 bytes --]


xenomai-core-bounces@domain.hid wrote on 14.11.2005 16:56:01:

> Hi,
>
> I'm having now my first contact with the pipe framework, an have some
> comments about it that might be of interest to the core developers:
>
> While the documentation is overall *great*, I fould it a bit lacking
> regarding the pipes. Would be good to have some examples of general
usage.

You may take a look at testsuite/klatency example that uses a pipe for rt
kernel-mode task ---> normal linux task communication.


>
> As far as I can tell, there is no mention of the usage of P_MSGPTR and
> P_MSGSIZE. I had to learn about them in the headers.
>
> At first sight, the rt_pipe_send call is confusing: why should I pass
> the data size since it is supposed to be embedded in the RT_PIPE_MSG
> structure?.
>
> This is what I first did:
>
> RT_PIPE_MSG *m = rt_pipe_alloc(sizeof(mystruct));
> P_MSGPTR(m) = &mystruct;
> P_MSGSIZE(m) = sizeof(mystruct)
> rt_pipe_send(&mypipe, m, sizeof(mystruct), P_NORMAL);


rt_pipe_write()
{
...
      msg = rt_pipe_alloc(size);

      if (!msg)
        return -ENOMEM;

      memcpy(P_MSGPTR(msg),buf,size);           <---- copying, not storing
a pointer like you did

      nbytes = rt_pipe_send(pipe,msg,size,mode);
...

Actually, if you have already a buffer filled with data, you may directly
use a rt_pipe_write() call.

>
> Which is obviously wrong. Please correct me if I'm wrong:
>
> P_MSGPTR and P_MSGSIZE are intended not to be used as an lvalue (is
> there a way to define these macros to generate a compile error if they
> are?).
>
> So, the correct way would be something like this (again, correct me if
> I'm wrong)::
>
> RT_PIPE_MSG *m = rt_pipe_alloc(sizeof(mystruct_t));
> mystruct_t *p = (mystruct_t *)P_MSGPTR(m);
> p->whatever1 = X;
> p->whatever2 = X;
> rt_pipe_send(&mypipe, m, sizeof(mystruct_t), P_NORMAL);
>
> If this is correct, why do I have to specify the size of mystruct_t
> *twice*. Can't it be initialized by rt_pipe_alloc ?.

It's initialized actually (*).

RT_PIPE_MSG *rt_pipe_alloc (size_t size)

{
    RT_PIPE_MSG *msg = (RT_PIPE_MSG *)xnheap_alloc(__pipe_heap,size +
sizeof(RT_PIPE_MSG));

    if (msg)
        {
        inith(&msg->link);
        msg->size = size;     <--- (*)
        }

    return msg;
}

Please take a look at testsuite/klatency/latency_module.c : latency() for a
correct use of the rt_pipe_alloc/send() calls.


>
> Nacho.
>

---
Best regards,
Dmitry

[-- Attachment #2: Type: text/html, Size: 3405 bytes --]

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

* Re: [Xenomai-help] xn_pipe_create [minor]
  2005-11-14 13:53         ` Dmitry Adamushko
@ 2005-11-14 16:28           ` Ignacio García Pérez
  2005-11-14 16:29             ` Philippe Gerum
  2005-11-14 16:40             ` [Xenomai-help] xn_pipe_create [minor] Dmitry Adamushko
  0 siblings, 2 replies; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-14 16:28 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: xenomai

Dmitry Adamushko wrote:

> xenomai-help-bounces@domain.hid wrote on 14.11.2005 13:15:07:
>
> > Hi,
> >
> > The registry system is great, allows to forget about agreeing about an
> > arbitrary minor number for pipes. But as far as I ca see, you still have
> > to pass an unique "minor" number to rt_pipe_create.
> >
> > What if you have several rt modules?... you must make sure you assign
> > different minor numbers to each pipe!.
> >
> > Wouldn't be useful to have a way to let the rt_pipe_create decide which
> > minor to use? (a free one, of course)
>
> It can be done and that would work if both sides of the communication
> channel are real-time threads so a rt_pipe_create/bind() pair may be
> used to establish a connection.
>
> But what should be done if another side is a linux task and uses a
> mere open() call?
>
> Currently, a naming convention is a "/dev/rtpN", N - is a minor being
> used by rt_pipe_create() and both sides of the channel must be aware
> of it.
>
> Moreover, a client side of the connection may be open even in case
> there is no server side yet (the one that calls rt_pipe_create) at the
> mement. In that case, the client is blocked in open().
>
> So the only convention between both sides can be a minor number +
> pre-created /dev/rtp[0, OPT_PIPE_NRDEV] character devices.
>
Um... I think you are wrong. When the rt task creates a pipe, a symbolik
link appears at /proc/xenomai/registry/pipes. Its name is the fifo name,
and points to the /dev/rtpN device. That's what I was talking about when
I said "clever procfs usage of xenomai".

Using this scheme, user mode programs just need to open()
/proc/xenomai/registry/pipes/whatever to access a named pipe, without
having to know the minor number.

Under these circumstances, it would be *very* useful to have
rt_pipe_create choose an unused minor automagically (for example passing
-1 as the minor).

Currently, I'm emulating this by calling rt_pipe_create for minor =
0,1,2... until it succeeds or returns any error different than -EBUSY.

Nacho.


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

* Re: [Xenomai-help] xn_pipe_create [minor]
  2005-11-14 16:28           ` Ignacio García Pérez
@ 2005-11-14 16:29             ` Philippe Gerum
  2005-11-14 16:41               ` Ignacio García Pérez
  2005-11-14 16:40             ` [Xenomai-help] xn_pipe_create [minor] Dmitry Adamushko
  1 sibling, 1 reply; 53+ messages in thread
From: Philippe Gerum @ 2005-11-14 16:29 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

Ignacio García Pérez wrote:
> Dmitry Adamushko wrote:
> 
> 
>>xenomai-help-bounces@domain.hid wrote on 14.11.2005 13:15:07:
>>
>>
>>>Hi,
>>>
>>>The registry system is great, allows to forget about agreeing about an
>>>arbitrary minor number for pipes. But as far as I ca see, you still have
>>>to pass an unique "minor" number to rt_pipe_create.
>>>
>>>What if you have several rt modules?... you must make sure you assign
>>>different minor numbers to each pipe!.
>>>
>>>Wouldn't be useful to have a way to let the rt_pipe_create decide which
>>>minor to use? (a free one, of course)
>>
>>It can be done and that would work if both sides of the communication
>>channel are real-time threads so a rt_pipe_create/bind() pair may be
>>used to establish a connection.
>>
>>But what should be done if another side is a linux task and uses a
>>mere open() call?
>>
>>Currently, a naming convention is a "/dev/rtpN", N - is a minor being
>>used by rt_pipe_create() and both sides of the channel must be aware
>>of it.
>>
>>Moreover, a client side of the connection may be open even in case
>>there is no server side yet (the one that calls rt_pipe_create) at the
>>mement. In that case, the client is blocked in open().
>>
>>So the only convention between both sides can be a minor number +
>>pre-created /dev/rtp[0, OPT_PIPE_NRDEV] character devices.
>>
> 
> Um... I think you are wrong. When the rt task creates a pipe, a symbolik
> link appears at /proc/xenomai/registry/pipes. Its name is the fifo name,
> and points to the /dev/rtpN device. That's what I was talking about when
> I said "clever procfs usage of xenomai".
> 
> Using this scheme, user mode programs just need to open()
> /proc/xenomai/registry/pipes/whatever to access a named pipe, without
> having to know the minor number.
> 
> Under these circumstances, it would be *very* useful to have
> rt_pipe_create choose an unused minor automagically (for example passing
> -1 as the minor).
>

Sounds reasonable.

> Currently, I'm emulating this by calling rt_pipe_create for minor =
> 0,1,2... until it succeeds or returns any error different than -EBUSY.
> 
> Nacho.
> 
> _______________________________________________
> Xenomai-help mailing list
> Xenomai-help@domain.hid
> https://mail.gna.org/listinfo/xenomai-help
> 


-- 

Philippe.


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

* Re: [Xenomai-core] rt_pipe_* usage
  2005-11-14 16:23                   ` [Xenomai-core] rt_pipe_* usage Dmitry Adamushko
@ 2005-11-14 16:36                     ` Ignacio García Pérez
  2005-11-15 12:41                       ` [Xenomai-core] Web site error (API doc search) Ignacio García Pérez
  2005-11-15 13:16                       ` [Xenomai-core] rt_pipe_* usage Philippe Gerum
  0 siblings, 2 replies; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-14 16:36 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: xenomai


> >
> > RT_PIPE_MSG *m = rt_pipe_alloc(sizeof(mystruct_t));
> > mystruct_t *p = (mystruct_t *)P_MSGPTR(m);
> > p->whatever1 = X;
> > p->whatever2 = X;
> > rt_pipe_send(&mypipe, m, sizeof(mystruct_t), P_NORMAL);
> >
> > If this is correct, why do I have to specify the size of mystruct_t
> > *twice*. Can't it be initialized by rt_pipe_alloc ?.
>
> It's initialized actually (*).
>
So, what's the sense of having to specify it again whet calling
rt_pipe_send ?




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

* Re: [Xenomai-help] xn_pipe_create [minor]
  2005-11-14 16:28           ` Ignacio García Pérez
  2005-11-14 16:29             ` Philippe Gerum
@ 2005-11-14 16:40             ` Dmitry Adamushko
  1 sibling, 0 replies; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-14 16:40 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 3103 bytes --]



Ignacio García Pérez <iggarpe@domain.hid> wrote on 14.11.2005 17:28:24:

> Dmitry Adamushko wrote:
>
> > xenomai-help-bounces@domain.hid wrote on 14.11.2005 13:15:07:
> >
> > > Hi,
> > >
> > > The registry system is great, allows to forget about agreeing about
an
> > > arbitrary minor number for pipes. But as far as I ca see, you still
have
> > > to pass an unique "minor" number to rt_pipe_create.
> > >
> > > What if you have several rt modules?... you must make sure you assign
> > > different minor numbers to each pipe!.
> > >
> > > Wouldn't be useful to have a way to let the rt_pipe_create decide
which
> > > minor to use? (a free one, of course)
> >
> > It can be done and that would work if both sides of the communication
> > channel are real-time threads so a rt_pipe_create/bind() pair may be
> > used to establish a connection.
> >
> > But what should be done if another side is a linux task and uses a
> > mere open() call?
> >
> > Currently, a naming convention is a "/dev/rtpN", N - is a minor being
> > used by rt_pipe_create() and both sides of the channel must be aware
> > of it.
> >
> > Moreover, a client side of the connection may be open even in case
> > there is no server side yet (the one that calls rt_pipe_create) at the
> > mement. In that case, the client is blocked in open().
> >
> > So the only convention between both sides can be a minor number +
> > pre-created /dev/rtp[0, OPT_PIPE_NRDEV] character devices.
> >
> Um... I think you are wrong. When the rt task creates a pipe, a symbolik
> link appears at /proc/xenomai/registry/pipes. Its name is the fifo name,
> and points to the /dev/rtpN device. That's what I was talking about when
> I said "clever procfs usage of xenomai".
>
> Using this scheme, user mode programs just need to open()
> /proc/xenomai/registry/pipes/whatever to access a named pipe, without
> having to know the minor number.
>
> Under these circumstances, it would be *very* useful to have
> rt_pipe_create choose an unused minor automagically (for example passing
> -1 as the minor).
>
> Currently, I'm emulating this by calling rt_pipe_create for minor =
> 0,1,2... until it succeeds or returns any error different than -EBUSY.
>

Ok, I have missed that point. But one more thing I have pointed out before
remains.

Currently it's possible to have a client blocked in open(/dev/rtpN, flags)
waiting for a pipe to be created (if flags does contain O_NONBLOCK). And it
can be done only through /dev/rtpN since there is still nothing at
/proc/xenomai/registry/pipe/ (there is no pipe object yet created by the
"server" side).

Does anybody need that? me, no at the moment.

Ok, we can keep actually this functionality as well but just extend the
rt_pipe_create() interface to

rt_pipe_create (&pipe, whatever_name, PIPE_MINOR_AUTO)

so in that case a minor value will be "auto-generated" without a need to
bother a user. And the old interface is still can be used.

Technically, nothing difficult to implement that.


> Nacho.

---
Best regards,
Dmitry

[-- Attachment #2: Type: text/html, Size: 3901 bytes --]

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

* Re: [Xenomai-help] xn_pipe_create [minor]
  2005-11-14 16:29             ` Philippe Gerum
@ 2005-11-14 16:41               ` Ignacio García Pérez
  2005-11-14 16:52                 ` Dmitry Adamushko
  0 siblings, 1 reply; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-14 16:41 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai


>> Using this scheme, user mode programs just need to open()
>> /proc/xenomai/registry/pipes/whatever to access a named pipe, without
>> having to know the minor number.
>>
>> Under these circumstances, it would be *very* useful to have
>> rt_pipe_create choose an unused minor automagically (for example passing
>> -1 as the minor).
>>
>
> Sounds reasonable.

On the heels of our abs/rel discussion, I suggest to use a #define
istead of -1

Will you implement it, or should I give a try?

Nacho.



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

* Re: [Xenomai-help] xn_pipe_create [minor]
  2005-11-14 16:41               ` Ignacio García Pérez
@ 2005-11-14 16:52                 ` Dmitry Adamushko
  2005-11-14 17:38                   ` Philippe Gerum
  2005-11-14 18:03                   ` [Xenomai-help] Strange pipe behaviour Ignacio García Pérez
  0 siblings, 2 replies; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-14 16:52 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 867 bytes --]



Ignacio García Pérez <iggarpe@domain.hid> wrote on 14.11.2005 17:41:13:

>
> >> Using this scheme, user mode programs just need to open()
> >> /proc/xenomai/registry/pipes/whatever to access a named pipe, without
> >> having to know the minor number.
> >>
> >> Under these circumstances, it would be *very* useful to have
> >> rt_pipe_create choose an unused minor automagically (for example
passing
> >> -1 as the minor).

ah.. yep, that's what I have meant with a PIPE_MINOR_AUTO thing :)

> >>
> >
> > Sounds reasonable.
>
> On the heels of our abs/rel discussion, I suggest to use a #define
> istead of -1
>
> Will you implement it, or should I give a try?
>

If you want to have some fun (and you have some time and desire for that)
then go ahead :) Otherwise, no problem, I'll do that.


> Nacho.
>

---
Best regards,
Dmitry

[-- Attachment #2: Type: text/html, Size: 1216 bytes --]

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

* Re: [Xenomai-help] xn_pipe_create [minor]
  2005-11-14 16:52                 ` Dmitry Adamushko
@ 2005-11-14 17:38                   ` Philippe Gerum
  2005-11-14 18:33                     ` Dmitry Adamushko
  2005-11-14 18:03                   ` [Xenomai-help] Strange pipe behaviour Ignacio García Pérez
  1 sibling, 1 reply; 53+ messages in thread
From: Philippe Gerum @ 2005-11-14 17:38 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: xenomai

Dmitry Adamushko wrote:
> Ignacio García Pérez <iggarpe@domain.hid> wrote on 14.11.2005 17:41:13:
> 
>  >
>  > >> Using this scheme, user mode programs just need to open()
>  > >> /proc/xenomai/registry/pipes/whatever to access a named pipe, without
>  > >> having to know the minor number.
>  > >>
>  > >> Under these circumstances, it would be *very* useful to have
>  > >> rt_pipe_create choose an unused minor automagically (for example 
> passing
>  > >> -1 as the minor).
> 
> ah.. yep, that's what I have meant with a PIPE_MINOR_AUTO thing :)
> 
>  > >>
>  > >
>  > > Sounds reasonable.
>  >
>  > On the heels of our abs/rel discussion, I suggest to use a #define
>  > istead of -1
>  >
>  > Will you implement it, or should I give a try?
>  >
> 
> If you want to have some fun (and you have some time and desire for 
> that) then go ahead :) Otherwise, no problem, I'll do that.
> 

Please make sure to implement this at the nucleus level, and if using a bitmap 
to locate free/busy slots, it should be large enough to handle FDSETSIZE 
channels, not BITS_PER_LONG.

-- 

Philippe.


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

* [Xenomai-help] Strange pipe behaviour
  2005-11-14 16:52                 ` Dmitry Adamushko
  2005-11-14 17:38                   ` Philippe Gerum
@ 2005-11-14 18:03                   ` Ignacio García Pérez
  2005-11-16  5:45                     ` Philippe Gerum
  1 sibling, 1 reply; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-14 18:03 UTC (permalink / raw)
  To: xenomai

Hi,

I have the following piece of code:

RT_PIPE_MSG *msg;

while ((r = rt_pipe_receive(&mypipe, &msg, TM_INFINITE)) >= 0) {
    /* whatever */
    rt_pipe_free(msg);
}

When that thread enters, it blocks, as expected, in the rt_pipe_receive
call.

Then, from user space, I do:

echo -en "\x00" > /dev/rtp0

What happens is:

1- rt_pipe_receive returns with r >= 0.
2- /* whatever */
3- Message is freed using rt_pipe_free.
4- Next call to rt_pipe_receive returns with r = -EINTR.

The only explanation I could come up with is that when the pipe is
closed by the user mode process, the rt_pipe_receive tells the rt task
by returning -EINTR. Is this right?. According to the docs, -EINTR is
only returned if rt_task_unblock() has been called...

Nacho.





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

* Re: [Xenomai-help] xn_pipe_create [minor]
  2005-11-14 17:38                   ` Philippe Gerum
@ 2005-11-14 18:33                     ` Dmitry Adamushko
  2005-11-15  8:04                       ` Philippe Gerum
  0 siblings, 1 reply; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-14 18:33 UTC (permalink / raw)
  To: rpm; +Cc: xenomai

On Monday 14 November 2005 18:38, Philippe Gerum wrote:
> xenomai@xenomai.org

> > If you want to have some fun (and you have some time and desire for 
> > that) then go ahead :) Otherwise, no problem, I'll do that.
> > 
> 
> Please make sure to implement this at the nucleus level, and if using a 
> bitmap to locate free/busy slots, it should be large enough to handle 
> FDSETSIZE  channels, not BITS_PER_LONG.

We have xnpipe_states[XNPIPE_DEVS] array of pipe objects. Choosing a minor 
value is about choosing a free slot (minor == id of that slot) so there are 
XNPIPE_DEVS possible values. The bitmap must contain at least XNPIPE_DEVS 
bits. I don't understand what FDSETSIZE has to do here (if you mean the one 
that is used to configure select() behaviour).

> -- 
>
> Philippe.

---

Dmitry


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

* Re: [Xenomai-help] xn_pipe_create [minor]
  2005-11-14 18:33                     ` Dmitry Adamushko
@ 2005-11-15  8:04                       ` Philippe Gerum
  0 siblings, 0 replies; 53+ messages in thread
From: Philippe Gerum @ 2005-11-15  8:04 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: xenomai

Dmitry Adamushko wrote:
> On Monday 14 November 2005 18:38, Philippe Gerum wrote:
> 
>>xenomai@xenomai.org
> 
> 
>>>If you want to have some fun (and you have some time and desire for 
>>>that) then go ahead :) Otherwise, no problem, I'll do that.
>>>
>>
>>Please make sure to implement this at the nucleus level, and if using a 
>>bitmap to locate free/busy slots, it should be large enough to handle 
>>FDSETSIZE  channels, not BITS_PER_LONG.
> 
> 
> We have xnpipe_states[XNPIPE_DEVS] array of pipe objects. Choosing a minor 
> value is about choosing a free slot (minor == id of that slot) so there are 
> XNPIPE_DEVS possible values. The bitmap must contain at least XNPIPE_DEVS 
> bits. I don't understand what FDSETSIZE has to do here (if you mean the one 
> that is used to configure select() behaviour).

The point is about not being limited to the number of bits in a long, because I 
know of configurations with more than 32 active channels. IOW,
#define XNPIPE_DEVS FDSETSIZE should be possible.

> 
> 
>>-- 
>>
>>Philippe.
> 
> 
> ---
> 
> Dmitry
> 


-- 

Philippe.


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

* [Xenomai-core] Re: [Xenomai-help] printk
  2005-11-14 14:50               ` [Xenomai-core] " Dmitry Adamushko
  2005-11-14 15:56                 ` [Xenomai-core] rt_pipe_* usage Ignacio García Pérez
@ 2005-11-15  9:38                 ` Philippe Gerum
  2005-11-15 10:00                   ` Dmitry Adamushko
  1 sibling, 1 reply; 53+ messages in thread
From: Philippe Gerum @ 2005-11-15  9:38 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: xenomai, xenomai

Dmitry Adamushko wrote:
>  > > ...
>  > >
>  > > This cannot happen in async mode, since the output would be 
> buffered and
>  > > printk() never called on behalf of the preempted handler.
>  > >
>  > >>
>  > >> let's say at the (*) point
>  > >>
>  > >> void __ipipe_flush_printk (unsigned virq)
>  > >> {
>  > >>       char *p = __ipipe_printk_buf;
>  > >>       int out = 0, len;
>  > >>
>  > >>       clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);
>  > >>
>  > >>       while (out < __ipipe_printk_fill) {
>  > >>               len = strlen(p) + 1;
>  > >>               printk("%s",p);
>  > >>               p += len;
>  > >>               out += len;
>  > >>       }
>  > >> (*) <---------------------------- preempted
>  > >>       __ipipe_printk_fill = 0;
>  > >> }
>  > >>
>  > >> When linux gets controll back the virq continues its execution and
>  > >> sets __ipipe_printk_fill up to 0.
>  > >>
>  > >> This cannot happen only if virqs are manipulated with the primary
>  > >> domain being stalled as well. But you told "and under __Linux
>  > >> domain___ stalling protection in __ipipe_flush_printk since it's a
>  > >> virq handler".
>  > >>
>  > >>
>  > >>  > and finally, printk() cannot preempt
>  > >>  > __ipipe_flush_printk under normal operation mode (i.e. async 
> mode).
>  > >> AFAICS,
>  > >>  > there's no race here.
>  >
>  > Mea culpa, Dmitry is right, in the above situation he depicted, we
>  > could drop a
>  > portion of the output buffer. A way to fix this would be to hw lock
>  > a test and
>  > decrement section of __ipipe_printk_fill in the flush handler.
>  >
> 
> Something like that (just a draft) would work probably but I suppose 
> something a bit more graceful would be implemented. Actually, with a 
> small optimization of IPIPE_PRINTK_FLAG.
> 
> void __ipipe_flush_printk (unsigned virq)
> {
>       char *p = __ipipe_printk_buf;
> -       int out = 0, len;
> +       int out = 0, len, used;
> 
> ...
> -       clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);
> ...
> 
> + spin_lock_irqsave_hw(&__ipipe_printk_lock,flags);
> + used = __ipipe_printk_fill;
> + spin_unlock_irqrestore_hw(&__ipipe_printk_lock,flags);
> 
> + oncemore:
> 
>       while (out < used) {
>               len = strlen(p) + 1;
>               printk("%s",p);
>               p += len;
>               out += len;
>       }
> 
> + spin_lock_irqsave_hw(&__ipipe_printk_lock,flags);
> + if (__ipipe_printk_fill == used)
> + {
> -       __ipipe_printk_fill = 0;
> 
> +     used = __ipipe_printk_fill = 0;
> 
> + // when everything is done
> +      clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);
> 
> + }
> + else
> + used = __ipipe_printk_fill;
> + spin_unlock_irqrestore_hw(&__ipipe_printk_lock,flags);
> 
> + if (used)
> + goto oncemore;
> 
> ...
> }
> 
> and
> 
> asmlinkage int printk(const char *fmt, ...)
> {
> + int virq_is_active;
> ...
> 
>       spin_lock_irqsave_hw(&__ipipe_printk_lock,flags);
> 
>       fbytes = __LOG_BUF_LEN - __ipipe_printk_fill;
> 
>       if (fbytes > 1) {
>               r = vscnprintf(__ipipe_printk_buf + __ipipe_printk_fill,
>                              fbytes, fmt, args) + 1; /* account for the 
> null byte */
>               __ipipe_printk_fill += r;
>       } else
>               r = 0;
> 
> + virq_is_active = 
> test_and_set_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);
> 
>       spin_unlock_irqrestore_hw(&__ipipe_printk_lock,flags);
> 
> - if (!test_and_set_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags))
> +      if (!virq_is_active)
>               ipipe_trigger_irq(__ipipe_printk_virq);
> out:
>       va_end(args);
> 
>       return r;
> }
> 

Another approach is about dropping the non-atomic update sequence that hurts, tolerating 
null runs of the virq when the seldom preemption case is seen, but without requiring hw 
interrupt masking to protect the shared stuff. Livelocking Linux inside the virq handler 
would still be possible whenever the RT side spams the kernel log, but this would not be 
an issue for us, since there is no such thing as a fair real-time system anyway.

--- kernel/printk.c	2 Nov 2005 16:29:34 -0000	1.2
+++ kernel/printk.c	15 Nov 2005 09:11:33 -0000
@@ -511,24 +511,23 @@

  static ipipe_spinlock_t __ipipe_printk_lock = IPIPE_SPIN_LOCK_UNLOCKED;

-static int __ipipe_printk_fill;
+static atomic_t __ipipe_printk_fill;

  static char __ipipe_printk_buf[__LOG_BUF_LEN];

  void __ipipe_flush_printk (unsigned virq)
  {
  	char *p = __ipipe_printk_buf;
-	int out = 0, len;
+	int len;

-	clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);
-
-	while (out < __ipipe_printk_fill) {
-		len = strlen(p) + 1;
-		printk("%s",p);
-		p += len;
-		out += len;
+	while (test_and_clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags)) {
+		while (atomic_read(&__ipipe_printk_fill) > 0) {
+			len = strlen(p) + 1;
+			printk("%s",p);
+			p += len;
+			atomic_sub(len,&__ipipe_printk_fill);
+		}
  	}
-	__ipipe_printk_fill = 0;
  }

  asmlinkage int printk(const char *fmt, ...)
@@ -548,12 +547,12 @@

  	spin_lock_irqsave_hw(&__ipipe_printk_lock,flags);

-	fbytes = __LOG_BUF_LEN - __ipipe_printk_fill;
+	fbytes = __LOG_BUF_LEN - atomic_read(&__ipipe_printk_fill);

  	if (fbytes > 1)	{
-		r = vscnprintf(__ipipe_printk_buf + __ipipe_printk_fill,
+		r = vscnprintf(__ipipe_printk_buf + atomic_read(&__ipipe_printk_fill),
  			       fbytes, fmt, args) + 1; /* account for the null byte */
-		__ipipe_printk_fill += r;
+		atomic_add(r,&__ipipe_printk_fill);
  	} else
  		r = 0;

-- 

Philippe.


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

* [Xenomai-core] Re: [Xenomai-help] printk
  2005-11-15  9:38                 ` [Xenomai-core] Re: [Xenomai-help] printk Philippe Gerum
@ 2005-11-15 10:00                   ` Dmitry Adamushko
  2005-11-16 12:58                     ` Philippe Gerum
  0 siblings, 1 reply; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-15 10:00 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai, xenomai

[-- Attachment #1: Type: text/plain, Size: 3079 bytes --]


please see comments below...

>
> Another approach is about dropping the non-atomic update sequence
> that hurts, tolerating
> null runs of the virq when the seldom preemption case is seen, but
> without requiring hw
> interrupt masking to protect the shared stuff. Livelocking Linux
> inside the virq handler
> would still be possible whenever the RT side spams the kernel log,
> but this would not be
> an issue for us, since there is no such thing as a fair real-time
> system anyway.
>
> --- kernel/printk.c   2 Nov 2005 16:29:34 -0000   1.2
> +++ kernel/printk.c   15 Nov 2005 09:11:33 -0000
> @@ -511,24 +511,23 @@
>
>   static ipipe_spinlock_t __ipipe_printk_lock = IPIPE_SPIN_LOCK_UNLOCKED;
>
> -static int __ipipe_printk_fill;
> +static atomic_t __ipipe_printk_fill;
>
>   static char __ipipe_printk_buf[__LOG_BUF_LEN];
>
>   void __ipipe_flush_printk (unsigned virq)
>   {
>      char *p = __ipipe_printk_buf;
> -   int out = 0, len;
> +   int len;
>
> -   clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);
> -
> -   while (out < __ipipe_printk_fill) {
> -      len = strlen(p) + 1;
> -      printk("%s",p);
> -      p += len;
> -      out += len;
> +   while
(test_and_clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags)) {
> +      while (atomic_read(&__ipipe_printk_fill) > 0) {
> +         len = strlen(p) + 1;
> +         printk("%s",p);
> +         p += len;

> +         atomic_sub(len,&__ipipe_printk_fill);

But that's wrong. __ipipe_printk_fill is used as an index in printk() and
here you use it as a number of bytes still need to be printed.

let's suppose:

p = __ipipe_printk_buf = [ 5 bytes \0] [10 bytes \0]
__ipipe_printk_fill == 17;

1) first iteration of __ipipe_flush_printk

5-byte string is printed out

p = __ipipe_printk_buf + 6 ---> [10 bytes \0]
__ipipe_printk_fill == 11;

...

In the mean time, on another CPU:

2) printk() does

> +      r = vscnprintf(__ipipe_printk_buf +
atomic_read(&__ipipe_printk_fill),
>                   fbytes, fmt, args) + 1; /* account for the null byte */

__ipipe_printk_buf + atomic_read(&__ipipe_printk_fill) ==
__ipipe_printk_buf + 11

and that points right in the middle of the still non-printed 10-bytes long
string [5 bytes \0] [10 bytes (*** this will be broken ***) \0]

So we are loosing data again.

is something wrong? anyway, there must be a small correction somewhere
around :)

> +      }
>      }
> -   __ipipe_printk_fill = 0;
>   }
>
>   asmlinkage int printk(const char *fmt, ...)
> @@ -548,12 +547,12 @@
>
>      spin_lock_irqsave_hw(&__ipipe_printk_lock,flags);
>
> -   fbytes = __LOG_BUF_LEN - __ipipe_printk_fill;
> +   fbytes = __LOG_BUF_LEN - atomic_read(&__ipipe_printk_fill);
>
>      if (fbytes > 1)   {
> -      r = vscnprintf(__ipipe_printk_buf + __ipipe_printk_fill,
> +      r = vscnprintf(__ipipe_printk_buf +
atomic_read(&__ipipe_printk_fill),
>                   fbytes, fmt, args) + 1; /* account for the null byte */
> -      __ipipe_printk_fill += r;
> +      atomic_add(r,&__ipipe_printk_fill);
>      } else
>         r = 0;
>

> --
>
> Philippe.

---

Dmitry

[-- Attachment #2: Type: text/html, Size: 4572 bytes --]

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

* [Xenomai-core] Web site error (API doc search)
  2005-11-14 16:36                     ` Ignacio García Pérez
@ 2005-11-15 12:41                       ` Ignacio García Pérez
  2005-11-15 13:16                       ` [Xenomai-core] rt_pipe_* usage Philippe Gerum
  1 sibling, 0 replies; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-15 12:41 UTC (permalink / raw)
  To: xenomai

Hi,

When I use the search function in the online API documentation, firefox
(1.0.7) downloads search.php. I guess something is fouled up.

Nacho.


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

* Re: [Xenomai-core] rt_pipe_* usage
  2005-11-14 16:36                     ` Ignacio García Pérez
  2005-11-15 12:41                       ` [Xenomai-core] Web site error (API doc search) Ignacio García Pérez
@ 2005-11-15 13:16                       ` Philippe Gerum
  2005-11-15 16:22                         ` Ignacio García Pérez
  1 sibling, 1 reply; 53+ messages in thread
From: Philippe Gerum @ 2005-11-15 13:16 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

Ignacio García Pérez wrote:
>>>RT_PIPE_MSG *m = rt_pipe_alloc(sizeof(mystruct_t));
>>>mystruct_t *p = (mystruct_t *)P_MSGPTR(m);
>>>p->whatever1 = X;
>>>p->whatever2 = X;
>>>rt_pipe_send(&mypipe, m, sizeof(mystruct_t), P_NORMAL);
>>>
>>>If this is correct, why do I have to specify the size of mystruct_t
>>>*twice*. Can't it be initialized by rt_pipe_alloc ?.
>>
>>It's initialized actually (*).
>>
> 
> So, what's the sense of having to specify it again whet calling
> rt_pipe_send ?
> 

Because you may (pre-)allocate more than you really need to send afterwards.

-- 

Philippe.


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

* Re: [Xenomai-core] More on rt pipes usage
  2005-11-14 16:15                   ` [Xenomai-core] More on rt pipes usage Ignacio García Pérez
@ 2005-11-15 13:24                     ` Philippe Gerum
  2005-11-15 16:41                       ` [Xenomai-help] " Ignacio García Pérez
  0 siblings, 1 reply; 53+ messages in thread
From: Philippe Gerum @ 2005-11-15 13:24 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

Ignacio García Pérez wrote:
> Hi,
> 
> Suppose I have a kernel rt task that samples data at a certain rate and
> writes it as messages into a rt pipe, from which it is read by a user
> space non rt program.
> 
> I want to limit the number of messages that are put into the pipe,
> because otherwise if the user space program dies, it will grow endlessly
> till it exausts the rt heap.
> 
> What I want to do is to have a pipe that can hold a limited number of
> messages such that rt_pipe_write will fail if it is full.
> 
> Is there a way to know how many messages are there in the pipe?
> 
> Even if there is a way, to prevent a (harmless) race condition, I would
> need to lock the pipe between checking the number of messages and
> calling rt_pipe_write. As far as I know, pipe locking belongs to the
> nucleus and I'd like to stay in the native skin as much as possible.
> 
> Another method would be to count how many messages I write, but then I'd
> need some hook that notifies me when the user space program reads a
> message so I can decrement the count.
> 
> Any ideas?

The plan is to be able to tell the pipe manager to use a user-provided heap 
instead of the system one; this way, exhausting the local heap (*) in RT space 
would be a clear sign that non-RT must be allowed to consume the pending data 
first. A simple interface to do that is missing, but the pipe manager already 
works with a variable heap pointer.

(*) Using the overall available memory seems a better metric than the number of 
pending messages, since it may often happen that messages have different sizes.

-- 

Philippe.


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

* Re: [Xenomai-core] rt_pipe_* usage
  2005-11-15 13:16                       ` [Xenomai-core] rt_pipe_* usage Philippe Gerum
@ 2005-11-15 16:22                         ` Ignacio García Pérez
  2005-11-16  5:38                           ` Philippe Gerum
  0 siblings, 1 reply; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-15 16:22 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 750 bytes --]

Philippe Gerum wrote:

> Ignacio García Pérez wrote:
>
>>>> RT_PIPE_MSG *m = rt_pipe_alloc(sizeof(mystruct_t));
>>>> mystruct_t *p = (mystruct_t *)P_MSGPTR(m);
>>>> p->whatever1 = X;
>>>> p->whatever2 = X;
>>>> rt_pipe_send(&mypipe, m, sizeof(mystruct_t), P_NORMAL);
>>>>
>>>> If this is correct, why do I have to specify the size of mystruct_t
>>>> *twice*. Can't it be initialized by rt_pipe_alloc ?.
>>>
>>>
>>> It's initialized actually (*).
>>>
>>
>> So, what's the sense of having to specify it again whet calling
>> rt_pipe_send ?
>>
>
> Because you may (pre-)allocate more than you really need to send
> afterwards.
>
I guess this should be explained in the docs. Please consider the small
patch I attach.

Nacho.

[-- Attachment #2: patch.diff --]
[-- Type: text/plain, Size: 844 bytes --]

Index: skins/native/pipe.c
===================================================================
--- skins/native/pipe.c	(revision 143)
+++ skins/native/pipe.c	(working copy)
@@ -598,7 +598,11 @@
  *
  * @param size The size in bytes of the message (payload data
  * only). Zero is a valid value, in which case the service returns
- * immediately without sending any message.
+ * immediately without sending any message. This parameter allows
+ * you to actually send less data than you reserved using the
+ * rt_pipe_alloc() service, which may be the case if you did not
+ * know how much space you needed at the time of allocation. In all
+ * other cases it may be more convenient to just pass P_MSGSIZE(msg).
  *
  * Additionally, rt_pipe_send() causes any data buffered by
  * rt_pipe_stream() to be flushed prior to sending the message. For

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

* [Xenomai-help] Re: [Xenomai-core] More on rt pipes usage
  2005-11-15 13:24                     ` Philippe Gerum
@ 2005-11-15 16:41                       ` Ignacio García Pérez
  0 siblings, 0 replies; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-15 16:41 UTC (permalink / raw)
  To: Philippe Gerum, xenomai

Philippe Gerum wrote:

> Ignacio García Pérez wrote:
>
>> Hi,
>>
>> Suppose I have a kernel rt task that samples data at a certain rate and
>> writes it as messages into a rt pipe, from which it is read by a user
>> space non rt program.
>>
>> I want to limit the number of messages that are put into the pipe,
>> because otherwise if the user space program dies, it will grow endlessly
>> till it exausts the rt heap.
>>
>> What I want to do is to have a pipe that can hold a limited number of
>> messages such that rt_pipe_write will fail if it is full.
>>
>> Is there a way to know how many messages are there in the pipe?
>>
>> Even if there is a way, to prevent a (harmless) race condition, I would
>> need to lock the pipe between checking the number of messages and
>> calling rt_pipe_write. As far as I know, pipe locking belongs to the
>> nucleus and I'd like to stay in the native skin as much as possible.
>>
>> Another method would be to count how many messages I write, but then I'd
>> need some hook that notifies me when the user space program reads a
>> message so I can decrement the count.
>>
>> Any ideas?
>
>
> The plan is to be able to tell the pipe manager to use a user-provided
> heap instead of the system one; this way, exhausting the local heap
> (*) in RT space would be a clear sign that non-RT must be allowed to
> consume the pending data first. A simple interface to do that is
> missing, but the pipe manager already works with a variable heap pointer.

That mechanism would work only if you allow a local heap for *each* pipe
(otherwise one abused pipe may clobber others).

Personally, I need this feature to manage extreme error cases (the user
process dying). There is no point in knowing when the non-RT processing
is overwhelmed, because if that happens there is nothing you can do.

If you are producing more RT data that your non-RT processes can
consume, then you'll exhaust storage sooner or later. If you have RT
data production peaks, it's your responsibility to allocate enough
storage to provide for the worst case.

In other words. RT processes may *never* have to wait for non-RT
processes, because then they would become also non-RT.

So, the only use I can think of for limited pipe storage (be it in
message count or used memory) is to detect fatal error conditions, such
as the case of no one consuming data. And at least in my case, I
absolutely need this feature (if the non-RT process dies for any reason,
the system must not collapse).

>
> (*) Using the overall available memory seems a better metric than the
> number of pending messages, since it may often happen that messages
> have different sizes.
>
Mmm... yeah, you are probably right. I mentioned the number of messages
because I noticed the elems field in the queue structure and though it
would be easier to implement using it.

However, being this limitation just an "electric fence" for out of hand
scenarios, the way you express the limit is not critial. If no one is
consuming data from non-RT space, the limit will be reached no matter if
you express it as messages or as memory.

Nacho.




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

* Re: [Xenomai-core] rt_pipe_* usage
  2005-11-15 16:22                         ` Ignacio García Pérez
@ 2005-11-16  5:38                           ` Philippe Gerum
  0 siblings, 0 replies; 53+ messages in thread
From: Philippe Gerum @ 2005-11-16  5:38 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

Ignacio García Pérez wrote:
> Philippe Gerum wrote:
> 
> 
>>Ignacio García Pérez wrote:
>>
>>
>>>>>RT_PIPE_MSG *m = rt_pipe_alloc(sizeof(mystruct_t));
>>>>>mystruct_t *p = (mystruct_t *)P_MSGPTR(m);
>>>>>p->whatever1 = X;
>>>>>p->whatever2 = X;
>>>>>rt_pipe_send(&mypipe, m, sizeof(mystruct_t), P_NORMAL);
>>>>>
>>>>>If this is correct, why do I have to specify the size of mystruct_t
>>>>>*twice*. Can't it be initialized by rt_pipe_alloc ?.
>>>>
>>>>
>>>>It's initialized actually (*).
>>>>
>>>
>>>So, what's the sense of having to specify it again whet calling
>>>rt_pipe_send ?
>>>
>>
>>Because you may (pre-)allocate more than you really need to send
>>afterwards.
>>
> 
> I guess this should be explained in the docs. Please consider the small
> patch I attach.
> 

Ok, applied. Thanks.

> Nacho.
> 
> 
> ------------------------------------------------------------------------
> 
> Index: skins/native/pipe.c
> ===================================================================
> --- skins/native/pipe.c	(revision 143)
> +++ skins/native/pipe.c	(working copy)
> @@ -598,7 +598,11 @@
>   *
>   * @param size The size in bytes of the message (payload data
>   * only). Zero is a valid value, in which case the service returns
> - * immediately without sending any message.
> + * immediately without sending any message. This parameter allows
> + * you to actually send less data than you reserved using the
> + * rt_pipe_alloc() service, which may be the case if you did not
> + * know how much space you needed at the time of allocation. In all
> + * other cases it may be more convenient to just pass P_MSGSIZE(msg).
>   *
>   * Additionally, rt_pipe_send() causes any data buffered by
>   * rt_pipe_stream() to be flushed prior to sending the message. For


-- 

Philippe.


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

* Re: [Xenomai-help] Strange pipe behaviour
  2005-11-14 18:03                   ` [Xenomai-help] Strange pipe behaviour Ignacio García Pérez
@ 2005-11-16  5:45                     ` Philippe Gerum
  2005-11-16  7:45                       ` Ignacio García Pérez
  0 siblings, 1 reply; 53+ messages in thread
From: Philippe Gerum @ 2005-11-16  5:45 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

Ignacio García Pérez wrote:
> Hi,
> 
> I have the following piece of code:
> 
> RT_PIPE_MSG *msg;
> 
> while ((r = rt_pipe_receive(&mypipe, &msg, TM_INFINITE)) >= 0) {
>     /* whatever */
>     rt_pipe_free(msg);
> }
> 
> When that thread enters, it blocks, as expected, in the rt_pipe_receive
> call.
> 
> Then, from user space, I do:
> 
> echo -en "\x00" > /dev/rtp0
> 
> What happens is:
> 
> 1- rt_pipe_receive returns with r >= 0.
> 2- /* whatever */
> 3- Message is freed using rt_pipe_free.
> 4- Next call to rt_pipe_receive returns with r = -EINTR.
> 
> The only explanation I could come up with is that when the pipe is
> closed by the user mode process, the rt_pipe_receive tells the rt task
> by returning -EINTR. Is this right?.

Yes.

  According to the docs, -EINTR is
> only returned if rt_task_unblock() has been called...
> 

Actually, this is what happened through the internal interface.
driver::release(pipe) -> nucleus::unblock(sleepers_on_pipe)

> Nacho.
> 
> 
> 
> 
> _______________________________________________
> Xenomai-help mailing list
> Xenomai-help@domain.hid
> https://mail.gna.org/listinfo/xenomai-help
> 


-- 

Philippe.


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

* Re: [Xenomai-help] Strange pipe behaviour
  2005-11-16  5:45                     ` Philippe Gerum
@ 2005-11-16  7:45                       ` Ignacio García Pérez
  2005-11-16 11:45                         ` Philippe Gerum
  0 siblings, 1 reply; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-16  7:45 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai


>>
>> 1- rt_pipe_receive returns with r >= 0.
>> 2- /* whatever */
>> 3- Message is freed using rt_pipe_free.
>> 4- Next call to rt_pipe_receive returns with r = -EINTR.
>>
>> The only explanation I could come up with is that when the pipe is
>> closed by the user mode process, the rt_pipe_receive tells the rt task
>> by returning -EINTR. Is this right?.
>
>
> Yes.
>
>  According to the docs, -EINTR is
>
>> only returned if rt_task_unblock() has been called...
>>
>
> Actually, this is what happened through the internal interface.
> driver::release(pipe) -> nucleus::unblock(sleepers_on_pipe)

Sure, but that behaviour is *extremely* confusing for a newbie (like
me). Should be described in the docs (this time I don't submit a patch
because I don't quite understand the pipe internals yet).

And anyway, I don't see the point in notifying the RT task that the
non-RT end has closed the pipe. Or, in other words, if we want to
provide such a notification, we should provide also opening notification.

By the way, where is the xnpipe_* API documentation? I could not find it
in the online docs (firefox downloads the file search.php when I try to
use the search feature).

>
>> Nacho.
>>
>>
>>
>>
>> _______________________________________________
>> Xenomai-help mailing list
>> Xenomai-help@domain.hid
>> https://mail.gna.org/listinfo/xenomai-help
>>
>
>



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

* Re: [Xenomai-help] Strange pipe behaviour
  2005-11-16  7:45                       ` Ignacio García Pérez
@ 2005-11-16 11:45                         ` Philippe Gerum
  0 siblings, 0 replies; 53+ messages in thread
From: Philippe Gerum @ 2005-11-16 11:45 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

Ignacio García Pérez wrote:
>>>1- rt_pipe_receive returns with r >= 0.
>>>2- /* whatever */
>>>3- Message is freed using rt_pipe_free.
>>>4- Next call to rt_pipe_receive returns with r = -EINTR.
>>>
>>>The only explanation I could come up with is that when the pipe is
>>>closed by the user mode process, the rt_pipe_receive tells the rt task
>>>by returning -EINTR. Is this right?.
>>
>>
>>Yes.
>>
>> According to the docs, -EINTR is
>>
>>
>>>only returned if rt_task_unblock() has been called...
>>>
>>
>>Actually, this is what happened through the internal interface.
>>driver::release(pipe) -> nucleus::unblock(sleepers_on_pipe)
> 
> 
> Sure, but that behaviour is *extremely* confusing for a newbie (like
> me). Should be described in the docs (this time I don't submit a patch
> because I don't quite understand the pipe internals yet).
>

If you understand enough of the API documentation to disagree with it, I guess 
that you should be able to reword it in a way that seems less error-prone in 
your eyes. You don't have to explain the gory details of the implementation to 
do that.

> And anyway, I don't see the point in notifying the RT task that the
> non-RT end has closed the pipe.

Message pipes are connection-oriented thingies. You cannot just let one 
communication end-point vanish and leave the other side lingering indefinitely 
without notifying it.

  Or, in other words, if we want to
> provide such a notification, we should provide also opening notification.
> 

That's irrelevant. rt_pipe_connect() from kernel space is semantically similar 
to open(some_named_fifo,O_RDWR|O_NONBLOCK) from user-space, since the caller 
does not wait for the other end-point to show up. But even in that case, closing 
the named fifo at the other side causes any subsequent read() on the connecting 
side to be notified of the closure. The same goes for message pipes. The only 
thing you could argue is that read() would first return a zero-sized message 
first as an end-of-file marker, then an error upon all subsequent reads; since 
we don't want to forcibly close the kernel side upon user-space closure, a 
possible change would be to make rt_pipe_recv() return -EPIPE instead of -EINTR 
in that specific case.

And actually, the nucleus interface does provide support for registering a 
connection notification handler, but it is not exported by the native skin since 
it would buy us nothing in the context of a regular API.

> By the way, where is the xnpipe_* API documentation? I could not find it
> in the online docs (firefox downloads the file search.php when I try to
> use the search feature).
> 

Still undocumented portion.

> 
>>>Nacho.
>>>
>>>
>>>
>>>
>>>_______________________________________________
>>>Xenomai-help mailing list
>>>Xenomai-help@domain.hid
>>>https://mail.gna.org/listinfo/xenomai-help
>>>
>>
>>
> 
> 


-- 

Philippe.


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

* [Xenomai-core] Re: [Xenomai-help] printk
  2005-11-15 10:00                   ` Dmitry Adamushko
@ 2005-11-16 12:58                     ` Philippe Gerum
  2005-11-16 14:44                       ` Dmitry Adamushko
  2005-11-17  9:44                       ` [Xenomai-help] Blocking reads from pipes Ignacio García Pérez
  0 siblings, 2 replies; 53+ messages in thread
From: Philippe Gerum @ 2005-11-16 12:58 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: xenomai, xenomai

Dmitry Adamushko wrote:
> please see comments below...
>
>  >
>  > Another approach is about dropping the non-atomic update sequence
>  > that hurts, tolerating
>  > null runs of the virq when the seldom preemption case is seen, but
>  > without requiring hw
>  > interrupt masking to protect the shared stuff. Livelocking Linux
>  > inside the virq handler
>  > would still be possible whenever the RT side spams the kernel log,
>  > but this would not be
>  > an issue for us, since there is no such thing as a fair real-time
>  > system anyway.
>  >
>  > --- kernel/printk.c   2 Nov 2005 16:29:34 -0000   1.2
>  > +++ kernel/printk.c   15 Nov 2005 09:11:33 -0000
>  > @@ -511,24 +511,23 @@
>  >
>  >   static ipipe_spinlock_t __ipipe_printk_lock = IPIPE_SPIN_LOCK_UNLOCKED;
>  >
>  > -static int __ipipe_printk_fill;
>  > +static atomic_t __ipipe_printk_fill;
>  >
>  >   static char __ipipe_printk_buf[__LOG_BUF_LEN];
>  >
>  >   void __ipipe_flush_printk (unsigned virq)
>  >   {
>  >      char *p = __ipipe_printk_buf;
>  > -   int out = 0, len;
>  > +   int len;
>  >
>  > -   clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);
>  > -
>  > -   while (out < __ipipe_printk_fill) {
>  > -      len = strlen(p) + 1;
>  > -      printk("%s",p);
>  > -      p += len;
>  > -      out += len;
>  > +   while
> (test_and_clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags)) {
>  > +      while (atomic_read(&__ipipe_printk_fill) > 0) {
>  > +         len = strlen(p) + 1;
>  > +         printk("%s",p);
>  > +         p += len;
>
>  > +         atomic_sub(len,&__ipipe_printk_fill);
>
> But that's wrong. __ipipe_printk_fill is used as an index in printk()
> and here you use it as a number of bytes still need to be printed.
>

Ok, this kind of stuff should always be designed with the brain turned on. Now
that I have eventually found the power switch, I'm going to fix the printk issue
in the Adeos core along the following lines. The code below basically reworks
your proposal. The construct is still a bit hairy, but unfortunately, we cannot
just go for using a plain atomic compare-and-exchange op in the virq handler,
since we need to serialize its activation among all CPUs - sigh... We also get rid
of PPRINTK - which is redundant - in the same move.

--- ipipe/v2.6/2.6.14/kernel/printk.c	2 Nov 2005 16:29:34 -0000	1.2
+++ ipipe/v2.6/2.6.14/kernel/printk.c	16 Nov 2005 12:18:09 -0000
@@ -518,23 +518,34 @@
  void __ipipe_flush_printk (unsigned virq)
  {
  	char *p = __ipipe_printk_buf;
-	int out = 0, len;
+	int len, lmax, out = 0;
+	unsigned long flags;

-	clear_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags);
+	goto start;

-	while (out < __ipipe_printk_fill) {
-		len = strlen(p) + 1;
-		printk("%s",p);
-		p += len;
-		out += len;
+	do {
+		spin_unlock_irqrestore_hw(&__ipipe_printk_lock,flags);
+ start:
+		lmax = __ipipe_printk_fill;
+		while (out < lmax) {
+			len = strlen(p) + 1;
+			printk("%s",p);
+			p += len;
+			out += len;
+		}
+		spin_lock_irqsave_hw(&__ipipe_printk_lock,flags);
  	}
+	while (__ipipe_printk_fill != lmax);
+
  	__ipipe_printk_fill = 0;
+
+	spin_unlock_irqrestore_hw(&__ipipe_printk_lock,flags);
  }

  asmlinkage int printk(const char *fmt, ...)
  {
-	unsigned long flags;
-	int r, fbytes;
+	int r, fbytes, oldcount;
+    	unsigned long flags;
  	va_list args;

  	va_start(args, fmt);
@@ -548,7 +559,8 @@

  	spin_lock_irqsave_hw(&__ipipe_printk_lock,flags);

-	fbytes = __LOG_BUF_LEN - __ipipe_printk_fill;
+	oldcount = __ipipe_printk_fill;
+	fbytes = __LOG_BUF_LEN - oldcount;

  	if (fbytes > 1)	{
  		r = vscnprintf(__ipipe_printk_buf + __ipipe_printk_fill,
@@ -559,7 +571,7 @@

  	spin_unlock_irqrestore_hw(&__ipipe_printk_lock,flags);

-	if (!test_and_set_bit(IPIPE_PPRINTK_FLAG,&ipipe_root_domain->flags))
+	if (oldcount == 0)
  		ipipe_trigger_irq(__ipipe_printk_virq);
  out:
  	va_end(args);
-- 

Philippe.




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

* [Xenomai-core] Re: [Xenomai-help] printk
  2005-11-16 12:58                     ` Philippe Gerum
@ 2005-11-16 14:44                       ` Dmitry Adamushko
  2005-11-17  9:44                       ` [Xenomai-help] Blocking reads from pipes Ignacio García Pérez
  1 sibling, 0 replies; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-16 14:44 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai, xenomai

[-- Attachment #1: Type: text/plain, Size: 723 bytes --]

Philippe Gerum <rpm@xenomai.org> wrote on 16.11.2005 13:58:45:

> ...
>
> Ok, this kind of stuff should always be designed with the brain turned
on. Now
> that I have eventually found the power switch, I'm going to fix the
> printk issue
> in the Adeos core along the following lines. The code below basically
reworks
> your proposal. The construct is still a bit hairy, but
> unfortunately, we cannot
> just go for using a plain atomic compare-and-exchange op in the virq
handler,
> since we need to serialize its activation among all CPUs - sigh...
> We also get rid
> of PPRINTK - which is redundant - in the same move.

Yep, this implementation looks at least sane to me now.


> ...

> --
>
> Philippe.
>

---

Dmitry

[-- Attachment #2: Type: text/html, Size: 1015 bytes --]

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

* [Xenomai-help] Blocking reads from pipes
  2005-11-16 12:58                     ` Philippe Gerum
  2005-11-16 14:44                       ` Dmitry Adamushko
@ 2005-11-17  9:44                       ` Ignacio García Pérez
  2005-11-17 10:21                         ` Romain Lenglet
  2005-11-17 10:46                         ` Dmitry Adamushko
  1 sibling, 2 replies; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-17  9:44 UTC (permalink / raw)
  To: xenomai

Hi,

My application consists of a real time module and a non-realtime user
mode program. They communicate through several pipes.

The user mode program creates a thread (pthread) that opens a pipe and
blocks in a read call, waiting for data. Under certain conditions, the
user mode program must do an orderly exit, and thus I need a way to
unblock that thread.

I've done that in the past with sockets. If you have one thread blocked
reading from a socket handle, and you close it from another thread, the
read call will immediately return with an error code.

However, that doesn't seem to work with xenomai pipes. One posix thread
blocked reading from a pipe (using posix open/read) won't unblock when
you close the file handle from another thread.

Any suggestions?

Thanks.

Nacho.






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

* Re: [Xenomai-help] Blocking reads from pipes
  2005-11-17  9:44                       ` [Xenomai-help] Blocking reads from pipes Ignacio García Pérez
@ 2005-11-17 10:21                         ` Romain Lenglet
  2005-11-17 13:16                           ` Ignacio García Pérez
  2005-11-17 10:46                         ` Dmitry Adamushko
  1 sibling, 1 reply; 53+ messages in thread
From: Romain Lenglet @ 2005-11-17 10:21 UTC (permalink / raw)
  To: xenomai

[-- Attachment #1: Type: text/plain, Size: 705 bytes --]

> One posix thread blocked reading from a pipe (using posix
> open/read) won't unblock when you close the file handle from
> another thread.

Yes, it does!

Compile the two attached source files:
$ gcc -o read read.c
$ gcc -o close close.c

Create the named pipe:
$ mkfifo testfifo

In two different terminals, run "read", which will block in 
read(), then "close".

You will remark that the blocking read call is unblocked when the 
other process closes its descriptor.


As a conclusion, the behaviour that you observed with Xenomai 
pipes seems consistent with that of Linux' named pipes, except 
that in Linux read() returns 0, and not an error code as you 
observed with Xenomai.

-- 
Romain Lenglet

[-- Attachment #2: close.c --]
[-- Type: text/x-csrc, Size: 276 bytes --]

#include <stdio.h>
#include <fcntl.h>

#define SIZE 1024

int
main (int argc, char **argv)
{
  int desc;
  int nread;
  char buf[SIZE];
  desc = open ("./testfifo", O_WRONLY);
  if (desc == -1)
    {
      perror (argv[0]);
      return 1;
    }
  close (desc);
  return 0;
}

[-- Attachment #3: read.c --]
[-- Type: text/x-csrc, Size: 517 bytes --]

#include <stdio.h>
#include <fcntl.h>

#define SIZE 1024

int
main (int argc, char **argv)
{
  int desc;
  int nread;
  char buf[SIZE];
  desc = open ("./testfifo", O_RDONLY);
  if (desc == -1)
    {
      perror (argv[0]);
      return 1;
    }
  while ((nread = read (desc, buf, SIZE)) > 0)
    {
      buf[nread] = 0;
      printf ("child received \"%s\" (%d)\n", buf, nread);
    }
  if (nread == 0)
    printf ("child received 0 bytes!\n");
  if (nread == -1)
    perror (argv[0]);
  close (desc);
  return 0;
}

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

* Re: [Xenomai-help] Blocking reads from pipes
  2005-11-17  9:44                       ` [Xenomai-help] Blocking reads from pipes Ignacio García Pérez
  2005-11-17 10:21                         ` Romain Lenglet
@ 2005-11-17 10:46                         ` Dmitry Adamushko
  1 sibling, 0 replies; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-17 10:46 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 943 bytes --]


> Hi,
>
> My application consists of a real time module and a non-realtime user
> mode program. They communicate through several pipes.
>
> The user mode program creates a thread (pthread) that opens a pipe and
> blocks in a read call, waiting for data. Under certain conditions, the
> user mode program must do an orderly exit, and thus I need a way to
> unblock that thread.
>
> I've done that in the past with sockets. If you have one thread blocked
> reading from a socket handle, and you close it from another thread, the
> read call will immediately return with an error code.
>
> However, that doesn't seem to work with xenomai pipes. One posix thread
> blocked reading from a pipe (using posix open/read) won't unblock when
> you close the file handle from another thread.

Actually, it should be unblocked but with 0 as a return value. I'll take a
look at that.


>
> Any suggestions?
>
> Thanks.
>
> Nacho.

---
Best regards,
Dmitry

[-- Attachment #2: Type: text/html, Size: 1227 bytes --]

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

* Re: [Xenomai-help] Blocking reads from pipes
  2005-11-17 10:21                         ` Romain Lenglet
@ 2005-11-17 13:16                           ` Ignacio García Pérez
  2005-11-17 15:11                             ` Dmitry Adamushko
  0 siblings, 1 reply; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-17 13:16 UTC (permalink / raw)
  To: Romain Lenglet; +Cc: xenomai


>As a conclusion, the behaviour that you observed with Xenomai 
>pipes seems consistent with that of Linux' named pipes, except 
>that in Linux read() returns 0, and not an error code as you 
>observed with Xenomai.
>  
>
The read() call does *not* return when you close the *same* file handle
from another pthread in the same process.

Is that the expected posix behaviour?

Nacho.



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

* Re: [Xenomai-help] Blocking reads from pipes
  2005-11-17 13:16                           ` Ignacio García Pérez
@ 2005-11-17 15:11                             ` Dmitry Adamushko
  2005-11-17 17:24                               ` Gilles Chanteperdrix
  0 siblings, 1 reply; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-17 15:11 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 512 bytes --]


>
> >As a conclusion, the behaviour that you observed with Xenomai
> >pipes seems consistent with that of Linux' named pipes, except
> >that in Linux read() returns 0, and not an error code as you
> >observed with Xenomai.
> >
> >
> The read() call does *not* return when you close the *same* file handle
> from another pthread in the same process.

I confirm that and as I pointed it out in my previous mail - this is not
how it's supposed to be.
I'm currently on it. More news later.


> Nacho.
>

---

Dmitry

[-- Attachment #2: Type: text/html, Size: 748 bytes --]

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

* Re: [Xenomai-help] Blocking reads from pipes
  2005-11-17 15:11                             ` Dmitry Adamushko
@ 2005-11-17 17:24                               ` Gilles Chanteperdrix
  2005-11-17 17:55                                 ` [Xenomai-core] " Dmitry Adamushko
  2005-11-17 19:40                                 ` Dmitry Adamushko
  0 siblings, 2 replies; 53+ messages in thread
From: Gilles Chanteperdrix @ 2005-11-17 17:24 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: xenomai

Dmitry Adamushko wrote:
 > 
 > >
 > > >As a conclusion, the behaviour that you observed with Xenomai
 > > >pipes seems consistent with that of Linux' named pipes, except
 > > >that in Linux read() returns 0, and not an error code as you
 > > >observed with Xenomai.
 > > >
 > > >
 > > The read() call does *not* return when you close the *same* file handle
 > > from another pthread in the same process.
 > 
 > I confirm that and as I pointed it out in my previous mail - this is not
 > how it's supposed to be.
 > I'm currently on it. More news later.

I am not sure about that: Linux regular pipes follow the same behaviour
(the real destruction of the file descriptor is delayed until read()
really returns).

-- 


					    Gilles Chanteperdrix.


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

* [Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
  2005-11-17 17:24                               ` Gilles Chanteperdrix
@ 2005-11-17 17:55                                 ` Dmitry Adamushko
  2005-11-17 19:17                                   ` Gilles Chanteperdrix
  2005-11-17 19:40                                 ` Dmitry Adamushko
  1 sibling, 1 reply; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-17 17:55 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai, xenomai-core

On Thursday 17 November 2005 18:24, Gilles Chanteperdrix wrote:
> Dmitry Adamushko wrote:
>  > > >As a conclusion, the behaviour that you observed with Xenomai
>  > > >pipes seems consistent with that of Linux' named pipes, except
>  > > >that in Linux read() returns 0, and not an error code as you
>  > > >observed with Xenomai.
>  > >
>  > > The read() call does *not* return when you close the *same* file
>  > > handle from another pthread in the same process.
>  >
>  > I confirm that and as I pointed it out in my previous mail - this is not
>  > how it's supposed to be.
>  > I'm currently on it. More news later.
>
> I am not sure about that: Linux regular pipes follow the same behaviour
> (the real destruction of the file descriptor is delayed until read()
> really returns).

My assertion was only based on the idea that nucleus::xnpipe_release() must be 
called as a result of any close() from the user space. And it, in turn, wakes 
up all the blocked readers. So the current implementation at least should 
have worked in sych a case. But, well, below is what I have observed.

Maybe your assertion may explain that.

The reason is actually not because of some problem in the xenomai codebase but 
because of the fact that nucleus::xnpipe_release() is _not_ called as I 
expected it to be :o)

The experiment was as follows (a slightly changed klatency test):

latency_module.ko uses a 10-second wait-interval for sending data

int fd; // pipe

thread#2
{
sleep(3);
close(fd); 

// closing a pipe. Here I expected that nucleus::xnpipe_release() would be 
// called as a result (== file_operations::release ).
}

thread#1
{
fd = open(/dev/rtpN);

pthread_create(thread#2);

read(fd, ...);	// blocked at least for 10 seconds so thread#2 closes a pipe 
		        //earlier 

...
if (error)
    break;

...
close(fd);
}

So xnpipe_release() is _not_ called as a result of the close() call in 
thread#2. close() returns 0 indeed.

10 seconds after its starting, thread#1 :: read() returns a valid block of 
data from the latency module and right after that - an error code is returned 
that the pipe is no longer valid.

I have taken a very brief look at the linux sources but it was not enough to 
get an explanation. So I'll take a closer look now :o)


---

Dmitry




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

* [Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
  2005-11-17 17:55                                 ` [Xenomai-core] " Dmitry Adamushko
@ 2005-11-17 19:17                                   ` Gilles Chanteperdrix
  2005-11-17 19:45                                     ` Dmitry Adamushko
  0 siblings, 1 reply; 53+ messages in thread
From: Gilles Chanteperdrix @ 2005-11-17 19:17 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: xenomai, xenomai-core

Dmitry Adamushko wrote:
 > On Thursday 17 November 2005 18:24, Gilles Chanteperdrix wrote:
 > > Dmitry Adamushko wrote:
 > >  > > >As a conclusion, the behaviour that you observed with Xenomai
 > >  > > >pipes seems consistent with that of Linux' named pipes, except
 > >  > > >that in Linux read() returns 0, and not an error code as you
 > >  > > >observed with Xenomai.
 > >  > >
 > >  > > The read() call does *not* return when you close the *same* file
 > >  > > handle from another pthread in the same process.
 > >  >
 > >  > I confirm that and as I pointed it out in my previous mail - this is not
 > >  > how it's supposed to be.
 > >  > I'm currently on it. More news later.
 > >
 > > I am not sure about that: Linux regular pipes follow the same behaviour
 > > (the real destruction of the file descriptor is delayed until read()
 > > really returns).
 > 
 > My assertion was only based on the idea that nucleus::xnpipe_release() must be 

 > called as a result of any close() from the user space.

If we have a look at the sources, sys_read uses fput_light and
fget_light, which increment and decrement the file descriptor
reference count (member f_count of the file structure) used by fget and
fput when the file descriptor is shared between. open and close call
fget and fput.

"release" only get called through __fput when f_count reaches 0.

-- 


					    Gilles Chanteperdrix.


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

* [Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
  2005-11-17 17:24                               ` Gilles Chanteperdrix
  2005-11-17 17:55                                 ` [Xenomai-core] " Dmitry Adamushko
@ 2005-11-17 19:40                                 ` Dmitry Adamushko
  1 sibling, 0 replies; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-17 19:40 UTC (permalink / raw)
  To: xenomai, xenomai-core

On Thursday 17 November 2005 18:24, Gilles Chanteperdrix wrote:
> Dmitry Adamushko wrote:
>  > > >As a conclusion, the behaviour that you observed with Xenomai
>  > > >pipes seems consistent with that of Linux' named pipes, except
>  > > >that in Linux read() returns 0, and not an error code as you
>  > > >observed with Xenomai.
>  > >
>  > > The read() call does *not* return when you close the *same* file
>  > > handle from another pthread in the same process.
>  >
>  > I confirm that and as I pointed it out in my previous mail - this is not
>  > how it's supposed to be.
>  > I'm currently on it. More news later.
>
> I am not sure about that: Linux regular pipes follow the same behaviour
> (the real destruction of the file descriptor is delayed until read()
> really returns).

Ok, it's me who is a stupid uneducated zorr... I mean bozzo :o)

The reason is quite simple indeed.

The file_operations::release() is called when a <file *> object is about to be 
destroyed (file * object is created for each open file). It happens when its 
refference count becomes 0.

Rigth after open() the counter == 1. As one may guess, close() decrease it on 
1.

There is another entity - file_operations::flush() which is called on each 
close() call. But file_operations::release() is called only when all the 
references on the object have been closed.

There can be N:1 relation. Imagine, dup() or fork() make a copy of the file 
descriptor and as a result - the regerence is increased appropriately.

Now what happens is that read/write() calls increase the counter before using 
a file object and decrease it right before returning.


thread1::open() --> file_operations::open() == xnpipe_open()   ---> counter=1

thread1::read() --> ... counter=2 .. -> file_operations::read() == 
xnpipe_read() - blocked ... (*)

thread2::close() --> ... -> file_operations::flush() [ we don't make use of 
this one in pipe.c ] --> counter = 1

So that's why xnpipe_release() is not called!

10 seconds have elapsed

thread1::read (*) - unblocked() --> copies data to the user's buffer ---> 
counter = 0. Oooops!

As a result -> file_operations::release() is called! Next thread1::read() call 
returns an error code.

So that's what happens. We can define file_operations::flush() and wake up all 
the readers there. But we can't know that this is a last reference on the 
file (ok, we can actually but with a bit of hacking).
I mean :

f = open() -> 1 reference
f2 = dup(f)    -> the 2-nd

close(f);
close(f2);

2 flush() calls but only 1 release() so do we need to wake up all the readers 
if the file is still valid?

So well, at least, there is no problem with the xenomai codebase, that's 
good :o)


---

Dmitry

 





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

* [Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
  2005-11-17 19:17                                   ` Gilles Chanteperdrix
@ 2005-11-17 19:45                                     ` Dmitry Adamushko
  2005-11-18  8:57                                       ` Ignacio García Pérez
  0 siblings, 1 reply; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-17 19:45 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai, xenomai-core

On Thursday 17 November 2005 20:17, you wrote:
> Dmitry Adamushko wrote:
>  > On Thursday 17 November 2005 18:24, Gilles Chanteperdrix wrote:
>  > > Dmitry Adamushko wrote:
>  > >  > > >As a conclusion, the behaviour that you observed with Xenomai
>  > >  > > >pipes seems consistent with that of Linux' named pipes, except
>  > >  > > >that in Linux read() returns 0, and not an error code as you
>  > >  > > >observed with Xenomai.
>  > >  > >
>  > >  > > The read() call does *not* return when you close the *same* file
>  > >  > > handle from another pthread in the same process.
>  > >  >
>  > >  > I confirm that and as I pointed it out in my previous mail - this
>  > >  > is not how it's supposed to be.
>  > >  > I'm currently on it. More news later.
>  > >
>  > > I am not sure about that: Linux regular pipes follow the same
>  > > behaviour (the real destruction of the file descriptor is delayed
>  > > until read() really returns).
>  >
>  > My assertion was only based on the idea that nucleus::xnpipe_release()
>  > must be
>  >
>  > called as a result of any close() from the user space.
>
> If we have a look at the sources, sys_read uses fput_light and
> fget_light, which increment and decrement the file descriptor
> reference count (member f_count of the file structure) used by fget and
> fput when the file descriptor is shared between. open and close call
> fget and fput.
>
> "release" only get called through __fput when f_count reaches 0.

Exactly, I have just found out that and posted actually a long mail just 
before getting this mail from you :o)

Yep, and before getting blocked, read() increments the counter as well, that's 
why we don't have a xnpipe_realease() called as a result of close().
So everything is correct.


---

Dmitry


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

* [Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
  2005-11-17 19:45                                     ` Dmitry Adamushko
@ 2005-11-18  8:57                                       ` Ignacio García Pérez
  2005-11-18  9:10                                         ` Dmitry Adamushko
  0 siblings, 1 reply; 53+ messages in thread
From: Ignacio García Pérez @ 2005-11-18  8:57 UTC (permalink / raw)
  To: Dmitry Adamushko; +Cc: xenomai, xenomai-core


>Exactly, I have just found out that and posted actually a long mail just 
>before getting this mail from you :o)
>
>Yep, and before getting blocked, read() increments the counter as well, that's 
>why we don't have a xnpipe_realease() called as a result of close().
>So everything is correct.
>  
>
Fine. Though then my problem is not related to xenomai, any suggestions
on how to force read() to return? (without writing anything to the other
end of the pipe)


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

* Re: [Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
  2005-11-18  8:57                                       ` Ignacio García Pérez
@ 2005-11-18  9:10                                         ` Dmitry Adamushko
  0 siblings, 0 replies; 53+ messages in thread
From: Dmitry Adamushko @ 2005-11-18  9:10 UTC (permalink / raw)
  To: Ignacio García Pérez; +Cc: xenomai, xenomai-core

[-- Attachment #1: Type: text/plain, Size: 991 bytes --]




xenomai-core-bounces@domain.hid wrote on 18.11.2005 09:57:15:

>
> >Exactly, I have just found out that and posted actually a long mail just

> >before getting this mail from you :o)
> >
> >Yep, and before getting blocked, read() increments the counter as
> well, that's
> >why we don't have a xnpipe_realease() called as a result of close().
> >So everything is correct.
> >
> >
> Fine. Though then my problem is not related to xenomai, any suggestions
> on how to force read() to return? (without writing anything to the other
> end of the pipe)

ummm... send it a certain signal with pthread_kill() (and setting up
something like thread::flag == END_OF_WORK_BABY at the same time but only
in case when there can be other cases of getting a signal by this thread)?
In such a case, read() should return -EINTR.
Note, a signal handler must be installed without a SA_RESTART flag so that
the read() will not be restarted after signal processing.


---

Dmitry

[-- Attachment #2: Type: text/html, Size: 1232 bytes --]

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

end of thread, other threads:[~2005-11-18  9:10 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-11-10 21:05 [Xenomai-help] Creation of a rt-queue from the user space ROSSIER Daniel
2005-11-11  9:30 ` [Xenomai-help] printk Ignacio García Pérez
2005-11-11 11:07   ` Dmitry Adamushko
2005-11-14 10:52     ` Ignacio García Pérez
2005-11-14 11:26       ` Philippe Gerum
2005-11-14 12:03         ` Dmitry Adamushko
2005-11-14 13:22           ` Philippe Gerum
2005-11-14 13:47             ` Philippe Gerum
2005-11-14 14:50               ` [Xenomai-core] " Dmitry Adamushko
2005-11-14 15:56                 ` [Xenomai-core] rt_pipe_* usage Ignacio García Pérez
2005-11-14 16:15                   ` [Xenomai-core] More on rt pipes usage Ignacio García Pérez
2005-11-15 13:24                     ` Philippe Gerum
2005-11-15 16:41                       ` [Xenomai-help] " Ignacio García Pérez
2005-11-14 16:23                   ` [Xenomai-core] rt_pipe_* usage Dmitry Adamushko
2005-11-14 16:36                     ` Ignacio García Pérez
2005-11-15 12:41                       ` [Xenomai-core] Web site error (API doc search) Ignacio García Pérez
2005-11-15 13:16                       ` [Xenomai-core] rt_pipe_* usage Philippe Gerum
2005-11-15 16:22                         ` Ignacio García Pérez
2005-11-16  5:38                           ` Philippe Gerum
2005-11-15  9:38                 ` [Xenomai-core] Re: [Xenomai-help] printk Philippe Gerum
2005-11-15 10:00                   ` Dmitry Adamushko
2005-11-16 12:58                     ` Philippe Gerum
2005-11-16 14:44                       ` Dmitry Adamushko
2005-11-17  9:44                       ` [Xenomai-help] Blocking reads from pipes Ignacio García Pérez
2005-11-17 10:21                         ` Romain Lenglet
2005-11-17 13:16                           ` Ignacio García Pérez
2005-11-17 15:11                             ` Dmitry Adamushko
2005-11-17 17:24                               ` Gilles Chanteperdrix
2005-11-17 17:55                                 ` [Xenomai-core] " Dmitry Adamushko
2005-11-17 19:17                                   ` Gilles Chanteperdrix
2005-11-17 19:45                                     ` Dmitry Adamushko
2005-11-18  8:57                                       ` Ignacio García Pérez
2005-11-18  9:10                                         ` Dmitry Adamushko
2005-11-17 19:40                                 ` Dmitry Adamushko
2005-11-17 10:46                         ` Dmitry Adamushko
2005-11-14 12:15       ` [Xenomai-help] xn_pipe_create [minor] Ignacio García Pérez
2005-11-14 13:53         ` Dmitry Adamushko
2005-11-14 16:28           ` Ignacio García Pérez
2005-11-14 16:29             ` Philippe Gerum
2005-11-14 16:41               ` Ignacio García Pérez
2005-11-14 16:52                 ` Dmitry Adamushko
2005-11-14 17:38                   ` Philippe Gerum
2005-11-14 18:33                     ` Dmitry Adamushko
2005-11-15  8:04                       ` Philippe Gerum
2005-11-14 18:03                   ` [Xenomai-help] Strange pipe behaviour Ignacio García Pérez
2005-11-16  5:45                     ` Philippe Gerum
2005-11-16  7:45                       ` Ignacio García Pérez
2005-11-16 11:45                         ` Philippe Gerum
2005-11-14 16:40             ` [Xenomai-help] xn_pipe_create [minor] Dmitry Adamushko
2005-11-12 19:45   ` [Xenomai-help] printk Philippe Gerum
2005-11-14 10:47   ` [Xenomai-help] Invalid characters in task's names Ignacio García Pérez
2005-11-14 11:39     ` Philippe Gerum
2005-11-11 14:08 ` [Xenomai-help] Creation of a rt-queue from the user space Jan Kiszka

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.