public inbox for ecos-discuss@sourceware.org
 help / color / mirror / Atom feed
* [ECOS] uSTL hello world
@ 2009-08-28 15:22 John Dallaway
  2009-09-01  8:36 ` [ECOS] " cetoni GmbH - Uwe Kindler
  0 siblings, 1 reply; 14+ messages in thread
From: John Dallaway @ 2009-08-28 15:22 UTC (permalink / raw)
  To: Uwe Kindler; +Cc: eCos Discussion

Hi Uwe

There seems to be a problem with the uSTL hello world example given in
the uSTL documentation. The code produces no output. However, if I add a
printf() call after the cout.flush(), then I see _both_ messages.

This is not a case of printf() flushing the output - I can observe the
output from cout on the diagnostics channel _before_ the call to
printf() is made. In fact, if I move the printf() call to the start of
main(), then everything still works.

eCos was configured with default template, pc_i82559 target, ustl and
fileio packages added, no optimization. Debugging via RedBoot over ethernet.

Does the hello world example work unmodified on your own hardware platform?

John Dallaway

--cut here--

#include <ustl.h>
//#include <stdio.h>
using namespace ustl;

int main (int argc, char* argv[])
{
    cout << "Hello world!\n";
    cout.flush();
//    printf("Hello printf!\n");
    return EXIT_SUCCESS;
}


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

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

* [ECOS] Re: uSTL hello world
  2009-08-28 15:22 [ECOS] uSTL hello world John Dallaway
@ 2009-09-01  8:36 ` cetoni GmbH - Uwe Kindler
  2009-09-01  9:03   ` John Dallaway
  2009-09-01 13:28   ` John Dallaway
  0 siblings, 2 replies; 14+ messages in thread
From: cetoni GmbH - Uwe Kindler @ 2009-09-01  8:36 UTC (permalink / raw)
  To: John Dallaway; +Cc: ecos-discuss

Hi John,

> There seems to be a problem with the uSTL hello world example given in
> the uSTL documentation. The code produces no output. However, if I add a
> printf() call after the cout.flush(), then I see _both_ messages.
> 
> This is not a case of printf() flushing the output - I can observe the
> output from cout on the diagnostics channel _before_ the call to
> printf() is made. In fact, if I move the printf() call to the start of
> main(), then everything still works.

I can confirm this on my target. For me it smells like a linker issue. I 
wrote the following main function from the example an added a test 
function with a printf call that is not called from main.

void test()
{
     printf("Hello printf2!\n");
}

int main (int argc, char* argv[])
{
     cout << "Hello world!\n";
     cout.flush();
     return EXIT_SUCCESS;
}

If I execute main then I can see the output of cout. If I remove the 
test function with the printf reference then the main function does not 
print anything. So adding a printf reference makes cout working - so I 
think this is a linker issue.

The stream objects are declared in the file ofstream.cpp:

#ifdef CYGVAR_USTL_CIN_COUT_CERR
ifstream cin  (STDIN_FILENO);
ofstream cout (STDOUT_FILENO);
ofstream cerr (STDERR_FILENO);
#endif

For the creation of these objects there is no constructor priority set - 
could this be the problem? Maybe the stream objects are created prior to 
the creation of the libc stream objects. In the uSTL code there is no 
explicit printf reference. It only uses vsnprintf.

Uwe

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

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

* [ECOS] Re: uSTL hello world
  2009-09-01  8:36 ` [ECOS] " cetoni GmbH - Uwe Kindler
@ 2009-09-01  9:03   ` John Dallaway
  2009-09-01 12:22     ` cetoni GmbH - Uwe Kindler
  2009-09-01 13:28   ` John Dallaway
  1 sibling, 1 reply; 14+ messages in thread
From: John Dallaway @ 2009-09-01  9:03 UTC (permalink / raw)
  To: Uwe Kindler; +Cc: ecos-discuss

Hi Uwe

Uwe Kindler wrote:

> I can confirm this on my target. For me it smells like a linker issue.

I agree that this smells like a linker issue. Does the problem still
occur if you link without -Wl,--gc-sections ?

John Dallaway

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

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

* [ECOS] Re: uSTL hello world
  2009-09-01  9:03   ` John Dallaway
@ 2009-09-01 12:22     ` cetoni GmbH - Uwe Kindler
  0 siblings, 0 replies; 14+ messages in thread
From: cetoni GmbH - Uwe Kindler @ 2009-09-01 12:22 UTC (permalink / raw)
  To: John Dallaway; +Cc: ecos-discuss

Hi John,


