diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index 121bf0bc158..be7c122be28 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -1230,19 +1230,6 @@ int find_mtddriver(FAR const char *pathname, FAR struct inode **ppinode); int close_mtddriver(FAR struct inode *pinode); -/**************************************************************************** - * Name: lib_flushall - * - * Description: - * Called either (1) by the OS when a task exits, or (2) from fflush() - * when a NULL stream argument is provided. - * - ****************************************************************************/ - -#ifdef CONFIG_FILE_STREAM -int lib_flushall(FAR struct streamlist *list); -#endif - /**************************************************************************** * Name: file_read * diff --git a/include/stdio.h b/include/stdio.h index cc7f10441c8..1af9e229357 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -99,7 +99,6 @@ #define setlinebuf(stream) setvbuf(stream, NULL, _IOLBF, 0) -#define clearerr_unlocked(stream) clearerr(stream) #define feof_unlocked(stream) feof(stream) #define ferror_unlocked(stream) ferror(stream) #define fileno_unlocked(stream) fileno(stream) @@ -140,8 +139,10 @@ extern "C" /* Operations on streams (FILE) */ void clearerr(FAR FILE *stream); +void clearerr_unlocked(FAR FILE *stream); int fclose(FAR FILE *stream); int fflush(FAR FILE *stream); +int fflush_unlocked(FAR FILE *stream); int feof(FAR FILE *stream); int ferror(FAR FILE *stream); int fileno(FAR FILE *stream); @@ -174,6 +175,7 @@ size_t fwrite(FAR const void *ptr, size_t size, size_t n_items, size_t fwrite_unlocked(FAR const void *ptr, size_t size, size_t n_items, FAR FILE *stream); int getc(FAR FILE *stream); +int getc_unlocked(FAR FILE *stream); int getchar(void); int getchar_unlocked(void); ssize_t getdelim(FAR char **lineptr, size_t *n, int delimiter, diff --git a/include/wchar.h b/include/wchar.h index d37fb235543..45db6605419 100644 --- a/include/wchar.h +++ b/include/wchar.h @@ -162,6 +162,7 @@ size_t mbsrtowcs(FAR wchar_t *, FAR const char **, size_t, wint_t putwc(wchar_t, FILE *); wint_t putwc_unlocked(wchar_t, FAR FILE *); wint_t putwchar(wchar_t); +wint_t putwchar_unlocked(wchar_t); int swprintf(FAR wchar_t *, size_t, FAR const wchar_t *, ...); int swscanf(FAR const wchar_t *, FAR const wchar_t *, ...); wint_t ungetwc(wint_t, FILE *); diff --git a/libs/libc/libc.h b/libs/libc/libc.h index ba339d48d56..8e3a038fb5a 100644 --- a/libs/libc/libc.h +++ b/libs/libc/libc.h @@ -209,6 +209,13 @@ FAR char *lib_fgets(FAR char *buf, size_t buflen, FILE *stream, FAR char *lib_fgets_unlocked(FAR char *buf, size_t buflen, FILE *stream, bool keepnl, bool consume); +/* Defined in lib_flushall.c */ + +#ifdef CONFIG_FILE_STREAM +int lib_flushall(FAR struct streamlist *list); +int lib_flushall_unlocked(FAR struct streamlist *list); +#endif + /* Defined in lib_libfflush.c */ ssize_t lib_fflush(FAR FILE *stream); diff --git a/libs/libc/stdio/lib_clearerr.c b/libs/libc/stdio/lib_clearerr.c index 39e6b74da90..faee4a973e7 100644 --- a/libs/libc/stdio/lib_clearerr.c +++ b/libs/libc/stdio/lib_clearerr.c @@ -46,8 +46,15 @@ * ****************************************************************************/ -void clearerr(FAR FILE *stream) +void clearerr_unlocked(FAR FILE *stream) { stream->fs_flags &= (__FS_FLAG_LBF | __FS_FLAG_UBF); } + +void clearerr(FAR FILE *stream) +{ + flockfile(stream); + clearerr_unlocked(stream); + funlockfile(stream); +} #endif /* CONFIG_FILE_STREAM */ diff --git a/libs/libc/stdio/lib_fflush.c b/libs/libc/stdio/lib_fflush.c index cbe4e7a6026..5c461f4e3d3 100644 --- a/libs/libc/stdio/lib_fflush.c +++ b/libs/libc/stdio/lib_fflush.c @@ -52,13 +52,48 @@ * ****************************************************************************/ +int fflush_unlocked(FAR FILE *stream) +{ + int ret; + + /* Is the stream argument NULL? */ + + if (stream == NULL) + { + /* Yes... then this is a request to flush all streams */ + + ret = lib_flushall_unlocked(lib_get_streams()); + } + else + { + ret = lib_fflush_unlocked(stream); + } + + /* Check the return value */ + + if (ret < 0) + { + /* An error occurred during the flush AND/OR we were unable to flush + * all of the buffered write data. Set the errno value. + */ + + set_errno(-ret); + + /* And return EOF on failure. */ + + return EOF; + } + + return OK; +} + int fflush(FAR FILE *stream) { int ret; /* Is the stream argument NULL? */ - if (!stream) + if (stream == NULL) { /* Yes... then this is a request to flush all streams */ diff --git a/libs/libc/stdio/lib_fputwc.c b/libs/libc/stdio/lib_fputwc.c index 95248598fde..5aab48bfe63 100644 --- a/libs/libc/stdio/lib_fputwc.c +++ b/libs/libc/stdio/lib_fputwc.c @@ -64,7 +64,7 @@ wint_t fputwc_unlocked(wchar_t c, FAR FILE *f) if (isascii(c)) { - c = putc(c, f); + c = putc_unlocked(c, f); } else { diff --git a/libs/libc/stdio/lib_libflushall.c b/libs/libc/stdio/lib_libflushall.c index 225482cb3ce..2c4f37c592c 100644 --- a/libs/libc/stdio/lib_libflushall.c +++ b/libs/libc/stdio/lib_libflushall.c @@ -45,6 +45,54 @@ * ****************************************************************************/ +int lib_flushall_unlocked(FAR struct streamlist *list) +{ + int lasterrno = OK; + int ret; + + /* Make sure that there are streams associated with this thread */ + + if (list != NULL) + { + FAR FILE *stream; + int i; + + /* Process each stream in the thread's stream list */ + + for (i = 0; i < 3; i++) + { + lib_fflush_unlocked(&list->sl_std[i]); + } + + for (stream = list->sl_head; stream != NULL; stream = stream->fs_next) + { + /* If the stream is opened for writing, then flush all of + * the pending write data in the stream. + */ + + if ((stream->fs_oflags & O_WROK) != 0) + { + /* Flush the writable FILE */ + + ret = lib_fflush_unlocked(stream); + if (ret < 0) + { + /* An error occurred during the flush AND/OR we were unable + * to flush all of the buffered write data. Remember the + * last errcode. + */ + + lasterrno = ret; + } + } + } + } + + /* If any flush failed, return the errorcode of the last failed flush */ + + return lasterrno; +} + int lib_flushall(FAR struct streamlist *list) { int lasterrno = OK; @@ -52,7 +100,7 @@ int lib_flushall(FAR struct streamlist *list) /* Make sure that there are streams associated with this thread */ - if (list) + if (list != NULL) { FAR FILE *stream; int i; @@ -66,8 +114,7 @@ int lib_flushall(FAR struct streamlist *list) lib_fflush(&list->sl_std[i]); } - stream = list->sl_head; - for (; stream != NULL; stream = stream->fs_next) + for (stream = list->sl_head; stream != NULL; stream = stream->fs_next) { /* If the stream is opened for writing, then flush all of * the pending write data in the stream. diff --git a/libs/libc/stdio/lib_putc.c b/libs/libc/stdio/lib_putc.c index e3369c031c1..00162b72754 100644 --- a/libs/libc/stdio/lib_putc.c +++ b/libs/libc/stdio/lib_putc.c @@ -32,3 +32,8 @@ int putc(int c, FAR FILE *stream) { return fputc(c, stream); } + +int putc_unlocked(int c, FAR FILE *stream) +{ + return fputc_unlocked(c, stream); +} diff --git a/libs/libc/stdio/lib_putwchar.c b/libs/libc/stdio/lib_putwchar.c index 6906cb82001..43911641c0d 100644 --- a/libs/libc/stdio/lib_putwchar.c +++ b/libs/libc/stdio/lib_putwchar.c @@ -51,13 +51,14 @@ * ****************************************************************************/ -wint_t putwchar(wchar_t c) +wint_t putwchar_unlocked(wchar_t c) { #ifdef CONFIG_FILE_STREAM - return fputwc(c, stdout); + return fputwc_unlocked(c, stdout); #else char mbc[MB_LEN_MAX]; int l; + l = wctomb(mbc, c); if (l < 0) { @@ -67,3 +68,18 @@ wint_t putwchar(wchar_t c) return write(STDOUT_FILENO, mbc, l) == l ? c : WEOF; #endif } + +wint_t putwchar(wchar_t c) +{ + wint_t w; + +#ifdef CONFIG_FILE_STREAM + flockfile(stdout); +#endif + w = putwchar_unlocked(c); +#ifdef CONFIG_FILE_STREAM + funlockfile(stdout); +#endif + + return w; +}