Browse Source

use a local temp buffer for unbuffered streams in vfprintf

this change makes it so most calls to fprintf(stderr, ...) will result
in a single writev syscall, as opposed to roughly 2*N syscalls (and
possibly more) where N is the number of format specifiers. in
principle we could use a much larger buffer, but it's best not to
increase the stack requirements too much. most messages are under 80
chars.
Rich Felker 14 năm trước cách đây
mục cha
commit
bd57e2b43a
2 tập tin đã thay đổi với 14 bổ sung0 xóa
  1. 1 0
      src/stdio/stderr.c
  2. 13 0
      src/stdio/vfprintf.c

+ 1 - 0
src/stdio/stderr.c

@@ -6,6 +6,7 @@ static FILE f = {
 	.buf_size = 0,
 	.fd = 2,
 	.flags = F_PERM | F_NORD,
+	.lbf = -1,
 	.write = __stdio_write,
 	.seek = __stdio_seek,
 	.close = __stdio_close,

+ 13 - 0
src/stdio/vfprintf.c

@@ -627,13 +627,26 @@ int vfprintf(FILE *f, const char *fmt, va_list ap)
 	va_list ap2;
 	int nl_type[NL_ARGMAX] = {0};
 	union arg nl_arg[NL_ARGMAX];
+	unsigned char internal_buf[80], *saved_buf = 0;
 	int ret;
 
 	va_copy(ap2, ap);
 	if (printf_core(0, fmt, &ap2, nl_arg, nl_type) < 0) return -1;
 
 	FLOCK(f);
+	if (!f->buf_size) {
+		saved_buf = f->buf;
+		f->buf = internal_buf;
+		f->buf_size = sizeof internal_buf;
+	}
 	ret = printf_core(f, fmt, &ap2, nl_arg, nl_type);
+	if (saved_buf) {
+		f->write(f, 0, 0);
+		if (!f->wpos) ret = -1;
+		f->buf = saved_buf;
+		f->buf_size = 0;
+		f->wpos = f->wbase = f->wend = 0;
+	}
 	FUNLOCK(f);
 	va_end(ap2);
 	return ret;