> I agree that this smells like a linker issue. Does the problem still
> occur if you link without -Wl,--gc-sections ?

Yes the problem does still occur.

Regards, Uwe

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

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

* [ECOS] Re: uSTL hello world
  2009-09-01  8:36 ` [ECOS] " cetoni GmbH - Uwe Kindler
  2009-09-01  9:03   ` John Dallaway
@ 2009-09-01 13:28   ` John Dallaway
  2009-09-08 15:14     ` cetoni GmbH - Uwe Kindler
  1 sibling, 1 reply; 14+ messages in thread
From: John Dallaway @ 2009-09-01 13:28 UTC (permalink / raw)
  To: Uwe Kindler; +Cc: ecos-discuss

Hi Uwe

Uwe Kindler wrote:

> The stream objects are declared in the file ofstream.cpp:
> 
> #ifdef CYGVAR_USTL_CIN_COUT_CERR
> ifstream cin  (STDIN_FILENO);
> ofstream cout (STDOUT_FILENO);
> ofstream cerr (STDERR_FILENO);
> #endif
> 
> For the creation of these objects there is no constructor priority set -
> could this be the problem? Maybe the stream objects are created prior to
> the creation of the libc stream objects. In the uSTL code there is no
> explicit printf reference. It only uses vsnprintf.

The libc static constructors are at priority 56000+ so should be called
before uSTL constructors at the default priority of 65535. So I don't
think this is the problem. Nevertheless, uSTL static objects should
probably be constructed with elevated priority in case they are needed
within application-level static constructors. Something to think about.

Back to the original problem. It may be easiest to drill down into the
cout call hierarchy under debug and compare with the equivalent call
stack from a working application in order to narrow the problem search
space.

John Dallaway

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

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

* [ECOS] Re: uSTL hello world
  2009-09-01 13:28   ` John Dallaway
@ 2009-09-08 15:14     ` cetoni GmbH - Uwe Kindler
  2009-09-08 15:59       ` John Dallaway
  0 siblings, 1 reply; 14+ messages in thread
From: cetoni GmbH - Uwe Kindler @ 2009-09-08 15:14 UTC (permalink / raw)
  To: John Dallaway; +Cc: ecos-discuss

Hi John,

> Back to the original problem. It may be easiest to drill down into the
> cout call hierarchy under debug and compare with the equivalent call
> stack from a working application in order to narrow the problem search
> space.
> 
> John Dallaway

O.k. - I did this and here are my results.

In both situations (reference to printf exists and no reference to 
printf exists in main.cpp) the call cout << "Hello world!\n" brings us 
into the function readwritev() in fileio/io.cxx. In this file the lines 
105 - 108 makes the difference:

     fp = cyg_fp_get( fd );

     if( fp == NULL )
         FILEIO_RETURN(EBADF);

If a printf call is present in main.cpp then cyg_fp_get() returns a 
valid file pointer. If no printf call is present in main.cpp the 
cyg_fp_get() returns 0 and the function returns with EBADF.

Here are the local variables in readwritev() with printf:

fd	0x1	
_iov	0xa0140948	
iov_len	0x1	
direction	0x2	
cnt	0xd	
len	0xd	
ret	0x11110008	
_idx	0x1	
fp	0xa0140d90	
iov	0xa014086c	
uio	{...}	
op	0xa014095c

and here are the locals in readwritev() without printf in main:

fd	0x1	
_iov	0xa013d5e8	
iov_len	0x1	
direction	0x2	
cnt	0x11110006	
len	0xd	
ret	0x11110008	
_idx	0x1	
fp	0x00000000	
iov	0xa013d50c	
uio	{...}	
op	0xa013d5fc

Any idea what is going wrong here before I dig even more deeper?

Regards, Uwe





-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

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

* [ECOS] Re: uSTL hello world
  2009-09-08 15:14     ` cetoni GmbH - Uwe Kindler
@ 2009-09-08 15:59       ` John Dallaway
  2009-09-09  7:00         ` cetoni GmbH - Uwe Kindler
  0 siblings, 1 reply; 14+ messages in thread
From: John Dallaway @ 2009-09-08 15:59 UTC (permalink / raw)
  To: Uwe Kindler; +Cc: ecos-discuss

Hi Uwe

Uwe Kindler wrote:

