sched/taskfiles: skip unnecessary file open/close operations to improve performance
The task files should consult the "spawn action" and "O_CLOEXEC flags" to determine further whether the file should be duplicated. This PR will further optimize file list duplicating to avoid the performance regression caused by additional file operations. Signed-off-by: chao an <anchao@xiaomi.com>
This commit is contained in:
parent
342a6bb676
commit
42427e9e29
@ -36,6 +36,7 @@ list(
|
|||||||
binfmt_execmodule.c
|
binfmt_execmodule.c
|
||||||
binfmt_exec.c
|
binfmt_exec.c
|
||||||
binfmt_copyargv.c
|
binfmt_copyargv.c
|
||||||
|
binfmt_copyactions.c
|
||||||
binfmt_dumpmodule.c
|
binfmt_dumpmodule.c
|
||||||
binfmt_coredump.c)
|
binfmt_coredump.c)
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ include $(TOPDIR)/Make.defs
|
|||||||
|
|
||||||
CSRCS = binfmt_globals.c binfmt_initialize.c binfmt_register.c binfmt_unregister.c
|
CSRCS = binfmt_globals.c binfmt_initialize.c binfmt_register.c binfmt_unregister.c
|
||||||
CSRCS += binfmt_loadmodule.c binfmt_unloadmodule.c binfmt_execmodule.c
|
CSRCS += binfmt_loadmodule.c binfmt_unloadmodule.c binfmt_execmodule.c
|
||||||
CSRCS += binfmt_exec.c binfmt_copyargv.c binfmt_dumpmodule.c
|
CSRCS += binfmt_exec.c binfmt_copyargv.c binfmt_copyactions.c binfmt_dumpmodule.c
|
||||||
CSRCS += binfmt_coredump.c
|
CSRCS += binfmt_coredump.c
|
||||||
|
|
||||||
ifeq ($(CONFIG_BINFMT_LOADABLE),y)
|
ifeq ($(CONFIG_BINFMT_LOADABLE),y)
|
||||||
|
@ -165,6 +165,51 @@ void binfmt_freeargv(FAR char * const *argv);
|
|||||||
# define binfmt_freeenv(envp)
|
# define binfmt_freeenv(envp)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: binfmt_copyactions
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* In the kernel build, the file actions will likely lie in the caller's
|
||||||
|
* address environment and, hence, be inaccessible when we switch to the
|
||||||
|
* address environment of the new process address environment. So we
|
||||||
|
* do not have any real option other than to copy the callers action list.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* copy - Pointer of file actions
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* A non-zero copy is returned on success.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
||||||
|
int binfmt_copyactions(FAR const posix_spawn_file_actions_t **copy,
|
||||||
|
FAR const posix_spawn_file_actions_t *actions);
|
||||||
|
#else
|
||||||
|
# define binfmt_copyactions(copy, actp) \
|
||||||
|
(*(copy) = (FAR posix_spawn_file_actions_t *)(actp), 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: binfmt_freeactions
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Release the copied file action list.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* copy - Pointer of file actions
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
||||||
|
void binfmt_freeactions(FAR const posix_spawn_file_actions_t *copy);
|
||||||
|
#else
|
||||||
|
# define binfmt_freeactions(copy)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_BUILTIN
|
#ifdef CONFIG_BUILTIN
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: builtin_initialize
|
* Name: builtin_initialize
|
||||||
|
194
binfmt/binfmt_copyactions.c
Normal file
194
binfmt/binfmt_copyactions.c
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* binfmt/binfmt_copyactions.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 <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <nuttx/kmalloc.h>
|
||||||
|
#include <nuttx/binfmt/binfmt.h>
|
||||||
|
|
||||||
|
#include "binfmt.h"
|
||||||
|
|
||||||
|
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL) && !defined(CONFIG_BINFMT_DISABLE)
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define ROUNDUP(x, y) (((x) + (y) - 1) / (y) * (y))
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: binfmt_copyactions
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* In the kernel build, the file actions will likely lie in the caller's
|
||||||
|
* address environment and, hence, be inaccessible when we switch to the
|
||||||
|
* address environment of the new process address environment. So we
|
||||||
|
* do not have any real option other than to copy the callers action list.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* copy - Pointer of file actions
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* A non-zero copy is returned on success.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int binfmt_copyactions(FAR const posix_spawn_file_actions_t **copy,
|
||||||
|
FAR const posix_spawn_file_actions_t *actions)
|
||||||
|
{
|
||||||
|
FAR struct spawn_general_file_action_s *entry;
|
||||||
|
FAR struct spawn_general_file_action_s *prev;
|
||||||
|
FAR struct spawn_close_file_action_s *close;
|
||||||
|
FAR struct spawn_open_file_action_s *open;
|
||||||
|
FAR struct spawn_open_file_action_s *tmp;
|
||||||
|
FAR struct spawn_dup2_file_action_s *dup2;
|
||||||
|
FAR void *buffer;
|
||||||
|
int size = 0;
|
||||||
|
|
||||||
|
if (actions == NULL)
|
||||||
|
{
|
||||||
|
*copy = NULL;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (entry = (FAR struct spawn_general_file_action_s *)actions;
|
||||||
|
entry != NULL;
|
||||||
|
entry = entry->flink)
|
||||||
|
{
|
||||||
|
switch (entry->action)
|
||||||
|
{
|
||||||
|
case SPAWN_FILE_ACTION_CLOSE:
|
||||||
|
size += sizeof(struct spawn_close_file_action_s);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPAWN_FILE_ACTION_DUP2:
|
||||||
|
size += sizeof(struct spawn_dup2_file_action_s);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPAWN_FILE_ACTION_OPEN:
|
||||||
|
open = (FAR struct spawn_open_file_action_s *)entry;
|
||||||
|
size += ROUNDUP(SIZEOF_OPEN_FILE_ACTION_S(strlen(open->path)),
|
||||||
|
sizeof(FAR void *));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*copy = buffer = kmm_malloc(size);
|
||||||
|
if (buffer == NULL)
|
||||||
|
{
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (entry = (FAR struct spawn_general_file_action_s *)actions,
|
||||||
|
prev = NULL; entry != NULL; prev = entry, entry = entry->flink)
|
||||||
|
{
|
||||||
|
switch (entry->action)
|
||||||
|
{
|
||||||
|
case SPAWN_FILE_ACTION_CLOSE:
|
||||||
|
close = buffer;
|
||||||
|
memcpy(close, entry, sizeof(struct spawn_close_file_action_s));
|
||||||
|
close->flink = NULL;
|
||||||
|
if (prev)
|
||||||
|
{
|
||||||
|
prev->flink = (FAR void *)close;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = close + 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPAWN_FILE_ACTION_DUP2:
|
||||||
|
dup2 = buffer;
|
||||||
|
memcpy(dup2, entry, sizeof(struct spawn_dup2_file_action_s));
|
||||||
|
dup2->flink = NULL;
|
||||||
|
if (prev)
|
||||||
|
{
|
||||||
|
prev->flink = (FAR void *)dup2;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = dup2 + 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPAWN_FILE_ACTION_OPEN:
|
||||||
|
tmp = (FAR struct spawn_open_file_action_s *)entry;
|
||||||
|
open = buffer;
|
||||||
|
memcpy(open, entry, sizeof(struct spawn_open_file_action_s));
|
||||||
|
open->flink = NULL;
|
||||||
|
if (prev)
|
||||||
|
{
|
||||||
|
prev->flink = (FAR void *)open;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(open->path, tmp->path);
|
||||||
|
|
||||||
|
buffer = (FAR char *)buffer +
|
||||||
|
ROUNDUP(SIZEOF_OPEN_FILE_ACTION_S(strlen(tmp->path)),
|
||||||
|
sizeof(FAR void *));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: binfmt_freeactions
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Release the copied file action list.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* copy - Pointer of file actions
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void binfmt_freeactions(FAR const posix_spawn_file_actions_t *copy)
|
||||||
|
{
|
||||||
|
/* Is there an allocated argument buffer */
|
||||||
|
|
||||||
|
if (copy != NULL)
|
||||||
|
{
|
||||||
|
/* Free the argument buffer */
|
||||||
|
|
||||||
|
kmm_free((FAR void *)copy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -256,6 +256,12 @@ int exec_module(FAR struct binary_s *binp,
|
|||||||
goto errout_with_args;
|
goto errout_with_args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = binfmt_copyactions(&actions, actions);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
goto errout_with_envp;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
||||||
/* If there is no argument vector, the process name must be copied here */
|
/* If there is no argument vector, the process name must be copied here */
|
||||||
|
|
||||||
@ -271,7 +277,7 @@ int exec_module(FAR struct binary_s *binp,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
berr("ERROR: addrenv_select() failed: %d\n", ret);
|
berr("ERROR: addrenv_select() failed: %d\n", ret);
|
||||||
goto errout_with_envp;
|
goto errout_with_actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = up_addrenv_vheap(addrenv, &vheap);
|
ret = up_addrenv_vheap(addrenv, &vheap);
|
||||||
@ -310,12 +316,14 @@ int exec_module(FAR struct binary_s *binp,
|
|||||||
if (argv && argv[0])
|
if (argv && argv[0])
|
||||||
{
|
{
|
||||||
ret = nxtask_init(tcb, argv[0], binp->priority, stackaddr,
|
ret = nxtask_init(tcb, argv[0], binp->priority, stackaddr,
|
||||||
binp->stacksize, binp->entrypt, &argv[1], envp);
|
binp->stacksize, binp->entrypt, &argv[1],
|
||||||
|
envp, actions);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret = nxtask_init(tcb, filename, binp->priority, stackaddr,
|
ret = nxtask_init(tcb, filename, binp->priority, stackaddr,
|
||||||
binp->stacksize, binp->entrypt, argv, envp);
|
binp->stacksize, binp->entrypt, argv,
|
||||||
|
envp, actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -326,6 +334,7 @@ int exec_module(FAR struct binary_s *binp,
|
|||||||
|
|
||||||
/* The copied argv and envp can now be released */
|
/* The copied argv and envp can now be released */
|
||||||
|
|
||||||
|
binfmt_freeactions(actions);
|
||||||
binfmt_freeargv(argv);
|
binfmt_freeargv(argv);
|
||||||
binfmt_freeenv(envp);
|
binfmt_freeenv(envp);
|
||||||
|
|
||||||
@ -376,10 +385,6 @@ int exec_module(FAR struct binary_s *binp,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Close the file descriptors with O_CLOEXEC before active task */
|
|
||||||
|
|
||||||
files_close_onexec(&tcb->cmn);
|
|
||||||
|
|
||||||
if (!spawn)
|
if (!spawn)
|
||||||
{
|
{
|
||||||
exec_swap(this_task(), (FAR struct tcb_s *)tcb);
|
exec_swap(this_task(), (FAR struct tcb_s *)tcb);
|
||||||
@ -400,17 +405,6 @@ int exec_module(FAR struct binary_s *binp,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Perform file actions */
|
|
||||||
|
|
||||||
if (actions != NULL)
|
|
||||||
{
|
|
||||||
ret = spawn_file_actions(&tcb->cmn, actions);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
goto errout_with_tcbinit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the attributes */
|
/* Set the attributes */
|
||||||
|
|
||||||
if (attr)
|
if (attr)
|
||||||
@ -442,8 +436,10 @@ errout_with_tcbinit:
|
|||||||
errout_with_addrenv:
|
errout_with_addrenv:
|
||||||
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
||||||
addrenv_restore(binp->oldenv);
|
addrenv_restore(binp->oldenv);
|
||||||
errout_with_envp:
|
errout_with_actions:
|
||||||
|
binfmt_freeactions(actions);
|
||||||
#endif
|
#endif
|
||||||
|
errout_with_envp:
|
||||||
binfmt_freeenv(envp);
|
binfmt_freeenv(envp);
|
||||||
errout_with_args:
|
errout_with_args:
|
||||||
binfmt_freeargv(argv);
|
binfmt_freeargv(argv);
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include <nuttx/cancelpt.h>
|
#include <nuttx/cancelpt.h>
|
||||||
#include <nuttx/mutex.h>
|
#include <nuttx/mutex.h>
|
||||||
#include <nuttx/sched.h>
|
#include <nuttx/sched.h>
|
||||||
|
#include <nuttx/spawn.h>
|
||||||
|
|
||||||
#ifdef CONFIG_FDSAN
|
#ifdef CONFIG_FDSAN
|
||||||
# include <android/fdsan.h>
|
# include <android/fdsan.h>
|
||||||
@ -462,20 +463,23 @@ int file_allocate(FAR struct inode *inode, int oflags, off_t pos,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist)
|
int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist,
|
||||||
|
FAR const posix_spawn_file_actions_t *actions,
|
||||||
|
bool cloexec)
|
||||||
{
|
{
|
||||||
|
bool fcloexec;
|
||||||
int ret;
|
int ret;
|
||||||
|
int fd;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
DEBUGASSERT(clist);
|
|
||||||
DEBUGASSERT(plist);
|
|
||||||
|
|
||||||
for (i = 0; i < plist->fl_rows; i++)
|
for (i = 0; i < plist->fl_rows; i++)
|
||||||
{
|
{
|
||||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||||
{
|
{
|
||||||
FAR struct file *filep;
|
FAR struct file *filep;
|
||||||
|
|
||||||
|
fd = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j;
|
||||||
#ifdef CONFIG_FDCLONE_STDIO
|
#ifdef CONFIG_FDCLONE_STDIO
|
||||||
|
|
||||||
/* Determine how many file descriptors to clone. If
|
/* Determine how many file descriptors to clone. If
|
||||||
@ -485,7 +489,7 @@ int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist)
|
|||||||
* cloned. Otherwise all file descriptors will be cloned.
|
* cloned. Otherwise all file descriptors will be cloned.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j >= 3)
|
if (fd >= 3)
|
||||||
{
|
{
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -497,6 +501,22 @@ int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fcloexec = (cloexec && (filep->f_oflags & O_CLOEXEC));
|
||||||
|
|
||||||
|
/* Skip file dup if file action is unnecessary to duplicate */
|
||||||
|
|
||||||
|
if (actions != NULL)
|
||||||
|
{
|
||||||
|
if (!spawn_file_is_duplicateable(actions, fd, fcloexec))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (fcloexec)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ret = files_extend(clist, i + 1);
|
ret = files_extend(clist, i + 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
@ -505,8 +525,7 @@ int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist)
|
|||||||
|
|
||||||
/* Yes... duplicate it for the child, include O_CLOEXEC flag. */
|
/* Yes... duplicate it for the child, include O_CLOEXEC flag. */
|
||||||
|
|
||||||
ret = file_dup3(filep, files_fget_by_index(clist, i, j),
|
ret = file_dup2(filep, files_fget_by_index(clist, i, j));
|
||||||
filep->f_oflags & O_CLOEXEC ? O_CLOEXEC : 0);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
return ret;
|
return ret;
|
||||||
@ -517,41 +536,6 @@ int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: files_close_onexec
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Close specified task's file descriptors with O_CLOEXEC before exec.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
void files_close_onexec(FAR struct tcb_s *tcb)
|
|
||||||
{
|
|
||||||
FAR struct filelist *list;
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
|
|
||||||
/* Get the file descriptor list. It should not be NULL in this context. */
|
|
||||||
|
|
||||||
list = nxsched_get_files_from_tcb(tcb);
|
|
||||||
DEBUGASSERT(list != NULL);
|
|
||||||
|
|
||||||
for (i = 0; i < list->fl_rows; i++)
|
|
||||||
{
|
|
||||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
|
||||||
{
|
|
||||||
FAR struct file *filep;
|
|
||||||
|
|
||||||
filep = files_fget_by_index(list, i, j);
|
|
||||||
if (filep->f_inode != NULL &&
|
|
||||||
(filep->f_oflags & O_CLOEXEC) != 0)
|
|
||||||
{
|
|
||||||
file_close(filep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: fs_getfilep
|
* Name: fs_getfilep
|
||||||
*
|
*
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include <nuttx/semaphore.h>
|
#include <nuttx/semaphore.h>
|
||||||
#include <nuttx/spinlock.h>
|
#include <nuttx/spinlock.h>
|
||||||
#include <nuttx/mm/map.h>
|
#include <nuttx/mm/map.h>
|
||||||
|
#include <nuttx/spawn.h>
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
@ -877,17 +878,9 @@ int files_countlist(FAR struct filelist *list);
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist);
|
int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist,
|
||||||
|
FAR const posix_spawn_file_actions_t *actions,
|
||||||
/****************************************************************************
|
bool cloexec);
|
||||||
* Name: files_close_onexec
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Close specified task's file descriptors with O_CLOEXEC before exec.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
void files_close_onexec(FAR struct tcb_s *tcb);
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: file_allocate_from_tcb
|
* Name: file_allocate_from_tcb
|
||||||
|
@ -923,7 +923,8 @@ FAR struct filelist *nxsched_get_files(void);
|
|||||||
|
|
||||||
int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority,
|
int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority,
|
||||||
FAR void *stack, uint32_t stack_size, main_t entry,
|
FAR void *stack, uint32_t stack_size, main_t entry,
|
||||||
FAR char * const argv[], FAR char * const envp[]);
|
FAR char * const argv[], FAR char * const envp[],
|
||||||
|
FAR const posix_spawn_file_actions_t *actions);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxtask_uninit
|
* Name: nxtask_uninit
|
||||||
|
@ -100,9 +100,14 @@ extern "C"
|
|||||||
void add_file_action(FAR posix_spawn_file_actions_t *file_action,
|
void add_file_action(FAR posix_spawn_file_actions_t *file_action,
|
||||||
FAR struct spawn_general_file_action_s *entry);
|
FAR struct spawn_general_file_action_s *entry);
|
||||||
|
|
||||||
|
struct tcb_s;
|
||||||
int spawn_file_actions(FAR struct tcb_s *tcb,
|
int spawn_file_actions(FAR struct tcb_s *tcb,
|
||||||
FAR const posix_spawn_file_actions_t *actions);
|
FAR const posix_spawn_file_actions_t *actions);
|
||||||
|
|
||||||
|
bool
|
||||||
|
spawn_file_is_duplicateable(FAR const posix_spawn_file_actions_t *actions,
|
||||||
|
int fd, bool cloexec);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -120,6 +120,8 @@ void group_remove_children(FAR struct task_group_s *group);
|
|||||||
/* Group data resource configuration */
|
/* Group data resource configuration */
|
||||||
|
|
||||||
int group_setupidlefiles(void);
|
int group_setupidlefiles(void);
|
||||||
int group_setuptaskfiles(FAR struct task_tcb_s *tcb);
|
int group_setuptaskfiles(FAR struct task_tcb_s *tcb,
|
||||||
|
FAR const posix_spawn_file_actions_t *actions,
|
||||||
|
bool cloexec);
|
||||||
|
|
||||||
#endif /* __SCHED_GROUP_GROUP_H */
|
#endif /* __SCHED_GROUP_GROUP_H */
|
||||||
|
@ -45,7 +45,9 @@
|
|||||||
* file descriptors and streams from the parent task.
|
* file descriptors and streams from the parent task.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* tcb - tcb of the new task.
|
* tcb - tcb of the new task.
|
||||||
|
* actions - The spawn file actions
|
||||||
|
* cloexec - Perform O_CLOEXEC on setup task files
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Zero (OK) is returned on success; A negated errno value is returned on
|
* Zero (OK) is returned on success; A negated errno value is returned on
|
||||||
@ -55,7 +57,9 @@
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int group_setuptaskfiles(FAR struct task_tcb_s *tcb)
|
int group_setuptaskfiles(FAR struct task_tcb_s *tcb,
|
||||||
|
FAR const posix_spawn_file_actions_t *actions,
|
||||||
|
bool cloexec)
|
||||||
{
|
{
|
||||||
FAR struct task_group_s *group = tcb->cmn.group;
|
FAR struct task_group_s *group = tcb->cmn.group;
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
@ -75,7 +79,12 @@ int group_setuptaskfiles(FAR struct task_tcb_s *tcb)
|
|||||||
|
|
||||||
/* Duplicate the parent task's file descriptors */
|
/* Duplicate the parent task's file descriptors */
|
||||||
|
|
||||||
ret = files_duplist(&rtcb->group->tg_filelist, &group->tg_filelist);
|
ret = files_duplist(&rtcb->group->tg_filelist,
|
||||||
|
&group->tg_filelist, actions, cloexec);
|
||||||
|
if (ret >= 0 && actions != NULL)
|
||||||
|
{
|
||||||
|
ret = spawn_file_actions(&tcb->cmn, actions);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sched_trace_end();
|
sched_trace_end();
|
||||||
|
@ -649,7 +649,7 @@ void nx_start(void)
|
|||||||
{
|
{
|
||||||
/* Clone stdout, stderr, stdin from the CPU0 IDLE task. */
|
/* Clone stdout, stderr, stdin from the CPU0 IDLE task. */
|
||||||
|
|
||||||
DEBUGVERIFY(group_setuptaskfiles(&g_idletcb[i]));
|
DEBUGVERIFY(group_setuptaskfiles(&g_idletcb[i], NULL, true));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -96,17 +96,13 @@ int nxthread_create(FAR const char *name, uint8_t ttype, int priority,
|
|||||||
/* Initialize the task */
|
/* Initialize the task */
|
||||||
|
|
||||||
ret = nxtask_init(tcb, name, priority, stack_addr, stack_size,
|
ret = nxtask_init(tcb, name, priority, stack_addr, stack_size,
|
||||||
entry, argv, envp);
|
entry, argv, envp, NULL);
|
||||||
if (ret < OK)
|
if (ret < OK)
|
||||||
{
|
{
|
||||||
kmm_free(tcb);
|
kmm_free(tcb);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close the file descriptors with O_CLOEXEC before active task */
|
|
||||||
|
|
||||||
files_close_onexec(&tcb->cmn);
|
|
||||||
|
|
||||||
/* Get the assigned pid before we start the task */
|
/* Get the assigned pid before we start the task */
|
||||||
|
|
||||||
pid = tcb->cmn.pid;
|
pid = tcb->cmn.pid;
|
||||||
|
@ -160,7 +160,7 @@ FAR struct task_tcb_s *nxtask_setup_fork(start_t retaddr)
|
|||||||
|
|
||||||
/* Associate file descriptors with the new task */
|
/* Associate file descriptors with the new task */
|
||||||
|
|
||||||
ret = group_setuptaskfiles(child);
|
ret = group_setuptaskfiles(child, NULL, false);
|
||||||
if (ret < OK)
|
if (ret < OK)
|
||||||
{
|
{
|
||||||
goto errout_with_tcb;
|
goto errout_with_tcb;
|
||||||
|
@ -86,7 +86,8 @@
|
|||||||
int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority,
|
int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority,
|
||||||
FAR void *stack, uint32_t stack_size,
|
FAR void *stack, uint32_t stack_size,
|
||||||
main_t entry, FAR char * const argv[],
|
main_t entry, FAR char * const argv[],
|
||||||
FAR char * const envp[])
|
FAR char * const envp[],
|
||||||
|
FAR const posix_spawn_file_actions_t *actions)
|
||||||
{
|
{
|
||||||
uint8_t ttype = tcb->cmn.flags & TCB_FLAG_TTYPE_MASK;
|
uint8_t ttype = tcb->cmn.flags & TCB_FLAG_TTYPE_MASK;
|
||||||
int ret;
|
int ret;
|
||||||
@ -127,7 +128,7 @@ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority,
|
|||||||
|
|
||||||
/* Associate file descriptors with the new task */
|
/* Associate file descriptors with the new task */
|
||||||
|
|
||||||
ret = group_setuptaskfiles(tcb);
|
ret = group_setuptaskfiles(tcb, actions, true);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
goto errout_with_group;
|
goto errout_with_group;
|
||||||
|
@ -104,7 +104,7 @@ static int nxtask_spawn_create(FAR const char *name, int priority,
|
|||||||
/* Initialize the task */
|
/* Initialize the task */
|
||||||
|
|
||||||
ret = nxtask_init(tcb, name, priority, stack_addr, stack_size,
|
ret = nxtask_init(tcb, name, priority, stack_addr, stack_size,
|
||||||
entry, argv, envp);
|
entry, argv, envp, actions);
|
||||||
if (ret < OK)
|
if (ret < OK)
|
||||||
{
|
{
|
||||||
kmm_free(tcb);
|
kmm_free(tcb);
|
||||||
@ -115,21 +115,6 @@ static int nxtask_spawn_create(FAR const char *name, int priority,
|
|||||||
|
|
||||||
pid = tcb->cmn.pid;
|
pid = tcb->cmn.pid;
|
||||||
|
|
||||||
/* Perform file actions */
|
|
||||||
|
|
||||||
if (actions != NULL)
|
|
||||||
{
|
|
||||||
ret = spawn_file_actions(&tcb->cmn, actions);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
goto errout_with_taskinit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close the file descriptors with O_CLOEXEC before active task */
|
|
||||||
|
|
||||||
files_close_onexec(&tcb->cmn);
|
|
||||||
|
|
||||||
/* Set the attributes */
|
/* Set the attributes */
|
||||||
|
|
||||||
if (attr)
|
if (attr)
|
||||||
|
@ -247,7 +247,7 @@ int spawn_execattrs(pid_t pid, FAR const posix_spawnattr_t *attr)
|
|||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
*
|
*
|
||||||
* attr - The spawn file actions
|
* actions - The spawn file actions
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* 0 (OK) on success; A negated errno value is returned on failure.
|
* 0 (OK) on success; A negated errno value is returned on failure.
|
||||||
@ -296,3 +296,77 @@ int spawn_file_actions(FAR struct tcb_s *tcb,
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: spawn_file_is_duplicateable
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Check the input file descriptor is duplicateable from spawn actions
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
*
|
||||||
|
* actions - The spawn file actions
|
||||||
|
* fd - file descriptor
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* True is returned if file descriptor is duplicate able
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
bool
|
||||||
|
spawn_file_is_duplicateable(FAR const posix_spawn_file_actions_t *actions,
|
||||||
|
int fd, bool cloexec)
|
||||||
|
{
|
||||||
|
FAR struct spawn_general_file_action_s *entry;
|
||||||
|
FAR struct spawn_close_file_action_s *close;
|
||||||
|
FAR struct spawn_open_file_action_s *open;
|
||||||
|
FAR struct spawn_dup2_file_action_s *dup2;
|
||||||
|
|
||||||
|
/* check each file action */
|
||||||
|
|
||||||
|
for (entry = (FAR struct spawn_general_file_action_s *)actions;
|
||||||
|
entry != NULL;
|
||||||
|
entry = entry->flink)
|
||||||
|
{
|
||||||
|
switch (entry->action)
|
||||||
|
{
|
||||||
|
case SPAWN_FILE_ACTION_CLOSE:
|
||||||
|
close = (FAR struct spawn_close_file_action_s *)entry;
|
||||||
|
if (close->fd == fd)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPAWN_FILE_ACTION_DUP2:
|
||||||
|
dup2 = (FAR struct spawn_dup2_file_action_s *)entry;
|
||||||
|
if (dup2->fd1 == fd)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (dup2->fd2 == fd)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPAWN_FILE_ACTION_OPEN:
|
||||||
|
open = (FAR struct spawn_open_file_action_s *)entry;
|
||||||
|
if (open->fd == fd)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cloexec)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user