This is an automated email from the ASF dual-hosted git repository.
masayuki pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new b96035885a stdio: Implement simple buffered out stream for vdprintf
b96035885a is described below
commit b96035885a294bbfbfdccac45b1b8bdd7e58e834
Author: Huang Qi <[email protected]>
AuthorDate: Mon Feb 27 18:32:38 2023 +0800
stdio: Implement simple buffered out stream for vdprintf
Improve performance for raw fd based printf like operation.
Signed-off-by: Huang Qi <[email protected]>
---
include/nuttx/streams.h | 28 ++++++++
libs/libc/stdio/lib_vdprintf.c | 7 +-
libs/libc/stream/Kconfig | 4 ++
libs/libc/stream/Make.defs | 2 +-
libs/libc/stream/lib_bufferedoutstream.c | 120 +++++++++++++++++++++++++++++++
5 files changed, 159 insertions(+), 2 deletions(-)
diff --git a/include/nuttx/streams.h b/include/nuttx/streams.h
index c49f6f0718..6ba76492b9 100644
--- a/include/nuttx/streams.h
+++ b/include/nuttx/streams.h
@@ -217,6 +217,14 @@ struct lib_rawsostream_s
int fd;
};
+struct lib_bufferedoutstream_s
+{
+ struct lib_outstream_s public;
+ FAR struct lib_outstream_s *backend;
+ int pending;
+ char buffer[CONFIG_STREAM_OUT_BUFFER_SIZE];
+};
+
/* This is a special stream that does buffered character I/O. NOTE that is
* CONFIG_SYSLOG_BUFFER is not defined, it is the same as struct
* lib_outstream_s
@@ -372,6 +380,26 @@ void lib_rawoutstream(FAR struct lib_rawoutstream_s
*outstream, int fd);
void lib_rawsistream(FAR struct lib_rawsistream_s *instream, int fd);
void lib_rawsostream(FAR struct lib_rawsostream_s *outstream, int fd);
+/****************************************************************************
+ * Name: lib_bufferedoutstream
+ *
+ * Description:
+ * Wrap a raw output stream to a buffered output stream.
+ *
+ * Input Parameters:
+ * outstream - User allocated, uninitialized instance of struct
+ * lib_bufferedoutstream_s to be initialized.
+ * backend - User allocated, initialized instance of struct
+ * lib_outstream_s to be buffered.
+ *
+ * Returned Value:
+ * None (User allocated instance initialized).
+ *
+ ****************************************************************************/
+
+void lib_bufferedoutstream(FAR struct lib_bufferedoutstream_s *outstream,
+ FAR struct lib_outstream_s *backend);
+
/****************************************************************************
* Name: lib_lowoutstream
*
diff --git a/libs/libc/stdio/lib_vdprintf.c b/libs/libc/stdio/lib_vdprintf.c
index 90a4b2367c..27d94df583 100644
--- a/libs/libc/stdio/lib_vdprintf.c
+++ b/libs/libc/stdio/lib_vdprintf.c
@@ -50,10 +50,15 @@
int vdprintf(int fd, FAR const IPTR char *fmt, va_list ap)
{
+ int ret;
struct lib_rawoutstream_s rawoutstream;
+ struct lib_bufferedoutstream_s outstream;
/* Wrap the fd in a stream object and let lib_vsprintf do the work. */
lib_rawoutstream(&rawoutstream, fd);
- return lib_vsprintf(&rawoutstream.public, fmt, ap);
+ lib_bufferedoutstream(&outstream, &rawoutstream.public);
+ ret = lib_vsprintf(&outstream.public, fmt, ap);
+ lib_stream_flush(&outstream.public);
+ return ret;
}
diff --git a/libs/libc/stream/Kconfig b/libs/libc/stream/Kconfig
index 90554aa661..77cb42e3da 100644
--- a/libs/libc/stream/Kconfig
+++ b/libs/libc/stream/Kconfig
@@ -21,4 +21,8 @@ config STREAM_LZF_BLOG
endif
+config STREAM_OUT_BUFFER_SIZE
+ int "Output stream buffer size"
+ default 64
+
endmenu # Locale Support
diff --git a/libs/libc/stream/Make.defs b/libs/libc/stream/Make.defs
index 868ff05576..0b6757c9bd 100644
--- a/libs/libc/stream/Make.defs
+++ b/libs/libc/stream/Make.defs
@@ -26,7 +26,7 @@ CSRCS += lib_memsostream.c lib_lowoutstream.c
lib_rawinstream.c
CSRCS += lib_rawoutstream.c lib_rawsistream.c lib_rawsostream.c
CSRCS += lib_zeroinstream.c lib_nullinstream.c lib_nulloutstream.c
CSRCS += lib_mtdoutstream.c lib_libnoflush.c lib_libsnoflush.c
-CSRCS += lib_syslogstream.c
+CSRCS += lib_syslogstream.c lib_bufferedoutstream.c
# The remaining sources files depend upon C streams
diff --git a/libs/libc/stream/lib_bufferedoutstream.c
b/libs/libc/stream/lib_bufferedoutstream.c
new file mode 100644
index 0000000000..4018b0cebb
--- /dev/null
+++ b/libs/libc/stream/lib_bufferedoutstream.c
@@ -0,0 +1,120 @@
+/****************************************************************************
+ * libs/libc/stream/lib_bufferedoutstream.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <nuttx/fs/fs.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: bufferedoutstream_flush
+ ****************************************************************************/
+
+static int bufferedoutstream_flush(FAR struct lib_outstream_s *this)
+{
+ FAR struct lib_bufferedoutstream_s *rthis =
+ (FAR struct lib_bufferedoutstream_s *)this;
+ int ret = OK;
+
+ ret = lib_stream_puts(rthis->backend, rthis->buffer,
+ rthis->pending);
+
+ if (ret >= 0)
+ {
+ rthis->pending = 0;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: bufferedoutstream_puts
+ ****************************************************************************/
+
+static int bufferedoutstream_puts(FAR struct lib_outstream_s *this,
+ FAR const void *buf, int len)
+{
+ FAR struct lib_bufferedoutstream_s *rthis =
+ (FAR struct lib_bufferedoutstream_s *)this;
+ int ret = len;
+
+ if (rthis->pending + len <= CONFIG_STREAM_OUT_BUFFER_SIZE)
+ {
+ /* If buffer is enough to save incoming data, cache it */
+
+ memcpy(rthis->buffer + rthis->pending, buf, len);
+ rthis->pending += len;
+ }
+ else
+ {
+ /* Or, for long data flush buffer and write it directly */
+
+ ret = lib_stream_flush(this);
+ if (ret >= 0)
+ {
+ ret = lib_stream_puts(rthis->backend, buf, len);
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: bufferedoutstream_putc
+ ****************************************************************************/
+
+static void bufferedoutstream_putc(FAR struct lib_outstream_s *this, int ch)
+{
+ char c = ch;
+
+ bufferedoutstream_puts(this, &c, 1);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_bufferedoutstream
+ ****************************************************************************/
+
+void lib_bufferedoutstream(FAR struct lib_bufferedoutstream_s *outstream,
+ FAR struct lib_outstream_s *backend)
+{
+ outstream->public.putc = bufferedoutstream_putc;
+ outstream->public.puts = bufferedoutstream_puts;
+ outstream->public.flush = bufferedoutstream_flush;
+ outstream->public.nput = 0;
+ outstream->backend = backend;
+ outstream->pending = 0;
+}