This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Reduce stack usage of _vfiprintf_r()


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]