mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 08:38:38 +08:00
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:
parent
19d1e08717
commit
819ebe7356
19 changed files with 57 additions and 69 deletions
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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.
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue