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 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);

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 */
lib_lock_init(stream);
nxrmutex_init(&stream->fs_lock);
}
else
{

View file

@ -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 */

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);
#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);

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);
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
*/

View file

@ -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 **"

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_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

View file

@ -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

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 */
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

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
* contributor license agreements. See the NOTICE file distributed with
@ -29,46 +29,36 @@
#include <errno.h>
#include <assert.h>
#include <nuttx/semaphore.h>
#include <nuttx/mutex.h>
#include <nuttx/fs/fs.h>
#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 */

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 */
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;
}

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 */
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)

View file

@ -30,7 +30,7 @@
#include <errno.h>
#include <nuttx/kmalloc.h>
#include <nuttx/semaphore.h>
#include <nuttx/mutex.h>
#include <nuttx/sched.h>
#include <nuttx/fs/fs.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 */
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);
}
/****************************************************************************

View file

@ -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);

View file

@ -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;
}

View file

@ -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);
}

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 */
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);

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.
*/
lib_take_lock(stream);
flockfile(stream);
n = lib_vsprintf(&stdoutstream.public, fmt, ap);
lib_give_lock(stream);
funlockfile(stream);
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.
*/
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;