This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Re: Reduce stack usage of _vfiprintf_r()
- From: Federico Terraneo <fede dot tft at hotmail dot it>
- To: newlib at sourceware dot org
- Date: Wed, 10 Oct 2012 17:59:29 +0200
- Subject: Re: Reduce stack usage of _vfiprintf_r()
- References: <5075951A.3070207@op.pl>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 10/10/2012 05:32 PM, Freddie Chopin wrote:
> Hi!
>
> I'm using newlib on ARM microcontrollers that have limited amount
> of RAM ("few" to "few tens" of kilobytes). Due to design of
> _vfiprintf_r() it's almost unusable for such targets, as static
> function __sbprintf() is inlined into it - sbprintf() has a 1kB
> buffer on stack. This buffer is there for optimizing access to
> unbuffered streams, but my application does not use them and 1kB is
> a tremendous waste of space... If I would be using such buffer,
> there would be a waste of space too, as __sbprintf() recursively
> calls _vfiprintf() which would have a buffered "fake" file now, but
> still allocate 1kB on stack in case it's unbuffered...
>
> I've changed that for myself to use dynamic allocation like this
> (that's from version 1.19.0):
>
>>
>> /* * Helper function for `fprintf to unbuffered unix file':
>> creates a * temporary buffer. We only work on write-only files;
>> this avoids * worries about ungetc buffers and so forth. */
>> static int _DEFUN(__sbprintf, (rptr, fp, fmt, ap), struct _reent
>> *rptr _AND register FILE *fp _AND _CONST char *fmt _AND
>> va_list ap) { int ret; FILE fake; unsigned char *buf;
>>
>> /* copy the important variables */ fake._flags = fp->_flags &
>> ~__SNBF; fake._flags2 = fp->_flags2; fake._file = fp->_file;
>> fake._cookie = fp->_cookie; fake._write = fp->_write;
>>
>> buf = _malloc_r(rptr, BUFSIZ);
>>
>> if (buf == NULL) return EOF;
>>
>> /* set up the buffer */ fake._bf._base = fake._p = buf;
>> fake._bf._size = fake._w = BUFSIZ; fake._lbfsize = 0; /* not
>> actually used, but Just In Case */ #ifndef __SINGLE_THREAD__
>> __lock_init_recursive (fake._lock); #endif
>>
>> /* do the work, then copy any error status */ ret = _VFPRINTF_R
>> (rptr, &fake, fmt, ap); if (ret >= 0 && _fflush_r (rptr, &fake))
>> ret = EOF; if (fake._flags & __SERR) fp->_flags |= __SERR;
>>
>> _free_r(rptr, buf);
>>
>> #ifndef __SINGLE_THREAD__ __lock_close_recursive (fake._lock);
>> #endif return (ret); }
>
> I can provide a patch against current trunk if you think this
> solution is reasonable - I hope you do, because such a waste of
> stack on small microcontrollers is unacceptable...
>
> Regards, Freddie Chopin
>
>
Hi,
first of all, am not a newlib devloper, just a regular user. I noticed
the exact same problem in RAM constrained ARM microcontrollers when
using newlib together with an RTOS that I developed. The solution I
found is different though, and is to apply a simple patch to newlib
that redefines BUFSIZ to 512 instead of 1024. That small change later
became part of a larger patch that can be found here:
http://gitorious.org/miosix-kernel/miosix-kernel/blobs/master/miosix/compiler/gcc-patches/newlib.patch
The relevant lines are 32--39.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://www.enigmail.net/
iQEcBAEBAgAGBQJQdZtWAAoJECkLFtN5Xr9fkeIIALemtaNysiK1B/wbhSN35Xfq
tnCSTMm/qD2nU5OUR3J7Eir+aQU4Eui4pTlbR3q5/rOzQteA+hyqPXcpJcOwwjJA
D+OZIznjzyd8MqZqpFKGS6zBgRdVl5mTE0stInAc/P8Mz9V2ByHRFwDQMHverOlG
2gQGIOQ5qSFwgwmNWiplzs3oFS9ychxJoJSfyN8zJGP0tw4hYD/mtYVSRQ4qNWWh
mBAxCNhf5sRAPwZiczsbFAs1TTC6P0zPPljCXegRHRE/4TpFsFC9pf9SAPEGPwa4
KIro/gQBdQhxqrVgWldNfz4CM9s5KePMFFL1FX5eDCxk7E32qFfghqHQ4vz8SVw=
=/6gR
-----END PGP SIGNATURE-----