> 
>> Back to the original problem. It may be easiest to drill down into the
>> cout call hierarchy under debug and compare with the equivalent call
>> stack from a working application in order to narrow the problem search
>> space.
>>
>> John Dallaway
> 
> O.k. - I did this and here are my results.
> 
> In both situations (reference to printf exists and no reference to
> printf exists in main.cpp) the call cout << "Hello world!\n" brings us
> into the function readwritev() in fileio/io.cxx. In this file the lines
> 105 - 108 makes the difference:
> 
>     fp = cyg_fp_get( fd );
> 
>     if( fp == NULL )
>         FILEIO_RETURN(EBADF);
> 
> If a printf call is present in main.cpp then cyg_fp_get() returns a
> valid file pointer. If no printf call is present in main.cpp the
> cyg_fp_get() returns 0 and the function returns with EBADF.
> 
> Here are the local variables in readwritev() with printf:
> 
> fd    0x1   
> _iov    0xa0140948   
> iov_len    0x1   
> direction    0x2   
> cnt    0xd   
> len    0xd   
> ret    0x11110008   
> _idx    0x1   
> fp    0xa0140d90   
> iov    0xa014086c   
> uio    {...}   
> op    0xa014095c
> 
> and here are the locals in readwritev() without printf in main:
> 
> fd    0x1   
> _iov    0xa013d5e8   
> iov_len    0x1   
> direction    0x2   
> cnt    0x11110006   
> len    0xd   
> ret    0x11110008   
> _idx    0x1   
> fp    0x00000000   
> iov    0xa013d50c   
> uio    {...}   
> op    0xa013d5fc
> 
> Any idea what is going wrong here before I dig even more deeper?

The file descriptor (fd) is unchanged between working and non-working
code which suggests that the relevant descriptor table entry is not
being initialised. Try planting breakpoints at cyg_fd_assign() and
cyg_fd_alloc(). I expect these will be called in the case where cout is
working and the call stack may provide a clue as to what is triggering
the correct behaviour.

John Dallaway

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

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

* [ECOS] Re: uSTL hello world
  2009-09-08 15:59       ` John Dallaway
@ 2009-09-09  7:00         ` cetoni GmbH - Uwe Kindler
  2009-09-09 11:55           ` John Dallaway
  0 siblings, 1 reply; 14+ messages in thread
From: cetoni GmbH - Uwe Kindler @ 2009-09-09  7:00 UTC (permalink / raw)
  To: John Dallaway; +Cc: ecos-discuss

Hi John,

> The file descriptor (fd) is unchanged between working and non-working
> code which suggests that the relevant descriptor table entry is not
> being initialised. Try planting breakpoints at cyg_fd_assign() and
> cyg_fd_alloc(). I expect these will be called in the case where cout is
> working and the call stack may provide a clue as to what is triggering
> the correct behaviour.

O.k. I followed your suggestions and that are my results.

If printf exists in main.cpp then both functions cyg_fd_assign() and 
cyg_fd_alloc() will get called for stdin and stdout. At the end of this 
message there is the call stack for stdin.

If printf is not present in main, then both functions will not get 
called for stdin and stdout and I think I now know why. In the ustl 
package in ofstream.cpp the streams are not created because the streams 
(cout, cin, cerr) are declared this way:

ifstream cin  (STDIN_FILENO);
ofstream cout (STDOUT_FILENO);
ofstream cerr (STDERR_FILENO);

That means they use the fileno to open the streams - they do not create 
them. But the streams are not present, because no function uses stdout, 
stdin, that means there are no references and the linker throws stdout 
and stdin away. This is the reason why the static constructors of stdout 
and stdin are never get called.

Here is my proposal to solve this problem. I changed the declaration of 
cout, cin and cerr this way:

ifstream cin  (((Cyg_StdioStream *)stdin)->get_dev());
ofstream cout (((Cyg_StdioStream *)stdout)->get_dev());
ofstream cerr (((Cyg_StdioStream *)stderr)->get_dev());

This ensures that stdout, stdin and stderr are created. After this 
change cyg_fd_assign() and cyg_fd_alloc() will get called if there is no 
printf function in main.cpp. The call cout << "Hello world!\n" works 
now. I noticed that the message is already printed before cout.flush() 
is called. So it seems cout.flush() is not required if a proper serial 
driver is used. If I use the diagnostic serial driver, then I always 
needed to call cout.flush().

If you agree to my proposal then I will provide a patch.

Regards, Uwe



Thread [1] (Suspended: Breakpoint hit.)	
7 cyg_fd_alloc() 
opt\ecos\ecos\packages\io\fileio\current\src\fd.cxx:230 0xa011d3a8	
6 open() \opt\ecos\ecos\packages\io\fileio\current\src\file.cxx:205 
0xa011f448	
5 cyg_stdio_open() 
\home\Nutzer\final_ustl_0D_install\include\cyg\libc\stdio\io.inl:101 
0xa0130228	
4 Cyg_libc_stdio_find_filename() 
\opt\ecos\ecos\packages\language\c\libc\stdio\current\src\common\stdiosupp.cxx:76 
0xa01302c0	
3 __static_initialization_and_destruction_0() 
\opt\ecos\ecos\packages\language\c\libc\stdio\current\src\common\stdin.cxx:86 
0xa013000c	
2 _GLOBAL__I.56000_cyg_libc_stdio_stdin() 
\opt\ecos\ecos\packages\language\c\libc\stdio\current\src\common\stdin.cxx:107 
0xa01300c4	
1 cyg_hal_invoke_constructors() 
\opt\ecos\ecos\packages\hal\arm\arch\current\src\hal_misc.c:213 0xa0104458

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

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

* [ECOS] Re: uSTL hello world
  2009-09-09  7:00         ` cetoni GmbH - Uwe Kindler
@ 2009-09-09 11:55           ` John Dallaway
  2009-09-10  0:32             ` Jonathan Larmour
  0 siblings, 1 reply; 14+ messages in thread
From: John Dallaway @ 2009-09-09 11:55 UTC (permalink / raw)
  To: Uwe Kindler, Jonathan Larmour; +Cc: ecos-discuss

Hi Uwe and Jifl

Uwe Kindler wrote:

> If printf is not present in main, then both functions will not get
> called for stdin and stdout and I think I now know why. In the ustl
> package in ofstream.cpp the streams are not created because the streams
> (cout, cin, cerr) are declared this way:
> 
> ifstream cin  (STDIN_FILENO);
> ofstream cout (STDOUT_FILENO);
> ofstream cerr (STDERR_FILENO);
> 
> That means they use the fileno to open the streams - they do not create
> them. But the streams are not present, because no function uses stdout,
> stdin, that means there are no references and the linker throws stdout
> and stdin away. This is the reason why the static constructors of stdout
> and stdin are never get called.
> 
> Here is my proposal to solve this problem. I changed the declaration of
> cout, cin and cerr this way:
> 
> ifstream cin  (((Cyg_StdioStream *)stdin)->get_dev());
> ofstream cout (((Cyg_StdioStream *)stdout)->get_dev());
> ofstream cerr (((Cyg_StdioStream *)stderr)->get_dev());
> 
> This ensures that stdout, stdin and stderr are created. After this
> change cyg_fd_assign() and cyg_fd_alloc() will get called if there is no
> printf function in main.cpp. The call cout << "Hello world!\n" works
> now. I noticed that the message is already printed before cout.flush()
> is called. So it seems cout.flush() is not required if a proper serial
> driver is used. If I use the diagnostic serial driver, then I always
> needed to call cout.flush().
> 
> If you agree to my proposal then I will provide a patch.

Uwe, congratulations on tracking this down. Your analysis makes good sense.

Jifl, is there a preferred way to ensure initialisation of the stdio
streams in the file descriptor table? I note that open() in the file I/O
package uses:

    CYG_REFERENCE_OBJECT(stdin);
    CYG_REFERENCE_OBJECT(stdout);
    CYG_REFERENCE_OBJECT(stderr);

Is this addressing the same issue that we're observing with uSTL?

John Dallaway

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

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

