newlib-nano ignores setvbuf?

Asked by Peter A. Bigot

With -specs=nosys.specs and implementing _write_r() I find that printf() collects input until a newline, then flushes.

Calling setvbuf(stdout, NULL, _IONBF, 0) removes the buffering, as expected.

When -specs=nano.specs is added, setvbuf has no effect and the output is again buffered until a newline.

This is with gcc-arm-none-eabi-4_8-2013q4 on Ubuntu.

The changes between newlib and newlib-nano-2.0 are large enough I can't immediately see where the problem lies

Is this behavior difference intentional? Is there another way to disable buffering with newlib-nano?

Question information

Language:
English Edit question
Status:
Solved
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Solved by:
Peter A. Bigot
Solved:
Last query:
Last reply:
Revision history for this message
chengbin (can-finner) said :
#1

Hi Peter,
This is an intentional behavior to save code size of streamio in newlib. This feature is also upstreamed to newlib and is available with configuration option "--disable-newlib-fvwrite-in-streamio". Below is description about this feature I checked in newlib's README.

+`--disable-newlib-fvwrite-in-streamio'
+ NEWLIB implements the vector buffer mechanism to support stream IO
+ buffering required by C standard. This feature is possibly
+ unnecessary for embedded systems which won't change file buffering
+ with functions like `setbuf' or `setvbuf'. The buffering mechanism
+ still acts as default for STDIN/STDOUT/STDERR even if this option
+ is specified.
+ Enabled by default.

As for how to disable the buffering in nano, I think it can be done by hacking streamio (and maybe easily), though I don't remember where to hack exactly.

Revision history for this message
Peter A. Bigot (pab-u) said :
#2

OK; I had seen that in the documentation, but didn't interpret it correctly. Unfortunately this behavior makes nano unusable for stdio for me, but if the feature is already upstream maybe I can provide a solution there, or just use http://pabigot.github.io/embtextf/.

Revision history for this message
chengbin (can-finner) said :
#3

Hi,
I think we may be able to introduce another configuration option to enable/disable buffering for STDIO/STDOUT/STDERR (or all streamio file?) when "--disable-newlib-fvwrite-in-streamio" is specified. I think the code size can be further reduced in this case. I think I can look into it later when I revisit newlib-nano.

Revision history for this message
Peter A. Bigot (pab-u) said :
#4

Thanks; I think that'd be a big help. I did look at the newlib source but was unable to understand what it was doing within the time I was willing to devote to the question.

Revision history for this message
chengbin (can-finner) said :
#5

Hi Peter,
Would you mind describe your use case a little bit more please? Why the buffering streamio doesn't work for you?

Thanks.
bin

Revision history for this message
Peter A. Bigot (pab-u) said :
#6

Sure. I'm doing a basic BSP in which my use involves a serial console that is primarily used for debugging output. I want printf/putchar to be usable to display progress, e.g. single characters emitted to tell me what point in the execution I've reached. I've implemented _write() to do blocking output to the UART.

Because printf/putchar are by default line-buffered, I use setvbuf() to disable buffering so that the characters appear as the code executes, rather than all at once whenever a newline is finally generated. This works with standard newlib, but takes 25 kiB or so because of the library overhead.

With newlib-nano, the code size drops by about 20 kiB, but the output is buffered internally with no way to turn it off. Where I misunderstood the documentation you added was in its statement that "The buffering mechanism still acts as default for STDIN/STDOUT/STDERR"; this is misleading because it's not a default that can be changed, it's hard-coded to be enabled.

So I can't use newlib-nano because the functionality is missing, and I don't want to use newlib because it's too big.

Hope this helps.

Revision history for this message
chengbin (can-finner) said :
#7

Thanks for pointing it out. I will change that part of words for now, then get back to the buffering/non-buffering issue later.

Revision history for this message
Peter A. Bigot (pab-u) said :
#8

I discovered that the CMSIS standard gcc-arm.ld script I was using inappropriately (IMO) included a GROUP command that searched in libc.a even when nano (libc_s.a) was being used. Once that command is removed, it appears that setvbuf() does work as it should, and newlib-nano is small enough to meet my needs.