fs/mmap/msync:support msync.
Summary: 1.Added msync callback in struct mm_map_entry_s 2.Added msync API in fs_msync.c 3.Added static msync_rammap for rammap. Signed-off-by: chenrun1 <chenrun1@xiaomi.com>
This commit is contained in:
parent
484600bd75
commit
d04205aa3d
@ -799,6 +799,33 @@ int fs_getfilep(int fd, FAR struct file **filep)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fs_reffilep
|
||||
*
|
||||
* Description:
|
||||
* To specify filep increase the reference count.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_FS_REFCOUNT
|
||||
void fs_reffilep(FAR struct file *filep)
|
||||
{
|
||||
/* This interface is used to increase the reference count of filep */
|
||||
|
||||
irqstate_t flags;
|
||||
|
||||
DEBUGASSERT(filep);
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
filep->f_refs++;
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fs_putfilep
|
||||
*
|
||||
@ -811,7 +838,6 @@ int fs_getfilep(int fd, FAR struct file **filep)
|
||||
* file' instance.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_FS_REFCOUNT
|
||||
int fs_putfilep(FAR struct file *filep)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
@ -18,7 +18,7 @@
|
||||
#
|
||||
# ##############################################################################
|
||||
|
||||
set(SRCS fs_mmap.c fs_munmap.c fs_mmisc.c)
|
||||
set(SRCS fs_mmap.c fs_munmap.c fs_mmisc.c fs_msync.c)
|
||||
|
||||
if(CONFIG_FS_RAMMAP)
|
||||
list(APPEND SRCS fs_rammap.c)
|
||||
|
@ -18,7 +18,7 @@
|
||||
#
|
||||
############################################################################
|
||||
|
||||
CSRCS += fs_mmap.c fs_munmap.c fs_mmisc.c
|
||||
CSRCS += fs_mmap.c fs_munmap.c fs_mmisc.c fs_msync.c
|
||||
|
||||
ifeq ($(CONFIG_FS_RAMMAP),y)
|
||||
CSRCS += fs_rammap.c
|
||||
|
@ -44,7 +44,7 @@ static int unmap_anonymous(FAR struct task_group_s *group,
|
||||
FAR void *start,
|
||||
size_t length)
|
||||
{
|
||||
FAR void *newaddr;
|
||||
FAR void *newaddr = NULL;
|
||||
off_t offset;
|
||||
bool kernel = entry->priv.i;
|
||||
int ret = OK;
|
||||
|
95
fs/mmap/fs_msync.c
Normal file
95
fs/mmap/fs_msync.c
Normal file
@ -0,0 +1,95 @@
|
||||
/****************************************************************************
|
||||
* fs/mmap/fs_msync.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/sched.h>
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs_rammap.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: msync
|
||||
*
|
||||
* Description:
|
||||
* Equivalent to the standard msync() function except that it accepts
|
||||
* a struct file instance instead of a memory address and it does not set
|
||||
* the errno variable.
|
||||
*
|
||||
* Input Parameters:
|
||||
* file - A pointer to the struct file instance representing the
|
||||
* mappedfile
|
||||
* start - The starting address of the memory region to be synchronized
|
||||
* length - The length of the memory region to be synchronized
|
||||
* flags - Flags that determine the type of synchronization to be
|
||||
* performed
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, returns 0 (OK); On failure, returns a negated errno value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int msync(FAR void *start, size_t length, int flags)
|
||||
{
|
||||
FAR struct mm_map_entry_s *entry;
|
||||
int ret;
|
||||
|
||||
ret = mm_map_lock();
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
entry = mm_map_find(get_current_mm(), start, length);
|
||||
if (!entry)
|
||||
{
|
||||
ferr("ERROR: Region not found\n");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (entry->msync == NULL)
|
||||
{
|
||||
ret = OK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = entry->msync(entry, start, length, flags);
|
||||
out:
|
||||
mm_map_unlock();
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
@ -49,14 +49,84 @@
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: msync_rammap
|
||||
****************************************************************************/
|
||||
|
||||
static int msync_rammap(FAR struct mm_map_entry_s *entry, FAR void *start,
|
||||
size_t length, int flags)
|
||||
{
|
||||
FAR struct file *filep = (FAR void *)((uintptr_t)entry->priv.p & ~1);
|
||||
FAR uint8_t *wrbuffer = start;
|
||||
ssize_t nwrite = 0;
|
||||
off_t offset;
|
||||
off_t fpos;
|
||||
off_t opos;
|
||||
|
||||
offset = (uintptr_t)start - (uintptr_t)entry->vaddr;
|
||||
if (length > entry->length - offset)
|
||||
{
|
||||
length = entry->length - offset;
|
||||
}
|
||||
|
||||
opos = file_seek(filep, 0, SEEK_CUR);
|
||||
if (opos < 0)
|
||||
{
|
||||
ferr("ERROR: Get current position failed\n");
|
||||
return opos;
|
||||
}
|
||||
|
||||
fpos = file_seek(filep, entry->offset + offset, SEEK_SET);
|
||||
if (fpos < 0)
|
||||
{
|
||||
ferr("ERRORL Seek to position %"PRIdOFF" failed\n", fpos);
|
||||
return fpos;
|
||||
}
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
nwrite = file_write(filep, wrbuffer, length);
|
||||
if (nwrite < 0)
|
||||
{
|
||||
/* Handle the special case where the write was interrupted by a
|
||||
* signal.
|
||||
*/
|
||||
|
||||
if (nwrite != -EINTR)
|
||||
{
|
||||
/* All other write errors are bad. */
|
||||
|
||||
ferr("ERROR: Write failed: offset=%"PRIdOFF" nwrite=%zd\n",
|
||||
entry->offset, nwrite);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment number of bytes written */
|
||||
|
||||
wrbuffer += nwrite;
|
||||
length -= nwrite;
|
||||
}
|
||||
|
||||
/* Restore file pos */
|
||||
|
||||
file_seek(filep, opos, SEEK_SET);
|
||||
return nwrite >= 0 ? 0 : nwrite;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: unmap_rammap
|
||||
****************************************************************************/
|
||||
|
||||
static int unmap_rammap(FAR struct task_group_s *group,
|
||||
FAR struct mm_map_entry_s *entry,
|
||||
FAR void *start,
|
||||
size_t length)
|
||||
{
|
||||
FAR struct file *filep = (FAR void *)((uintptr_t)entry->priv.p & ~1);
|
||||
enum mm_map_type_e type = (uintptr_t)entry->priv.p & 1;
|
||||
FAR void *newaddr = NULL;
|
||||
off_t offset;
|
||||
enum mm_map_type_e type = entry->priv.i;
|
||||
int ret = OK;
|
||||
|
||||
/* Get the offset from the beginning of the region and the actual number
|
||||
@ -94,6 +164,8 @@ static int unmap_rammap(FAR struct task_group_s *group,
|
||||
kumm_free(entry->vaddr);
|
||||
}
|
||||
|
||||
fs_putfilep(filep);
|
||||
|
||||
/* Then remove the mapping from the list */
|
||||
|
||||
ret = mm_map_remove(get_group_mm(group), entry);
|
||||
@ -248,8 +320,10 @@ int rammap(FAR struct file *filep, FAR struct mm_map_entry_s *entry,
|
||||
/* Add the buffer to the list of regions */
|
||||
|
||||
out:
|
||||
entry->priv.i = type;
|
||||
fs_reffilep(filep);
|
||||
entry->priv.p = (FAR void *)((uintptr_t)filep | type);
|
||||
entry->munmap = unmap_rammap;
|
||||
entry->msync = msync_rammap;
|
||||
|
||||
ret = mm_map_add(get_current_mm(), entry);
|
||||
if (ret < 0)
|
||||
|
@ -1159,6 +1159,22 @@ int nx_open(FAR const char *path, int oflags, ...);
|
||||
|
||||
int fs_getfilep(int fd, FAR struct file **filep);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fs_reffilep
|
||||
*
|
||||
* Description:
|
||||
* To specify filep increase the reference count.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void fs_reffilep(FAR struct file *filep);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fs_putfilep
|
||||
*
|
||||
|
@ -56,11 +56,14 @@ struct mm_map_entry_s
|
||||
int i;
|
||||
} priv;
|
||||
|
||||
/* Drivers which register mappings may also implement the unmap function
|
||||
* to undo anything done in mmap.
|
||||
* Nb. Implementation must NOT use "this_task()->group" since it is not
|
||||
* valid during process exit. The argument "group" will be NULL in this
|
||||
* case.
|
||||
int (*msync)(FAR struct mm_map_entry_s *entry, FAR void *start,
|
||||
size_t length, int flags);
|
||||
|
||||
/* Drivers which register mappings may also
|
||||
* implement the unmap function to undo anything done in mmap.
|
||||
* Nb. Implementation must NOT use "this_task()->group" since
|
||||
* this is not valid during process exit. The argument "group" will be
|
||||
* NULL in this case.
|
||||
*/
|
||||
|
||||
int (*munmap)(FAR struct task_group_s *group,
|
||||
|
@ -248,6 +248,7 @@ SYSCALL_LOOKUP(fchown, 3)
|
||||
SYSCALL_LOOKUP(utimens, 2)
|
||||
SYSCALL_LOOKUP(lutimens, 2)
|
||||
SYSCALL_LOOKUP(futimens, 2)
|
||||
SYSCALL_LOOKUP(msync, 3)
|
||||
SYSCALL_LOOKUP(munmap, 2)
|
||||
|
||||
#if defined(CONFIG_PSEUDOFS_SOFTLINKS)
|
||||
|
@ -77,6 +77,7 @@
|
||||
"mq_timedreceive","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","ssize_t","mqd_t","FAR char *","size_t","FAR unsigned int *","FAR const struct timespec *"
|
||||
"mq_timedsend","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","mqd_t","FAR const char *","size_t","unsigned int","FAR const struct timespec *"
|
||||
"mq_unlink","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","FAR const char *"
|
||||
"msync","sys/mman.h","","int","FAR void *","size_t","int"
|
||||
"munmap","sys/mman.h","","int","FAR void *","size_t"
|
||||
"nanosleep","time.h","","int","FAR const struct timespec *","FAR struct timespec *"
|
||||
"nx_mkfifo","nuttx/fs/fs.h","defined(CONFIG_PIPES) && CONFIG_DEV_FIFO_SIZE > 0","int","FAR const char *","mode_t","size_t"
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
Loading…
Reference in New Issue
Block a user