* [ECOS] Re: uSTL hello world
  2009-09-09 11:55           ` John Dallaway
@ 2009-09-10  0:32             ` Jonathan Larmour
  2009-09-11 19:25               ` Bart Veer
  0 siblings, 1 reply; 14+ messages in thread
From: Jonathan Larmour @ 2009-09-10  0:32 UTC (permalink / raw)
  To: John Dallaway; +Cc: Uwe Kindler, ecos-discuss, Nick Garnett

[ NB Nick, see below... ]

John Dallaway wrote:
> Uwe Kindler wrote:
>>If printf is not present in main, then both functions will not get
>>called for stdin and stdout and I think I now know why. In the ustl
>>package in ofstream.cpp the streams are not created because the streams
>>(cout, cin, cerr) are declared this way:
>>
>>ifstream cin  (STDIN_FILENO);
>>ofstream cout (STDOUT_FILENO);
>>ofstream cerr (STDERR_FILENO);
>>
>>That means they use the fileno to open the streams - they do not create
>>them. But the streams are not present, because no function uses stdout,
>>stdin, that means there are no references and the linker throws stdout
>>and stdin away. This is the reason why the static constructors of stdout
>>and stdin are never get called.
>>
>>Here is my proposal to solve this problem. I changed the declaration of
>>cout, cin and cerr this way:
>>
>>ifstream cin  (((Cyg_StdioStream *)stdin)->get_dev());
>>ofstream cout (((Cyg_StdioStream *)stdout)->get_dev());
>>ofstream cerr (((Cyg_StdioStream *)stderr)->get_dev());
>>
>>This ensures that stdout, stdin and stderr are created. After this
>>change cyg_fd_assign() and cyg_fd_alloc() will get called if there is no
>>printf function in main.cpp. The call cout << "Hello world!\n" works
>>now. I noticed that the message is already printed before cout.flush()
>>is called. So it seems cout.flush() is not required if a proper serial
>>driver is used. If I use the diagnostic serial driver, then I always
>>needed to call cout.flush().
>>
>>If you agree to my proposal then I will provide a patch.
> 
> 
> Uwe, congratulations on tracking this down. Your analysis makes good sense.
> 
> Jifl, is there a preferred way to ensure initialisation of the stdio
> streams in the file descriptor table? I note that open() in the file I/O
> package uses:
> 
>     CYG_REFERENCE_OBJECT(stdin);
>     CYG_REFERENCE_OBJECT(stdout);
>     CYG_REFERENCE_OBJECT(stderr);
> 
> Is this addressing the same issue that we're observing with uSTL?

I think there's a more fundamental problem, not specific to uSTL (so I 
think Uwe's workaround isn't really appropriate). That is that something like:

   write(STDOUT_FILENO, buf, n);

can't be guaranteed to just work, at present. That's a bug.

I think those CYG_REFERENCE_OBJECT lines (and surrounding ifdef) need to 
move out of open() and into cyg_fd_init(). Theoretically cyg_fp_get() 
would be slightly better, but that is called a lot, and there is a trivial 
but non-zero overhead to CYG_REFERENCE_OBJECT. I'd appreciate Nick's 
opinion on this proposal if possible though. It does mean that including 
the fileio package at all in a configuration would then guarantee pulling 
in stdin/stdout/stderr, even irrespective of use. Maybe the number of 
people this would affect is too small to care about. Maybe there should be 
a default-enabled option, to allow it to be turned off to remove that 
dependency.

Taking the usual principle of "leave it to the user", I think I'd 
personally lean towards the latter.

Jifl
-- 
--["No sense being pessimistic, it wouldn't work anyway"]-- Opinions==mine

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

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

* Re: [ECOS] Re: uSTL hello world
  2009-09-10  0:32             ` Jonathan Larmour
@ 2009-09-11 19:25               ` Bart Veer
  2009-09-12  2:49                 ` Jonathan Larmour
  0 siblings, 1 reply; 14+ messages in thread
From: Bart Veer @ 2009-09-11 19:25 UTC (permalink / raw)
  To: Jonathan Larmour; +Cc: ecos-discuss

>>>>> "Jifl" == Jonathan Larmour <jifl@jifvik.org> writes:

    <snip>
    
    >> Jifl, is there a preferred way to ensure initialisation of the
    >> stdio streams in the file descriptor table? I note that open()
    >> in the file I/O package uses:
    >> 
    >> CYG_REFERENCE_OBJECT(stdin);
    >> CYG_REFERENCE_OBJECT(stdout);
    >> CYG_REFERENCE_OBJECT(stderr);
    >> 
    >> Is this addressing the same issue that we're observing with
    >> uSTL?

    Jifl> I think there's a more fundamental problem, not specific to
    Jifl> uSTL (so I think Uwe's workaround isn't really appropriate).
    Jifl> That is that something like:

    Jifl>    write(STDOUT_FILENO, buf, n);

    Jifl> can't be guaranteed to just work, at present. That's a bug.

    Jifl> I think those CYG_REFERENCE_OBJECT lines (and surrounding
    Jifl> ifdef) need to move out of open() and into cyg_fd_init().
    Jifl> Theoretically cyg_fp_get() would be slightly better, but
    Jifl> that is called a lot, and there is a trivial but non-zero
    Jifl> overhead to CYG_REFERENCE_OBJECT. I'd appreciate Nick's
    Jifl> opinion on this proposal if possible though. It does mean
    Jifl> that including the fileio package at all in a configuration
    Jifl> would then guarantee pulling in stdin/stdout/stderr, even
    Jifl> irrespective of use. Maybe the number of people this would
    Jifl> affect is too small to care about. Maybe there should be a
    Jifl> default-enabled option, to allow it to be turned off to
    Jifl> remove that dependency.

    Jifl> Taking the usual principle of "leave it to the user", I
    Jifl> think I'd personally lean towards the latter.

I think there is another approach which might fit in better with
linker garbage collection. Instead of #define'ing STDOUT_FILENO as 1,
declare it as an extern const char. Then provide the variable
STDOUT_FILENO in some module which causes the necessary initialization
to happen. It is slightly more expensive: a bit of space for the const
variable, an extra memory access for the write() call. However it
would eliminate the need for CYG_REFERENCE_OBJECT's and it would allow
linker garbage collection to work as normal.

Obviously code which uses write(1, buf, n) would still be broken, and
http://www.opengroup.org/onlinepubs/009695399/basedefs/unistd.h.html
requires that STDOUT_FILENO be defined as 1. Hence my proposal would
not be fully standards-compliant.

Bart

-- 
Bart Veer                                   eCos Configuration Architect
eCosCentric Limited    The eCos experts      http://www.ecoscentric.com/
Barnwell House, Barnwell Drive, Cambridge, UK.      Tel: +44 1223 245571
Registered in England and Wales: Reg No 4422071.
 >>>> Visit us at ESC-Boston  http://www.embedded.com/esc/boston <<<<
 >>>> Sep 22-23 on Stand 226  at Hynes Convention Center, Boston <<<<

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

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

* Re: [ECOS] Re: uSTL hello world
  2009-09-11 19:25               ` Bart Veer
@ 2009-09-12  2:49                 ` Jonathan Larmour
  2009-09-29 14:28                   ` Bart Veer
  0 siblings, 1 reply; 14+ messages in thread
From: Jonathan Larmour @ 2009-09-12  2:49 UTC (permalink / raw)
  To: Bart Veer; +Cc: ecos-discuss

Bart Veer wrote:
>>>>>>"Jifl" == Jonathan Larmour <jifl@jifvik.org> writes:
> 
> 
>     <snip>
>     
>     >> Jifl, is there a preferred way to ensure initialisation of the
>     >> stdio streams in the file descriptor table? I note that open()
>     >> in the file I/O package uses:
>     >> 
>     >> CYG_REFERENCE_OBJECT(stdin);
>     >> CYG_REFERENCE_OBJECT(stdout);
>     >> CYG_REFERENCE_OBJECT(stderr);
>     >> 
>     >> Is this addressing the same issue that we're observing with
>     >> uSTL?
> 
>     Jifl> I think there's a more fundamental problem, not specific to
>     Jifl> uSTL (so I think Uwe's workaround isn't really appropriate).
>     Jifl> That is that something like:
> 
>     Jifl>    write(STDOUT_FILENO, buf, n);
> 
>     Jifl> can't be guaranteed to just work, at present. That's a bug.
> 
>     Jifl> I think those CYG_REFERENCE_OBJECT lines (and surrounding
>     Jifl> ifdef) need to move out of open() and into cyg_fd_init().
>     Jifl> Theoretically cyg_fp_get() would be slightly better, but
>     Jifl> that is called a lot, and there is a trivial but non-zero
>     Jifl> overhead to CYG_REFERENCE_OBJECT. I'd appreciate Nick's
>     Jifl> opinion on this proposal if possible though. It does mean
>     Jifl> that including the fileio package at all in a configuration
>     Jifl> would then guarantee pulling in stdin/stdout/stderr, even
>     Jifl> irrespective of use. Maybe the number of people this would
>     Jifl> affect is too small to care about. Maybe there should be a
>     Jifl> default-enabled option, to allow it to be turned off to
>     Jifl> remove that dependency.
> 
>     Jifl> Taking the usual principle of "leave it to the user", I
>     Jifl> think I'd personally lean towards the latter.
> 
> I think there is another approach which might fit in better with
> linker garbage collection. Instead of #define'ing STDOUT_FILENO as 1,
> declare it as an extern const char. Then provide the variable
> STDOUT_FILENO in some module which causes the necessary initialization
> to happen. It is slightly more expensive: a bit of space for the const
> variable, an extra memory access for the write() call. However it
> would eliminate the need for CYG_REFERENCE_OBJECT's and it would allow
> linker garbage collection to work as normal.
> 
> Obviously code which uses write(1, buf, n) would still be broken, and
> http://www.opengroup.org/onlinepubs/009695399/basedefs/unistd.h.html
> requires that STDOUT_FILENO be defined as 1. Hence my proposal would
> not be fully standards-compliant.

While that's an interesting workaround, I think your last paragraph is the 
killer, chiefly because I think write(1, buf, n) should still be able to 
work. *However*, maybe the config option could instead be between 
standards compliant mode, and "not quite right, but may often still work" 
mode.

Unfortunately we have another problem. I've looked at the output of our 
recent compilers, and I see that CYG_REFERENCE_OBJECT no longer appears to 
be effective :-(. The reference gets removed by more aggressive compiler 
optimisation at -O2. This is a much wider problem than just stdin/out/err 
of course.

Solving that efficiently may be difficult (although I don't consider the 
current implementation to necessarily be efficient either, when it worked, 
anyway). Managing to get the reference into .text/.rodata would probably 
be better than .data/.bss. Even better would be if it were possible to 
play tricks to get it into a non-loadable section, although that starts to 
venture into the world of HAL-specific stuff. I see a .comment section 
though. Something along those lines might work (and by overridable by 
specific HALs if needed).

But I've experimented (admittedly briefly) and not got as far as even 
making the reference. I've tried using various attributes, nested 
functions, volatiles, embedding  asm(".word " #__object__ ";"), etc. It 
may be that we can only do this properly using HAL-specific inline asm 
:-(. The least worst idea I've had which actually creates a reference is 
to have a real function cyg_reference_object(void*) and call it with the 
address of the object to reference, but which returns immediately.

Any other ideas? At least there are not many uses of CYG_REFERENCE_OBJECT.

Jifl
-- 
--["No sense being pessimistic, it wouldn't work anyway"]-- Opinions==mine

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

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

* Re: [ECOS] Re: uSTL hello world
  2009-09-12  2:49                 ` Jonathan Larmour
