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 <miguel@midokura.com>
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
Miguel Herranz 2022-04-25 18:13:41 +02:00 committed by Xiang Xiao
parent 19d1e08717
commit 819ebe7356
19 changed files with 57 additions and 69 deletions

View File

@ -268,6 +268,7 @@ Standard I/O
int fgetc(FAR FILE *stream); int fgetc(FAR FILE *stream);
int fgetpos(FAR FILE *stream, FAR fpos_t *pos); int fgetpos(FAR FILE *stream, FAR fpos_t *pos);
FAR char *fgets(FAR char *s, int n, FAR FILE *stream); 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); FAR FILE *fopen(FAR const char *path, FAR const char *type);
int fprintf(FAR FILE *stream, FAR const char *format, ...); int fprintf(FAR FILE *stream, FAR const char *format, ...);
int fputc(int c, FAR FILE *stream); 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 fseek(FAR FILE *stream, long int offset, int whence);
int fsetpos(FAR FILE *stream, FAR fpos_t *pos); int fsetpos(FAR FILE *stream, FAR fpos_t *pos);
long ftell(FAR FILE *stream); 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); 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(FAR char *s);
FAR char *gets_s(FAR char *s, rsize_t n); FAR char *gets_s(FAR char *s, rsize_t n);

View File

@ -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 */ /* Initialize the mutex the manages access to the buffer */
lib_lock_init(stream); nxrmutex_init(&stream->fs_lock);
} }
else else
{ {

View File

@ -475,9 +475,9 @@ struct filelist
struct file_struct struct file_struct
{ {
FAR struct file_struct *fs_next; /* Pointer to next file stream */ 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 */ int fs_fd; /* File descriptor associated with stream */
#ifndef CONFIG_STDIO_DISABLE_BUFFERING #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_bufstart; /* Pointer to start of buffer */
FAR unsigned char *fs_bufend; /* Pointer to 1 past end of buffer */ FAR unsigned char *fs_bufend; /* Pointer to 1 past end of buffer */
FAR unsigned char *fs_bufpos; /* Current position in buffer */ FAR unsigned char *fs_bufpos; /* Current position in buffer */

View File

@ -109,18 +109,6 @@ void lib_stream_initialize(FAR struct task_group_s *group);
void lib_stream_release(FAR struct task_group_s *group); void lib_stream_release(FAR struct task_group_s *group);
#endif #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 *****************************************/ /* Functions defined in lib_srand.c *****************************************/
unsigned long nrand(unsigned long limit); unsigned long nrand(unsigned long limit);

View File

@ -173,6 +173,10 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size);
int ungetc(int c, FAR FILE *stream); 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, /* Operations on the stdout stream, buffers, paths,
* and the whole printf-family * and the whole printf-family
*/ */

View File

@ -53,6 +53,7 @@
"fgetpos","stdio.h","defined(CONFIG_FILE_STREAM)","int","FAR FILE *","FAR fpos_t *" "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 *" "fgets","stdio.h","defined(CONFIG_FILE_STREAM)","FAR char *","FAR char *","int","FAR FILE *"
"fileno","stdio.h","","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" "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 *" "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 *","..." "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 *" "fsetpos","stdio.h","defined(CONFIG_FILE_STREAM)","int","FAR FILE *","FAR fpos_t *"
"fstatvfs","sys/statvfs.h","","int","int","FAR struct statvfs *" "fstatvfs","sys/statvfs.h","","int","int","FAR struct statvfs *"
"ftell","stdio.h","defined(CONFIG_FILE_STREAM)","long","FAR FILE *" "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 *" "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" "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 **" "getaddrinfo","netdb.h","defined(CONFIG_LIBC_NETDB)","int","FAR const char *","FAR const char *","FAR const struct addrinfo *","FAR struct addrinfo **"

Can't render this file because it has a wrong number of fields in line 2.

View File

@ -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_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_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_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 endif
# Add the stdio directory to the build # Add the stdio directory to the build

View File

@ -53,7 +53,7 @@
static off_t lib_getoffset(FAR FILE *stream) static off_t lib_getoffset(FAR FILE *stream)
{ {
off_t offset = 0; off_t offset = 0;
lib_take_lock(stream); flockfile(stream);
if (stream->fs_bufstart != if (stream->fs_bufstart !=
NULL && stream->fs_bufread != NULL && stream->fs_bufread !=
@ -71,7 +71,7 @@ static off_t lib_getoffset(FAR FILE *stream)
offset = -(stream->fs_bufpos - stream->fs_bufstart); offset = -(stream->fs_bufpos - stream->fs_bufstart);
} }
lib_give_lock(stream); funlockfile(stream);
return offset; return offset;
} }
#else #else

View File

@ -73,7 +73,7 @@ ssize_t lib_fflush(FAR FILE *stream, bool bforce)
/* Make sure that we have exclusive access to the stream */ /* 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 */ /* 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. * remaining in the buffer.
*/ */
lib_give_lock(stream); funlockfile(stream);
return stream->fs_bufpos - stream->fs_bufstart; return stream->fs_bufpos - stream->fs_bufstart;
errout_with_lock: errout_with_lock:
lib_give_lock(stream); funlockfile(stream);
return ret; return ret;
#else #else

View File

@ -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 * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
@ -29,46 +29,36 @@
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#include <nuttx/semaphore.h> #include <nuttx/mutex.h>
#include <nuttx/fs/fs.h> #include <nuttx/fs/fs.h>
#include "libc.h"
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* lib_lock_init * flockfile
****************************************************************************/ ****************************************************************************/
void lib_lock_init(FAR struct file_struct *stream) void flockfile(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)
{ {
nxrmutex_lock(&stream->fs_lock); 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); nxrmutex_unlock(&stream->fs_lock);
} }
#endif /* CONFIG_STDIO_DISABLE_BUFFERING */

View File

@ -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 */ /* The stream must be stable until we complete the read */
lib_take_lock(stream); flockfile(stream);
#if CONFIG_NUNGET_CHARS > 0 #if CONFIG_NUNGET_CHARS > 0
/* First, re-read any previously ungotten characters */ /* First, re-read any previously ungotten characters */
@ -304,7 +304,7 @@ shortread:
stream->fs_flags |= __FS_FLAG_EOF; stream->fs_flags |= __FS_FLAG_EOF;
} }
lib_give_lock(stream); funlockfile(stream);
return count - remaining; return count - remaining;
} }
@ -312,6 +312,6 @@ shortread:
errout_with_errno: errout_with_errno:
stream->fs_flags |= __FS_FLAG_ERROR; stream->fs_flags |= __FS_FLAG_ERROR;
lib_give_lock(stream); funlockfile(stream);
return ERROR; return ERROR;
} }

View File

@ -83,7 +83,7 @@ ssize_t lib_fwrite(FAR const void *ptr, size_t count, FAR FILE *stream)
/* Get exclusive access to the stream */ /* Get exclusive access to the stream */
lib_take_lock(stream); flockfile(stream);
/* If the buffer is currently being used for read access, then /* If the buffer is currently being used for read access, then
* discard all of the read-ahead data. We do not support concurrent * 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; ret = (uintptr_t)src - (uintptr_t)start;
errout_with_lock: errout_with_lock:
lib_give_lock(stream); funlockfile(stream);
errout: errout:
if (ret < 0) if (ret < 0)

View File

@ -30,7 +30,7 @@
#include <errno.h> #include <errno.h>
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include <nuttx/semaphore.h> #include <nuttx/mutex.h>
#include <nuttx/sched.h> #include <nuttx/sched.h>
#include <nuttx/fs/fs.h> #include <nuttx/fs/fs.h>
#include <nuttx/lib/lib.h> #include <nuttx/lib/lib.h>
@ -73,11 +73,11 @@ void lib_stream_initialize(FAR struct task_group_s *group)
/* Initialize stdin, stdout and stderr stream */ /* Initialize stdin, stdout and stderr stream */
list->sl_std[0].fs_fd = -1; 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; 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; list->sl_std[2].fs_fd = -1;
lib_lock_init(&list->sl_std[2]); nxrmutex_init(&list->sl_std[2].fs_lock);
} }
/**************************************************************************** /****************************************************************************

View File

@ -50,7 +50,7 @@ int puts(FAR const IPTR char *s)
/* Write the string (the next two steps must be atomic) */ /* Write the string (the next two steps must be atomic) */
lib_take_lock(stream); flockfile(stream);
/* Write the string without its trailing '\0' */ /* 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; return nput;
#else #else
size_t len = strlen(s); size_t len = strlen(s);

View File

@ -65,7 +65,7 @@ int lib_rdflush(FAR FILE *stream)
/* Get exclusive access to the 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 /* 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 * 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) if (fseek(stream, -rdoffset, SEEK_CUR) < 0)
{ {
lib_give_lock(stream); funlockfile(stream);
return ERROR; return ERROR;
} }
} }
lib_give_lock(stream); funlockfile(stream);
return OK; return OK;
} }

View File

@ -46,8 +46,8 @@ void rewind(FAR FILE *stream)
return; return;
} }
lib_take_lock(stream); flockfile(stream);
(void) fseek(stream, 0L, SEEK_SET); fseek(stream, 0L, SEEK_SET);
stream->fs_flags &= ~__FS_FLAG_ERROR; stream->fs_flags &= ~__FS_FLAG_ERROR;
lib_give_lock(stream); funlockfile(stream);
} }

View File

@ -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 */ /* 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 /* setvbuf() may only be called AFTER the stream has been opened and
* BEFORE any operations have been performed on the stream. * 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: reuse_buffer:
stream->fs_flags = flags; stream->fs_flags = flags;
lib_give_lock(stream); funlockfile(stream);
return OK; return OK;
errout_with_lock: errout_with_lock:
lib_give_lock(stream); funlockfile(stream);
errout: errout:
set_errno(errcode); set_errno(errcode);

View File

@ -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. * before being pre-empted by the next thread.
*/ */
lib_take_lock(stream); flockfile(stream);
n = lib_vsprintf(&stdoutstream.public, fmt, ap); n = lib_vsprintf(&stdoutstream.public, fmt, ap);
lib_give_lock(stream); funlockfile(stream);
return n; return n;
} }

View File

@ -55,7 +55,7 @@ int vfscanf(FAR FILE *stream, FAR const IPTR char *fmt, va_list ap)
* by the next thread. * by the next thread.
*/ */
lib_take_lock(stream); flockfile(stream);
n = lib_vscanf(&stdinstream.public, &lastc, fmt, ap); 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); ungetc(lastc, stream);
} }
lib_give_lock(stream); funlockfile(stream);
} }
return n; return n;