From 819ebe7356e4652a859005b065fac45226a69846 Mon Sep 17 00:00:00 2001 From: Miguel Herranz Date: Mon, 25 Apr 2022 18:13:41 +0200 Subject: [PATCH] libc/stdio: Add stdio file locking functions Add flockfile(), ftrylockfile() and funlockfile() functions [1]. [1] POSIX.1-2008 / System Interfaces / flockfile https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/functions/flockfile.html Signed-off-by: Miguel Herranz Signed-off-by: Xiang Xiao --- .../reference/user/10_filesystem.rst | 3 ++ fs/vfs/fs_fdopen.c | 2 +- include/nuttx/fs/fs.h | 2 +- include/nuttx/lib/lib.h | 12 ------ include/stdio.h | 4 ++ libs/libc/libc.csv | 3 ++ libs/libc/stdio/Make.defs | 2 +- libs/libc/stdio/lib_ftello.c | 4 +- libs/libc/stdio/lib_libfflush.c | 6 +-- .../{lib_libfilesem.c => lib_libfilelock.c} | 40 +++++++------------ libs/libc/stdio/lib_libfread.c | 6 +-- libs/libc/stdio/lib_libfwrite.c | 4 +- libs/libc/stdio/lib_libstream.c | 8 ++-- libs/libc/stdio/lib_puts.c | 4 +- libs/libc/stdio/lib_rdflush.c | 6 +-- libs/libc/stdio/lib_rewind.c | 6 +-- libs/libc/stdio/lib_setvbuf.c | 6 +-- libs/libc/stdio/lib_vfprintf.c | 4 +- libs/libc/stdio/lib_vfscanf.c | 4 +- 19 files changed, 57 insertions(+), 69 deletions(-) rename libs/libc/stdio/{lib_libfilesem.c => lib_libfilelock.c} (79%) diff --git a/Documentation/reference/user/10_filesystem.rst b/Documentation/reference/user/10_filesystem.rst index ce2a0c6044..acbf64b0b5 100644 --- a/Documentation/reference/user/10_filesystem.rst +++ b/Documentation/reference/user/10_filesystem.rst @@ -268,6 +268,7 @@ Standard I/O int fgetc(FAR FILE *stream); int fgetpos(FAR FILE *stream, FAR fpos_t *pos); FAR char *fgets(FAR char *s, int n, FAR FILE *stream); + void flockfile(FAR FILE *stream); FAR FILE *fopen(FAR const char *path, FAR const char *type); int fprintf(FAR FILE *stream, FAR const char *format, ...); int fputc(int c, FAR FILE *stream); @@ -278,6 +279,8 @@ Standard I/O int fseek(FAR FILE *stream, long int offset, int whence); int fsetpos(FAR FILE *stream, FAR fpos_t *pos); long ftell(FAR FILE *stream); + int ftrylockfile(FAR FILE *stream); + void funlockfile(FAR FILE *stream); size_t fwrite(FAR const void *ptr, size_t size, size_t n_items, FAR FILE *stream); FAR char *gets(FAR char *s); FAR char *gets_s(FAR char *s, rsize_t n); diff --git a/fs/vfs/fs_fdopen.c b/fs/vfs/fs_fdopen.c index 8f14738860..db02601568 100644 --- a/fs/vfs/fs_fdopen.c +++ b/fs/vfs/fs_fdopen.c @@ -194,7 +194,7 @@ int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb, /* Initialize the mutex the manages access to the buffer */ - lib_lock_init(stream); + nxrmutex_init(&stream->fs_lock); } else { diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index 2d9d7be9f0..cb55135018 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -475,9 +475,9 @@ struct filelist struct file_struct { FAR struct file_struct *fs_next; /* Pointer to next file stream */ + rmutex_t fs_lock; /* Recursive lock */ int fs_fd; /* File descriptor associated with stream */ #ifndef CONFIG_STDIO_DISABLE_BUFFERING - rmutex_t fs_lock; /* Recursive lock */ FAR unsigned char *fs_bufstart; /* Pointer to start of buffer */ FAR unsigned char *fs_bufend; /* Pointer to 1 past end of buffer */ FAR unsigned char *fs_bufpos; /* Current position in buffer */ diff --git a/include/nuttx/lib/lib.h b/include/nuttx/lib/lib.h index 2668588caa..00b41adef7 100644 --- a/include/nuttx/lib/lib.h +++ b/include/nuttx/lib/lib.h @@ -109,18 +109,6 @@ void lib_stream_initialize(FAR struct task_group_s *group); void lib_stream_release(FAR struct task_group_s *group); #endif -/* Functions defined in lib_filesem.c ***************************************/ - -#ifdef CONFIG_STDIO_DISABLE_BUFFERING -# define lib_lock_init(s) -# define lib_take_lock(s) -# define lib_give_lock(s) -#else -void lib_lock_init(FAR struct file_struct *stream); -void lib_take_lock(FAR struct file_struct *stream); -void lib_give_lock(FAR struct file_struct *stream); -#endif - /* Functions defined in lib_srand.c *****************************************/ unsigned long nrand(unsigned long limit); diff --git a/include/stdio.h b/include/stdio.h index 6379072ba9..9175b159a8 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -173,6 +173,10 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size); int ungetc(int c, FAR FILE *stream); +void flockfile(FAR FILE *stream); +int ftrylockfile(FAR FILE *stream); +void funlockfile(FAR FILE *stream); + /* Operations on the stdout stream, buffers, paths, * and the whole printf-family */ diff --git a/libs/libc/libc.csv b/libs/libc/libc.csv index 2a1704a398..41b53621ba 100644 --- a/libs/libc/libc.csv +++ b/libs/libc/libc.csv @@ -53,6 +53,7 @@ "fgetpos","stdio.h","defined(CONFIG_FILE_STREAM)","int","FAR FILE *","FAR fpos_t *" "fgets","stdio.h","defined(CONFIG_FILE_STREAM)","FAR char *","FAR char *","int","FAR FILE *" "fileno","stdio.h","","int","FAR FILE *" +"flockfile","stdio.h","!defined(CONFIG_FILE_STREAM)","void","FAR FILE *" "fnmatch","fnmatch.h","","int","FAR const char *","FAR const char *","int" "fopen","stdio.h","defined(CONFIG_FILE_STREAM)","FAR FILE *","FAR const char *","FAR const char *" "fprintf","stdio.h","defined(CONFIG_FILE_STREAM)","int","FAR FILE *","FAR const IPTR char *","..." @@ -65,6 +66,8 @@ "fsetpos","stdio.h","defined(CONFIG_FILE_STREAM)","int","FAR FILE *","FAR fpos_t *" "fstatvfs","sys/statvfs.h","","int","int","FAR struct statvfs *" "ftell","stdio.h","defined(CONFIG_FILE_STREAM)","long","FAR FILE *" +"ftrylockfile","stdio.h","!defined(CONFIG_FILE_STREAM)","int","FAR FILE *" +"funlockfile","stdio.h","!defined(CONFIG_FILE_STREAM)","void","FAR FILE *" "fwrite","stdio.h","defined(CONFIG_FILE_STREAM)","size_t","FAR const void *","size_t","size_t","FAR FILE *" "gai_strerror","netdb.h","defined(CONFIG_LIBC_NETDB)","FAR const char *","int" "getaddrinfo","netdb.h","defined(CONFIG_LIBC_NETDB)","int","FAR const char *","FAR const char *","FAR const struct addrinfo *","FAR struct addrinfo **" diff --git a/libs/libc/stdio/Make.defs b/libs/libc/stdio/Make.defs index c99af90aa5..44fd90219c 100644 --- a/libs/libc/stdio/Make.defs +++ b/libs/libc/stdio/Make.defs @@ -44,7 +44,7 @@ CSRCS += lib_rdflush.c lib_wrflush.c lib_putc.c lib_fputc.c CSRCS += lib_fputs.c lib_ungetc.c lib_fprintf.c lib_vfprintf.c CSRCS += lib_feof.c lib_ferror.c lib_rewind.c lib_clearerr.c CSRCS += lib_scanf.c lib_vscanf.c lib_fscanf.c lib_vfscanf.c lib_tmpfile.c -CSRCS += lib_setbuf.c lib_setvbuf.c lib_libstream.c lib_libfilesem.c +CSRCS += lib_setbuf.c lib_setvbuf.c lib_libstream.c lib_libfilelock.c endif # Add the stdio directory to the build diff --git a/libs/libc/stdio/lib_ftello.c b/libs/libc/stdio/lib_ftello.c index 8fa1e1ee4d..0052a50e80 100644 --- a/libs/libc/stdio/lib_ftello.c +++ b/libs/libc/stdio/lib_ftello.c @@ -53,7 +53,7 @@ static off_t lib_getoffset(FAR FILE *stream) { off_t offset = 0; - lib_take_lock(stream); + flockfile(stream); if (stream->fs_bufstart != NULL && stream->fs_bufread != @@ -71,7 +71,7 @@ static off_t lib_getoffset(FAR FILE *stream) offset = -(stream->fs_bufpos - stream->fs_bufstart); } - lib_give_lock(stream); + funlockfile(stream); return offset; } #else diff --git a/libs/libc/stdio/lib_libfflush.c b/libs/libc/stdio/lib_libfflush.c index 8790bbf77f..60d33e4b26 100644 --- a/libs/libc/stdio/lib_libfflush.c +++ b/libs/libc/stdio/lib_libfflush.c @@ -73,7 +73,7 @@ ssize_t lib_fflush(FAR FILE *stream, bool bforce) /* Make sure that we have exclusive access to the stream */ - lib_take_lock(stream); + flockfile(stream); /* Check if there is an allocated I/O buffer */ @@ -156,11 +156,11 @@ ssize_t lib_fflush(FAR FILE *stream, bool bforce) * remaining in the buffer. */ - lib_give_lock(stream); + funlockfile(stream); return stream->fs_bufpos - stream->fs_bufstart; errout_with_lock: - lib_give_lock(stream); + funlockfile(stream); return ret; #else diff --git a/libs/libc/stdio/lib_libfilesem.c b/libs/libc/stdio/lib_libfilelock.c similarity index 79% rename from libs/libc/stdio/lib_libfilesem.c rename to libs/libc/stdio/lib_libfilelock.c index 3fc19c7672..ded1f530fd 100644 --- a/libs/libc/stdio/lib_libfilesem.c +++ b/libs/libc/stdio/lib_libfilelock.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/stdio/lib_libfilesem.c + * libs/libc/stdio/lib_libfilelock.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -29,46 +29,36 @@ #include #include -#include +#include #include -#include "libc.h" - -#ifndef CONFIG_STDIO_DISABLE_BUFFERING - /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * lib_lock_init + * flockfile ****************************************************************************/ -void lib_lock_init(FAR struct file_struct *stream) -{ - /* Initialize the LIB mutex to one (to support one-at-a-time access - * to private data sets. - */ - - nxrmutex_init(&stream->fs_lock); -} - -/**************************************************************************** - * lib_take_lock - ****************************************************************************/ - -void lib_take_lock(FAR struct file_struct *stream) +void flockfile(FAR struct file_struct *stream) { nxrmutex_lock(&stream->fs_lock); } /**************************************************************************** - * lib_give_lock + * flockfile ****************************************************************************/ -void lib_give_lock(FAR struct file_struct *stream) +int ftrylockfile(FAR struct file_struct *stream) +{ + return nxrmutex_trylock(&stream->fs_lock); +} + +/**************************************************************************** + * funlockfile + ****************************************************************************/ + +void funlockfile(FAR struct file_struct *stream) { nxrmutex_unlock(&stream->fs_lock); } - -#endif /* CONFIG_STDIO_DISABLE_BUFFERING */ diff --git a/libs/libc/stdio/lib_libfread.c b/libs/libc/stdio/lib_libfread.c index a689ba79c0..44d703cfad 100644 --- a/libs/libc/stdio/lib_libfread.c +++ b/libs/libc/stdio/lib_libfread.c @@ -70,7 +70,7 @@ ssize_t lib_fread(FAR void *ptr, size_t count, FAR FILE *stream) { /* The stream must be stable until we complete the read */ - lib_take_lock(stream); + flockfile(stream); #if CONFIG_NUNGET_CHARS > 0 /* First, re-read any previously ungotten characters */ @@ -304,7 +304,7 @@ shortread: stream->fs_flags |= __FS_FLAG_EOF; } - lib_give_lock(stream); + funlockfile(stream); return count - remaining; } @@ -312,6 +312,6 @@ shortread: errout_with_errno: stream->fs_flags |= __FS_FLAG_ERROR; - lib_give_lock(stream); + funlockfile(stream); return ERROR; } diff --git a/libs/libc/stdio/lib_libfwrite.c b/libs/libc/stdio/lib_libfwrite.c index 024a7223e9..37f9528202 100644 --- a/libs/libc/stdio/lib_libfwrite.c +++ b/libs/libc/stdio/lib_libfwrite.c @@ -83,7 +83,7 @@ ssize_t lib_fwrite(FAR const void *ptr, size_t count, FAR FILE *stream) /* Get exclusive access to the stream */ - lib_take_lock(stream); + flockfile(stream); /* If the buffer is currently being used for read access, then * discard all of the read-ahead data. We do not support concurrent @@ -157,7 +157,7 @@ ssize_t lib_fwrite(FAR const void *ptr, size_t count, FAR FILE *stream) ret = (uintptr_t)src - (uintptr_t)start; errout_with_lock: - lib_give_lock(stream); + funlockfile(stream); errout: if (ret < 0) diff --git a/libs/libc/stdio/lib_libstream.c b/libs/libc/stdio/lib_libstream.c index 873a2268cc..07461eb88e 100644 --- a/libs/libc/stdio/lib_libstream.c +++ b/libs/libc/stdio/lib_libstream.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include #include @@ -73,11 +73,11 @@ void lib_stream_initialize(FAR struct task_group_s *group) /* Initialize stdin, stdout and stderr stream */ list->sl_std[0].fs_fd = -1; - lib_lock_init(&list->sl_std[0]); + nxrmutex_init(&list->sl_std[0].fs_lock); list->sl_std[1].fs_fd = -1; - lib_lock_init(&list->sl_std[1]); + nxrmutex_init(&list->sl_std[1].fs_lock); list->sl_std[2].fs_fd = -1; - lib_lock_init(&list->sl_std[2]); + nxrmutex_init(&list->sl_std[2].fs_lock); } /**************************************************************************** diff --git a/libs/libc/stdio/lib_puts.c b/libs/libc/stdio/lib_puts.c index 841a03facc..48bcbaab9f 100644 --- a/libs/libc/stdio/lib_puts.c +++ b/libs/libc/stdio/lib_puts.c @@ -50,7 +50,7 @@ int puts(FAR const IPTR char *s) /* Write the string (the next two steps must be atomic) */ - lib_take_lock(stream); + flockfile(stream); /* Write the string without its trailing '\0' */ @@ -80,7 +80,7 @@ int puts(FAR const IPTR char *s) } } - lib_give_lock(stdout); + funlockfile(stdout); return nput; #else size_t len = strlen(s); diff --git a/libs/libc/stdio/lib_rdflush.c b/libs/libc/stdio/lib_rdflush.c index 926cf75e3b..edbfdeccfc 100644 --- a/libs/libc/stdio/lib_rdflush.c +++ b/libs/libc/stdio/lib_rdflush.c @@ -65,7 +65,7 @@ int lib_rdflush(FAR FILE *stream) /* Get exclusive access to the stream */ - lib_take_lock(stream); + flockfile(stream); /* If the buffer is currently being used for read access, then discard all * of the read-ahead data. We do not support concurrent buffered read/write @@ -98,12 +98,12 @@ int lib_rdflush(FAR FILE *stream) if (fseek(stream, -rdoffset, SEEK_CUR) < 0) { - lib_give_lock(stream); + funlockfile(stream); return ERROR; } } - lib_give_lock(stream); + funlockfile(stream); return OK; } diff --git a/libs/libc/stdio/lib_rewind.c b/libs/libc/stdio/lib_rewind.c index c456e054e3..e488eaf5c8 100644 --- a/libs/libc/stdio/lib_rewind.c +++ b/libs/libc/stdio/lib_rewind.c @@ -46,8 +46,8 @@ void rewind(FAR FILE *stream) return; } - lib_take_lock(stream); - (void) fseek(stream, 0L, SEEK_SET); + flockfile(stream); + fseek(stream, 0L, SEEK_SET); stream->fs_flags &= ~__FS_FLAG_ERROR; - lib_give_lock(stream); + funlockfile(stream); } diff --git a/libs/libc/stdio/lib_setvbuf.c b/libs/libc/stdio/lib_setvbuf.c index 5bd5db8ae4..8d5e5e5703 100644 --- a/libs/libc/stdio/lib_setvbuf.c +++ b/libs/libc/stdio/lib_setvbuf.c @@ -125,7 +125,7 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size) /* Make sure that we have exclusive access to the stream */ - lib_take_lock(stream); + flockfile(stream); /* setvbuf() may only be called AFTER the stream has been opened and * BEFORE any operations have been performed on the stream. @@ -246,11 +246,11 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size) reuse_buffer: stream->fs_flags = flags; - lib_give_lock(stream); + funlockfile(stream); return OK; errout_with_lock: - lib_give_lock(stream); + funlockfile(stream); errout: set_errno(errcode); diff --git a/libs/libc/stdio/lib_vfprintf.c b/libs/libc/stdio/lib_vfprintf.c index 97e504cb70..c6dbd1d938 100644 --- a/libs/libc/stdio/lib_vfprintf.c +++ b/libs/libc/stdio/lib_vfprintf.c @@ -48,9 +48,9 @@ int vfprintf(FAR FILE *stream, FAR const IPTR char *fmt, va_list ap) * before being pre-empted by the next thread. */ - lib_take_lock(stream); + flockfile(stream); n = lib_vsprintf(&stdoutstream.public, fmt, ap); - lib_give_lock(stream); + funlockfile(stream); return n; } diff --git a/libs/libc/stdio/lib_vfscanf.c b/libs/libc/stdio/lib_vfscanf.c index 9be80ebf6f..88ac17825a 100644 --- a/libs/libc/stdio/lib_vfscanf.c +++ b/libs/libc/stdio/lib_vfscanf.c @@ -55,7 +55,7 @@ int vfscanf(FAR FILE *stream, FAR const IPTR char *fmt, va_list ap) * by the next thread. */ - lib_take_lock(stream); + flockfile(stream); n = lib_vscanf(&stdinstream.public, &lastc, fmt, ap); @@ -68,7 +68,7 @@ int vfscanf(FAR FILE *stream, FAR const IPTR char *fmt, va_list ap) ungetc(lastc, stream); } - lib_give_lock(stream); + funlockfile(stream); } return n;