@ 2009-09-29 14:28                   ` Bart Veer
  2009-09-29 15:36                     ` Jonathan Larmour
  0 siblings, 1 reply; 14+ messages in thread
From: Bart Veer @ 2009-09-29 14:28 UTC (permalink / raw)
  To: Jonathan Larmour; +Cc: ecos-discuss

>>>>> "Jifl" == Jonathan Larmour <jifl@jifvik.org> writes:

    <snip>

    Jifl> Unfortunately we have another problem. I've looked at the
    Jifl> output of our recent compilers, and I see that
    Jifl> CYG_REFERENCE_OBJECT no longer appears to be effective :-(.
    Jifl> The reference gets removed by more aggressive compiler
    Jifl> optimisation at -O2. This is a much wider problem than just
    Jifl> stdin/out/err of course.

    Jifl> Solving that efficiently may be difficult (although I don't
    Jifl> consider the current implementation to necessarily be
    Jifl> efficient either, when it worked, anyway). Managing to get
    Jifl> the reference into .text/.rodata would probably be better
    Jifl> than .data/.bss. Even better would be if it were possible to
    Jifl> play tricks to get it into a non-loadable section, although
    Jifl> that starts to venture into the world of HAL-specific stuff.
    Jifl> I see a .comment section though. Something along those lines
    Jifl> might work (and by overridable by specific HALs if needed).

    Jifl> But I've experimented (admittedly briefly) and not got as
    Jifl> far as even making the reference. I've tried using various
    Jifl> attributes, nested functions, volatiles, embedding
    Jifl> asm(".word " #__object__ ";"), etc. It may be that we can
    Jifl> only do this properly using HAL-specific inline asm :-(. The
    Jifl> least worst idea I've had which actually creates a reference
    Jifl> is to have a real function cyg_reference_object(void*) and
    Jifl> call it with the address of the object to reference, but
    Jifl> which returns immediately.

    Jifl> Any other ideas? At least there are not many uses of
    Jifl> CYG_REFERENCE_OBJECT.

I think the following may do the trick:

----------------------------------------------------------------------------
// The unused attribute stops the compiler warning about the variable
// not being used.
// The used attribute prevents the compiler from optimizing it away.

#define NEW_CYG_REFERENCE_OBJECT(__object__)                            \
    CYG_MACRO_START                                                     \
    static const void*  __cygvar_discard_me__                           \
    __attribute__ ((unused, used)) = (const void*)&(__object__);        \
    CYG_MACRO_END
----------------------------------------------------------------------------

I have tried it in a simple testcase at -O2. The compiler does not
optimize away __cygvar_discard_me__ because the used attribute
prevents that. Hence the referenced object gets pulled in during the
link. Subsequently linker garbage collection eliminates
__cygvar_discard_me__. If the referenced object is a C++ object then
it will be preserved because of the KEEP(*.ctors) in the linker
script. So, even though it seems peculiar to have a variable both used
and unused, that combo appears to do what we want and should be fully
portable.

Looking at the gcc ChangeLog-2001, attribute(used) was added on
2001-10-18 so has probably been available since gcc 3.1 days. However
there is a comment in cyg_type.h associated with CYGBLD_ATTRIB_USED
claiming >= 3.3.2.

Let me know if it still does not solve the problem in al cases, and I
can investigate further.

Bart

-- 
Bart Veer                                   eCos Configuration Architect
eCosCentric Limited    The eCos experts      http://www.ecoscentric.com/
Barnwell House, Barnwell Drive, Cambridge, UK.      Tel: +44 1223 245571
Registered in England and Wales: Reg No 4422071.
       >>>> Visit us at ESC-UK  http://www.embedded.co.uk <<<<
       >>>> Oct 7-8 on Stand 433 at FIVE ISC, Farnborough <<<<

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

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

* Re: [ECOS] Re: uSTL hello world
  2009-09-29 14:28                   ` Bart Veer
@ 2009-09-29 15:36                     ` Jonathan Larmour
  0 siblings, 0 replies; 14+ messages in thread
From: Jonathan Larmour @ 2009-09-29 15:36 UTC (permalink / raw)
  To: Bart Veer; +Cc: ecos-discuss, Uwe Kindler

Bart Veer wrote:
>>>>>>"Jifl" == Jonathan Larmour <jifl@jifvik.org> writes:
> 
> 
>     <snip>
> 
>     Jifl> Unfortunately we have another problem. I've looked at the
>     Jifl> output of our recent compilers, and I see that
>     Jifl> CYG_REFERENCE_OBJECT no longer appears to be effective :-(.
[snip failed attempts to resolve]
>     Jifl> Any other ideas? At least there are not many uses of
>     Jifl> CYG_REFERENCE_OBJECT.
> 
> I think the following may do the trick:
> 
> ----------------------------------------------------------------------------
> // The unused attribute stops the compiler warning about the variable
> // not being used.
> // The used attribute prevents the compiler from optimizing it away.
> 
> #define NEW_CYG_REFERENCE_OBJECT(__object__)                            \
>     CYG_MACRO_START                                                     \
>     static const void*  __cygvar_discard_me__                           \
>     __attribute__ ((unused, used)) = (const void*)&(__object__);        \
>     CYG_MACRO_END
> ----------------------------------------------------------------------------
> 
> I have tried it in a simple testcase at -O2. The compiler does not
> optimize away __cygvar_discard_me__ because the used attribute
> prevents that. Hence the referenced object gets pulled in during the
> link. Subsequently linker garbage collection eliminates
> __cygvar_discard_me__. If the referenced object is a C++ object then
> it will be preserved because of the KEEP(*.ctors) in the linker
> script. So, even though it seems peculiar to have a variable both used
> and unused, that combo appears to do what we want and should be fully
> portable.

That does seem very peculiar, but if it works....

> Looking at the gcc ChangeLog-2001, attribute(used) was added on
> 2001-10-18 so has probably been available since gcc 3.1 days. However
> there is a comment in cyg_type.h associated with CYGBLD_ATTRIB_USED
> claiming >= 3.3.2.

ISTR something about the behaviour of that attribute changing at some 
point- perhaps it was buggy before. We could ifdef CYG_REFERENCE_OBJECT 
based on GCC version easily enough.

> Let me know if it still does not solve the problem in al cases, and I
> can investigate further.

Now I think it's back to Uwe to verify that this, in combination with the 
stuff I mentioned before, does resolve his uSTL problems.

Uwe?

Even better if you can submit an associated patch.

Jifl
-- 
--["No sense being pessimistic, it wouldn't work anyway"]-- Opinions==mine

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

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

end of thread, other threads:[~2009-09-29 15:36 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-28 15:22 [ECOS] uSTL hello world John Dallaway
2009-09-01  8:36 ` [ECOS] " cetoni GmbH - Uwe Kindler
2009-09-01  9:03   ` John Dallaway
2009-09-01 12:22     ` cetoni GmbH - Uwe Kindler
2009-09-01 13:28   ` John Dallaway
2009-09-08 15:14     ` cetoni GmbH - Uwe Kindler
2009-09-08 15:59       ` John Dallaway
2009-09-09  7:00         ` cetoni GmbH - Uwe Kindler
2009-09-09 11:55           ` John Dallaway
2009-09-10  0:32             ` Jonathan Larmour
2009-09-11 19:25               ` Bart Veer
2009-09-12  2:49                 ` Jonathan Larmour
2009-09-29 14:28                   ` Bart Veer
2009-09-29 15:36                     ` Jonathan Larmour

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).