forked from nuttx/nuttx-update
sched/task/fork: add fork implementation
1. as we can use fork to implement vfork, so we rename the vfork to fork, and use the fork method as the base to implement vfork method 2. create the vfork function as a libc function based on fork function Signed-off-by: guoshichao <guoshichao@xiaomi.com>
This commit is contained in:
parent
5d7864fbcb
commit
c33d1c9c97
39 changed files with 797 additions and 740 deletions
10
arch/Kconfig
10
arch/Kconfig
|
@ -11,7 +11,7 @@ config ARCH_ARM
|
|||
bool "ARM"
|
||||
select ARCH_HAVE_BACKTRACE
|
||||
select ARCH_HAVE_INTERRUPTSTACK
|
||||
select ARCH_HAVE_VFORK
|
||||
select ARCH_HAVE_FORK
|
||||
select ARCH_HAVE_STACKCHECK
|
||||
select ARCH_HAVE_CUSTOMOPT
|
||||
select ARCH_HAVE_STDARG_H
|
||||
|
@ -27,7 +27,7 @@ config ARCH_ARM64
|
|||
select ALARM_ARCH
|
||||
select ARCH_HAVE_BACKTRACE
|
||||
select ARCH_HAVE_INTERRUPTSTACK
|
||||
select ARCH_HAVE_VFORK
|
||||
select ARCH_HAVE_FORK
|
||||
select ARCH_HAVE_STACKCHECK
|
||||
select ARCH_HAVE_CUSTOMOPT
|
||||
select ARCH_HAVE_STDARG_H
|
||||
|
@ -81,7 +81,7 @@ config ARCH_RISCV
|
|||
select ARCH_HAVE_CPUINFO
|
||||
select ARCH_HAVE_INTERRUPTSTACK
|
||||
select ARCH_HAVE_STACKCHECK
|
||||
select ARCH_HAVE_VFORK
|
||||
select ARCH_HAVE_FORK
|
||||
select ARCH_HAVE_CUSTOMOPT
|
||||
select ARCH_HAVE_SETJMP
|
||||
select ARCH_HAVE_STDARG_H
|
||||
|
@ -101,7 +101,7 @@ config ARCH_SIM
|
|||
select ARCH_HAVE_TICKLESS
|
||||
select ARCH_HAVE_POWEROFF
|
||||
select ARCH_HAVE_TESTSET
|
||||
select ARCH_HAVE_VFORK if !HOST_WINDOWS
|
||||
select ARCH_HAVE_FORK if !HOST_WINDOWS
|
||||
select ARCH_HAVE_SETJMP
|
||||
select ARCH_HAVE_CUSTOMOPT
|
||||
select ARCH_HAVE_TEXT_HEAP
|
||||
|
@ -392,7 +392,7 @@ config ARCH_HAVE_MULTICPU
|
|||
bool
|
||||
default n
|
||||
|
||||
config ARCH_HAVE_VFORK
|
||||
config ARCH_HAVE_FORK
|
||||
bool
|
||||
default n
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ CMN_CSRCS += arm_getintstack.c arm_initialize.c arm_lowputs.c
|
|||
CMN_CSRCS += arm_modifyreg8.c arm_modifyreg16.c arm_modifyreg32.c
|
||||
CMN_CSRCS += arm_nputs.c arm_releasestack.c arm_registerdump.c
|
||||
CMN_CSRCS += arm_stackframe.c arm_switchcontext.c
|
||||
CMN_CSRCS += arm_usestack.c arm_vfork.c
|
||||
CMN_CSRCS += arm_usestack.c arm_fork.c
|
||||
|
||||
ifneq ($(CONFIG_ALARM_ARCH),y)
|
||||
ifneq ($(CONFIG_TIMER_ARCH),y)
|
||||
|
@ -73,7 +73,7 @@ ifeq ($(CONFIG_UNWINDER_ARM),y)
|
|||
CMN_CSRCS += arm_backtrace_unwind.c
|
||||
endif
|
||||
|
||||
CMN_ASRCS += vfork.S
|
||||
CMN_ASRCS += fork.S
|
||||
|
||||
ifeq ($(CONFIG_ARCH_HAVE_TESTSET),y)
|
||||
ifeq ($(CONFIG_ARCH_ARMV6M),)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/common/arm_vfork.c
|
||||
* arch/arm/src/common/arm_fork.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -35,7 +35,7 @@
|
|||
#include <nuttx/arch.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
#include "arm_vfork.h"
|
||||
#include "arm_fork.h"
|
||||
#include "arm_internal.h"
|
||||
#include "sched/sched.h"
|
||||
|
||||
|
@ -44,22 +44,22 @@
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_vfork
|
||||
* Name: up_fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the
|
||||
* behavior is undefined if the process created by vfork() either modifies
|
||||
* The fork() function has the same effect as posix fork(), except that the
|
||||
* behavior is undefined if the process created by fork() either modifies
|
||||
* any data other than a variable of type pid_t used to store the return
|
||||
* value from vfork(), or returns from the function in which vfork() was
|
||||
* value from fork(), or returns from the function in which fork() was
|
||||
* called, or calls any other function before successfully calling _exit()
|
||||
* or one of the exec family of functions.
|
||||
*
|
||||
* The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork() and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB.
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork() and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB.
|
||||
* This consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -67,27 +67,27 @@
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* nxtask_abort_vfork() may be called if an error occurs between steps 3 and
|
||||
* nxtask_abort_fork() may be called if an error occurs between steps 3 and
|
||||
* 6.
|
||||
*
|
||||
* Input Parameters:
|
||||
* context - Caller context information saved by vfork()
|
||||
* context - Caller context information saved by fork()
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and
|
||||
* Upon successful completion, fork() returns 0 to the child process and
|
||||
* returns the process ID of the child process to the parent process.
|
||||
* Otherwise, -1 is returned to the parent, no child process is created,
|
||||
* and errno is set to indicate the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
pid_t up_vfork(const struct vfork_s *context)
|
||||
pid_t up_fork(const struct fork_s *context)
|
||||
{
|
||||
struct tcb_s *parent = this_task();
|
||||
struct task_tcb_s *child;
|
||||
|
@ -97,7 +97,7 @@ pid_t up_vfork(const struct vfork_s *context)
|
|||
uint32_t stacktop;
|
||||
uint32_t stackutil;
|
||||
|
||||
sinfo("vfork context [%p]:\n", context);
|
||||
sinfo("fork context [%p]:\n", context);
|
||||
sinfo(" r4:%08" PRIx32 " r5:%08" PRIx32
|
||||
" r6:%08" PRIx32 " r7:%08" PRIx32 "\n",
|
||||
context->r4, context->r5, context->r6, context->r7);
|
||||
|
@ -108,10 +108,10 @@ pid_t up_vfork(const struct vfork_s *context)
|
|||
|
||||
/* Allocate and initialize a TCB for the child task. */
|
||||
|
||||
child = nxtask_setup_vfork((start_t)(context->lr & ~1));
|
||||
child = nxtask_setup_fork((start_t)(context->lr & ~1));
|
||||
if (!child)
|
||||
{
|
||||
serr("ERROR: nxtask_setup_vfork failed\n");
|
||||
serr("ERROR: nxtask_setup_fork failed\n");
|
||||
return (pid_t)ERROR;
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ pid_t up_vfork(const struct vfork_s *context)
|
|||
/* Make some feeble effort to preserve the stack contents. This is
|
||||
* feeble because the stack surely contains invalid pointers and other
|
||||
* content that will not work in the child context. However, if the
|
||||
* user follows all of the caveats of vfork() usage, even this feeble
|
||||
* user follows all of the caveats of fork() usage, even this feeble
|
||||
* effort is overkill.
|
||||
*/
|
||||
|
||||
|
@ -229,9 +229,9 @@ pid_t up_vfork(const struct vfork_s *context)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* And, finally, start the child task. On a failure, nxtask_start_vfork()
|
||||
* will discard the TCB by calling nxtask_abort_vfork().
|
||||
/* And, finally, start the child task. On a failure, nxtask_start_fork()
|
||||
* will discard the TCB by calling nxtask_abort_fork().
|
||||
*/
|
||||
|
||||
return nxtask_start_vfork(child);
|
||||
return nxtask_start_fork(child);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/common/arm_vfork.h
|
||||
* arch/arm/src/common/arm_fork.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -18,8 +18,8 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_COMMON_ARM_VFORK_H
|
||||
#define __ARCH_ARM_SRC_COMMON_ARM_VFORK_H
|
||||
#ifndef __ARCH_ARM_SRC_COMMON_ARM_FORK_H
|
||||
#define __ARCH_ARM_SRC_COMMON_ARM_FORK_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
|
@ -31,26 +31,26 @@
|
|||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define VFORK_R4_OFFSET (0*4) /* Volatile register r4 */
|
||||
#define VFORK_R5_OFFSET (1*4) /* Volatile register r5 */
|
||||
#define VFORK_R6_OFFSET (2*4) /* Volatile register r6 */
|
||||
#define VFORK_R7_OFFSET (3*4) /* Volatile register r7 */
|
||||
#define VFORK_R8_OFFSET (4*4) /* Volatile register r8 */
|
||||
#define VFORK_R9_OFFSET (5*4) /* Volatile register r9 */
|
||||
#define VFORK_R10_OFFSET (6*4) /* Volatile register r10 */
|
||||
#define FORK_R4_OFFSET (0*4) /* Volatile register r4 */
|
||||
#define FORK_R5_OFFSET (1*4) /* Volatile register r5 */
|
||||
#define FORK_R6_OFFSET (2*4) /* Volatile register r6 */
|
||||
#define FORK_R7_OFFSET (3*4) /* Volatile register r7 */
|
||||
#define FORK_R8_OFFSET (4*4) /* Volatile register r8 */
|
||||
#define FORK_R9_OFFSET (5*4) /* Volatile register r9 */
|
||||
#define FORK_R10_OFFSET (6*4) /* Volatile register r10 */
|
||||
|
||||
#define VFORK_FP_OFFSET (7*4) /* Frame pointer */
|
||||
#define VFORK_SP_OFFSET (8*4) /* Stack pointer*/
|
||||
#define VFORK_LR_OFFSET (9*4) /* Return address*/
|
||||
#define FORK_FP_OFFSET (7*4) /* Frame pointer */
|
||||
#define FORK_SP_OFFSET (8*4) /* Stack pointer*/
|
||||
#define FORK_LR_OFFSET (9*4) /* Return address*/
|
||||
|
||||
#define VFORK_SIZEOF (10*4)
|
||||
#define FORK_SIZEOF (10*4)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
struct vfork_s
|
||||
struct fork_s
|
||||
{
|
||||
/* CPU registers */
|
||||
|
||||
|
@ -70,4 +70,4 @@ struct vfork_s
|
|||
};
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_COMMON_ARM_VFORK_H */
|
||||
#endif /* __ARCH_ARM_SRC_COMMON_ARM_FORK_H */
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/common/vfork.S
|
||||
* arch/arm/src/common/fork.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -24,33 +24,33 @@
|
|||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "arm_vfork.h"
|
||||
#include "arm_fork.h"
|
||||
|
||||
.syntax unified
|
||||
.file "vfork.S"
|
||||
.file "fork.S"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vfork
|
||||
* Name: fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the
|
||||
* behavior is undefined if the process created by vfork() either modifies
|
||||
* The fork() function has the same effect as posix fork(), except that the
|
||||
* behavior is undefined if the process created by fork() either modifies
|
||||
* any data other than a variable of type pid_t used to store the return
|
||||
* value from vfork(), or returns from the function in which vfork() was
|
||||
* value from fork(), or returns from the function in which fork() was
|
||||
* called, or calls any other function before successfully calling _exit()
|
||||
* or one of the exec family of functions.
|
||||
*
|
||||
* This thin layer implements vfork by simply calling up_vfork() with the
|
||||
* vfork() context as an argument. The overall sequence is:
|
||||
* This thin layer implements fork by simply calling up_fork() with the
|
||||
* fork() context as an argument. The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork() and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB.
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork() and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB.
|
||||
* This consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -58,31 +58,31 @@
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and
|
||||
* Upon successful completion, fork() returns 0 to the child process and
|
||||
* returns the process ID of the child process to the parent process.
|
||||
* Otherwise, -1 is returned to the parent, no child process is created,
|
||||
* and errno is set to indicate the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.globl vfork
|
||||
.type vfork, function
|
||||
.globl fork
|
||||
.type fork, function
|
||||
|
||||
vfork:
|
||||
fork:
|
||||
/* Create a stack frame */
|
||||
|
||||
mov r0, sp /* Save the value of the stack on entry */
|
||||
sub sp, sp, #VFORK_SIZEOF /* Allocate the structure on the stack */
|
||||
sub sp, sp, #FORK_SIZEOF /* Allocate the structure on the stack */
|
||||
|
||||
/* CPU registers */
|
||||
/* Save the volatile registers */
|
||||
|
@ -97,22 +97,22 @@ vfork:
|
|||
mov r5, lr /* Copy lr to a low register */
|
||||
stmia r1!, {r0,r5} /* Save sp and lr in the structure */
|
||||
|
||||
/* Then, call up_vfork(), passing it a pointer to the stack structure */
|
||||
/* Then, call up_fork(), passing it a pointer to the stack structure */
|
||||
|
||||
mov r0, sp
|
||||
bl up_vfork
|
||||
bl up_fork
|
||||
|
||||
/* Recover r4-r7 that were destroyed before up_vfork was called */
|
||||
/* Recover r4-r7 that were destroyed before up_fork was called */
|
||||
|
||||
mov r1, sp
|
||||
ldmia r1!, {r4-r7}
|
||||
|
||||
/* Release the stack data and return the value returned by up_vfork */
|
||||
/* Release the stack data and return the value returned by up_fork */
|
||||
|
||||
ldr r1, [sp, #VFORK_LR_OFFSET]
|
||||
ldr r1, [sp, #FORK_LR_OFFSET]
|
||||
mov r14, r1
|
||||
add sp, sp, #VFORK_SIZEOF
|
||||
add sp, sp, #FORK_SIZEOF
|
||||
bx lr
|
||||
|
||||
.size vfork, .-vfork
|
||||
.size fork, .-fork
|
||||
.end
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/common/iar/vfork.S
|
||||
* arch/arm/src/common/iar/fork.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -24,9 +24,9 @@
|
|||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "arm_vfork.h"
|
||||
#include "arm_fork.h"
|
||||
|
||||
MODULE vfork
|
||||
MODULE fork
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -37,31 +37,31 @@
|
|||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
PUBLIC vfork
|
||||
EXTERN up_vfork
|
||||
PUBLIC fork
|
||||
EXTERN up_fork
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vfork
|
||||
* Name: fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the
|
||||
* behavior is undefined if the process created by vfork() either modifies
|
||||
* The fork() function has the same effect as posix fork(), except that the
|
||||
* behavior is undefined if the process created by fork() either modifies
|
||||
* any data other than a variable of type pid_t used to store the return
|
||||
* value from vfork(), or returns from the function in which vfork() was
|
||||
* value from fork(), or returns from the function in which fork() was
|
||||
* called, or calls any other function before successfully calling _exit()
|
||||
* or one of the exec family of functions.
|
||||
*
|
||||
* This thin layer implements vfork by simply calling up_vfork() with the
|
||||
* vfork() context as an argument. The overall sequence is:
|
||||
* This thin layer implements fork by simply calling up_fork() with the
|
||||
* fork() context as an argument. The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork() and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB.
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork() and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB.
|
||||
* This consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -69,17 +69,17 @@
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and
|
||||
* Upon successful completion, fork() returns 0 to the child process and
|
||||
* returns the process ID of the child process to the parent process.
|
||||
* Otherwise, -1 is returned to the parent, no child process is created,
|
||||
* and errno is set to indicate the error.
|
||||
|
@ -88,40 +88,40 @@
|
|||
|
||||
THUMB
|
||||
|
||||
vfork:
|
||||
fork:
|
||||
/* Create a stack frame */
|
||||
|
||||
mov r0, sp /* Save the value of the stack on entry */
|
||||
sub sp, sp, #VFORK_SIZEOF /* Allocate the structure on the stack */
|
||||
sub sp, sp, #FORK_SIZEOF /* Allocate the structure on the stack */
|
||||
|
||||
/* CPU registers */
|
||||
/* Save the volatile registers */
|
||||
|
||||
str r4, [sp, #VFORK_R4_OFFSET]
|
||||
str r5, [sp, #VFORK_R5_OFFSET]
|
||||
str r6, [sp, #VFORK_R6_OFFSET]
|
||||
str r7, [sp, #VFORK_R7_OFFSET]
|
||||
str r8, [sp, #VFORK_R8_OFFSET]
|
||||
str r9, [sp, #VFORK_R9_OFFSET]
|
||||
str r10, [sp, #VFORK_R10_OFFSET]
|
||||
str r4, [sp, #FORK_R4_OFFSET]
|
||||
str r5, [sp, #FORK_R5_OFFSET]
|
||||
str r6, [sp, #FORK_R6_OFFSET]
|
||||
str r7, [sp, #FORK_R7_OFFSET]
|
||||
str r8, [sp, #FORK_R8_OFFSET]
|
||||
str r9, [sp, #FORK_R9_OFFSET]
|
||||
str r10, [sp, #FORK_R10_OFFSET]
|
||||
|
||||
/* Save the frame pointer, stack pointer, and return address */
|
||||
|
||||
str r11, [sp, #VFORK_FP_OFFSET] /* fp not defined. use r11 */
|
||||
str r0, [sp, #VFORK_SP_OFFSET]
|
||||
str lr, [sp, #VFORK_LR_OFFSET]
|
||||
str r11, [sp, #FORK_FP_OFFSET] /* fp not defined. use r11 */
|
||||
str r0, [sp, #FORK_SP_OFFSET]
|
||||
str lr, [sp, #FORK_LR_OFFSET]
|
||||
|
||||
/* Floating point registers (not yet) */
|
||||
|
||||
/* Then, call up_vfork(), passing it a pointer to the stack structure */
|
||||
/* Then, call up_fork(), passing it a pointer to the stack structure */
|
||||
|
||||
mov r0, sp
|
||||
bl up_vfork
|
||||
bl up_fork
|
||||
|
||||
/* Release the stack data and return the value returned by up_vfork */
|
||||
/* Release the stack data and return the value returned by up_fork */
|
||||
|
||||
ldr lr, [sp, #VFORK_LR_OFFSET]
|
||||
add sp, sp, #VFORK_SIZEOF
|
||||
ldr lr, [sp, #FORK_LR_OFFSET]
|
||||
add sp, sp, #FORK_SIZEOF
|
||||
bx lr
|
||||
|
||||
END
|
|
@ -35,7 +35,7 @@ endif
|
|||
|
||||
# Common assembly language files
|
||||
CMN_ASRCS = arm64_vector_table.S arm64_vectors.S arm64_smccc.S
|
||||
CMN_ASRCS += arm64_cpu_idle.S arm64_vfork_func.S
|
||||
CMN_ASRCS += arm64_cpu_idle.S arm64_fork_func.S
|
||||
|
||||
ifeq ($(CONFIG_ARCH_HAVE_TESTSET),y)
|
||||
CMN_ASRCS += arm64_testset.S
|
||||
|
@ -45,7 +45,7 @@ endif
|
|||
CMN_CSRCS = arm64_initialize.c arm64_initialstate.c arm64_boot.c
|
||||
CMN_CSRCS += arm64_nputs.c arm64_idle.c arm64_copystate.c arm64_createstack.c
|
||||
CMN_CSRCS += arm64_releasestack.c arm64_stackframe.c arm64_usestack.c
|
||||
CMN_CSRCS += arm64_task_sched.c arm64_exit.c arm64_vfork.c arm64_switchcontext.c
|
||||
CMN_CSRCS += arm64_task_sched.c arm64_exit.c arm64_fork.c arm64_switchcontext.c
|
||||
CMN_CSRCS += arm64_schedulesigaction.c arm64_sigdeliver.c
|
||||
CMN_CSRCS += arm64_getintstack.c arm64_registerdump.c
|
||||
CMN_CSRCS += arm64_perf.c
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/common/arm64_vfork.c
|
||||
* arch/arm64/src/common/arm64_fork.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -37,7 +37,7 @@
|
|||
#include "sched/sched.h"
|
||||
|
||||
#include "arm64_arch.h"
|
||||
#include "arm64_vfork.h"
|
||||
#include "arm64_fork.h"
|
||||
#include "arm64_internal.h"
|
||||
#include "arm64_fatal.h"
|
||||
|
||||
|
@ -55,7 +55,7 @@
|
|||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
|
||||
void arm64_vfork_fpureg_save(struct vfork_s *context)
|
||||
void arm64_fork_fpureg_save(struct fork_s *context)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
|
@ -75,22 +75,22 @@ void arm64_vfork_fpureg_save(struct vfork_s *context)
|
|||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vfork
|
||||
* Name: fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the
|
||||
* behavior is undefined if the process created by vfork() either modifies
|
||||
* The fork() function has the same effect as posix fork(), except that the
|
||||
* behavior is undefined if the process created by fork() either modifies
|
||||
* any data other than a variable of type pid_t used to store the return
|
||||
* value from vfork(), or returns from the function in which vfork() was
|
||||
* value from fork(), or returns from the function in which fork() was
|
||||
* called, or calls any other function before successfully calling _exit()
|
||||
* or one of the exec family of functions.
|
||||
*
|
||||
* The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork() and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB.
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork() and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB.
|
||||
* This consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -98,27 +98,27 @@ void arm64_vfork_fpureg_save(struct vfork_s *context)
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* nxtask_abort_vfork() may be called if an error occurs between steps 3 and
|
||||
* nxtask_abort_fork() may be called if an error occurs between steps 3 and
|
||||
* 6.
|
||||
*
|
||||
* Input Parameters:
|
||||
* context - Caller context information saved by vfork()
|
||||
* context - Caller context information saved by fork()
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and
|
||||
* Upon successful completion, fork() returns 0 to the child process and
|
||||
* returns the process ID of the child process to the parent process.
|
||||
* Otherwise, -1 is returned to the parent, no child process is created,
|
||||
* and errno is set to indicate the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
pid_t up_vfork(const struct vfork_s *context)
|
||||
pid_t up_fork(const struct fork_s *context)
|
||||
{
|
||||
struct tcb_s *parent = this_task();
|
||||
struct task_tcb_s *child;
|
||||
|
@ -128,17 +128,17 @@ pid_t up_vfork(const struct vfork_s *context)
|
|||
uint64_t stacktop;
|
||||
uint64_t stackutil;
|
||||
char *stack_ptr;
|
||||
struct regs_context *pvforkctx;
|
||||
struct regs_context *pforkctx;
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
struct fpu_reg *pfpuctx;
|
||||
#endif
|
||||
|
||||
/* Allocate and initialize a TCB for the child task. */
|
||||
|
||||
child = nxtask_setup_vfork((start_t)(context->lr & ~1));
|
||||
child = nxtask_setup_fork((start_t)(context->lr & ~1));
|
||||
if (!child)
|
||||
{
|
||||
serr("ERROR: nxtask_setup_vfork failed\n");
|
||||
serr("ERROR: nxtask_setup_fork failed\n");
|
||||
return (pid_t)ERROR;
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ pid_t up_vfork(const struct vfork_s *context)
|
|||
/* Make some feeble effort to preserve the stack contents. This is
|
||||
* feeble because the stack surely contains invalid pointers and other
|
||||
* content that will not work in the child context. However, if the
|
||||
* user follows all of the caveats of vfork() usage, even this feeble
|
||||
* user follows all of the caveats of fork() usage, even this feeble
|
||||
* effort is overkill.
|
||||
*/
|
||||
|
||||
|
@ -184,7 +184,7 @@ pid_t up_vfork(const struct vfork_s *context)
|
|||
* child thread.
|
||||
*/
|
||||
|
||||
/* make the vfork stack frame */
|
||||
/* make the fork stack frame */
|
||||
|
||||
stack_ptr = (char *)newsp;
|
||||
|
||||
|
@ -198,51 +198,51 @@ pid_t up_vfork(const struct vfork_s *context)
|
|||
|
||||
#endif
|
||||
|
||||
pvforkctx = STACK_PTR_TO_FRAME(struct regs_context, stack_ptr);
|
||||
pforkctx = STACK_PTR_TO_FRAME(struct regs_context, stack_ptr);
|
||||
|
||||
pvforkctx->regs[REG_X0] = 0;
|
||||
pvforkctx->regs[REG_X8] = context->regs[VFORK_REG_X8];
|
||||
pvforkctx->regs[REG_X9] = context->regs[VFORK_REG_X9];
|
||||
pvforkctx->regs[REG_X10] = context->regs[VFORK_REG_X10];
|
||||
pvforkctx->regs[REG_X11] = context->regs[VFORK_REG_X11];
|
||||
pvforkctx->regs[REG_X12] = context->regs[VFORK_REG_X12];
|
||||
pvforkctx->regs[REG_X13] = context->regs[VFORK_REG_X13];
|
||||
pvforkctx->regs[REG_X14] = context->regs[VFORK_REG_X14];
|
||||
pvforkctx->regs[REG_X15] = context->regs[VFORK_REG_X15];
|
||||
pvforkctx->regs[REG_X16] = context->regs[VFORK_REG_X16];
|
||||
pvforkctx->regs[REG_X17] = context->regs[VFORK_REG_X17];
|
||||
pvforkctx->regs[REG_X18] = context->regs[VFORK_REG_X18];
|
||||
pvforkctx->regs[REG_X19] = context->regs[VFORK_REG_X19];
|
||||
pvforkctx->regs[REG_X20] = context->regs[VFORK_REG_X20];
|
||||
pvforkctx->regs[REG_X21] = context->regs[VFORK_REG_X21];
|
||||
pvforkctx->regs[REG_X22] = context->regs[VFORK_REG_X22];
|
||||
pvforkctx->regs[REG_X23] = context->regs[VFORK_REG_X23];
|
||||
pvforkctx->regs[REG_X24] = context->regs[VFORK_REG_X24];
|
||||
pvforkctx->regs[REG_X25] = context->regs[VFORK_REG_X25];
|
||||
pvforkctx->regs[REG_X26] = context->regs[VFORK_REG_X26];
|
||||
pvforkctx->regs[REG_X27] = context->regs[VFORK_REG_X27];
|
||||
pvforkctx->regs[REG_X28] = context->regs[VFORK_REG_X28];
|
||||
pvforkctx->regs[REG_X29] = newfp;
|
||||
pforkctx->regs[REG_X0] = 0;
|
||||
pforkctx->regs[REG_X8] = context->regs[FORK_REG_X8];
|
||||
pforkctx->regs[REG_X9] = context->regs[FORK_REG_X9];
|
||||
pforkctx->regs[REG_X10] = context->regs[FORK_REG_X10];
|
||||
pforkctx->regs[REG_X11] = context->regs[FORK_REG_X11];
|
||||
pforkctx->regs[REG_X12] = context->regs[FORK_REG_X12];
|
||||
pforkctx->regs[REG_X13] = context->regs[FORK_REG_X13];
|
||||
pforkctx->regs[REG_X14] = context->regs[FORK_REG_X14];
|
||||
pforkctx->regs[REG_X15] = context->regs[FORK_REG_X15];
|
||||
pforkctx->regs[REG_X16] = context->regs[FORK_REG_X16];
|
||||
pforkctx->regs[REG_X17] = context->regs[FORK_REG_X17];
|
||||
pforkctx->regs[REG_X18] = context->regs[FORK_REG_X18];
|
||||
pforkctx->regs[REG_X19] = context->regs[FORK_REG_X19];
|
||||
pforkctx->regs[REG_X20] = context->regs[FORK_REG_X20];
|
||||
pforkctx->regs[REG_X21] = context->regs[FORK_REG_X21];
|
||||
pforkctx->regs[REG_X22] = context->regs[FORK_REG_X22];
|
||||
pforkctx->regs[REG_X23] = context->regs[FORK_REG_X23];
|
||||
pforkctx->regs[REG_X24] = context->regs[FORK_REG_X24];
|
||||
pforkctx->regs[REG_X25] = context->regs[FORK_REG_X25];
|
||||
pforkctx->regs[REG_X26] = context->regs[FORK_REG_X26];
|
||||
pforkctx->regs[REG_X27] = context->regs[FORK_REG_X27];
|
||||
pforkctx->regs[REG_X28] = context->regs[FORK_REG_X28];
|
||||
pforkctx->regs[REG_X29] = newfp;
|
||||
|
||||
pvforkctx->spsr = SPSR_MODE_EL1H;
|
||||
pforkctx->spsr = SPSR_MODE_EL1H;
|
||||
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
pvforkctx->spsr |= (DAIF_IRQ_BIT | DAIF_FIQ_BIT);
|
||||
pforkctx->spsr |= (DAIF_IRQ_BIT | DAIF_FIQ_BIT);
|
||||
#endif /* CONFIG_SUPPRESS_INTERRUPTS */
|
||||
|
||||
pvforkctx->elr = (uint64_t)context->lr;
|
||||
pforkctx->elr = (uint64_t)context->lr;
|
||||
|
||||
pvforkctx->exe_depth = 0;
|
||||
pvforkctx->sp_elx = (uint64_t)pvforkctx;
|
||||
pvforkctx->sp_el0 = (uint64_t)pvforkctx;
|
||||
pvforkctx->tpidr_el0 = (uint64_t)(&child->cmn);
|
||||
pvforkctx->tpidr_el1 = (uint64_t)(&child->cmn);
|
||||
pforkctx->exe_depth = 0;
|
||||
pforkctx->sp_elx = (uint64_t)pforkctx;
|
||||
pforkctx->sp_el0 = (uint64_t)pforkctx;
|
||||
pforkctx->tpidr_el0 = (uint64_t)(&child->cmn);
|
||||
pforkctx->tpidr_el1 = (uint64_t)(&child->cmn);
|
||||
|
||||
child->cmn.xcp.regs = (uint64_t *)pvforkctx;
|
||||
child->cmn.xcp.regs = (uint64_t *)pforkctx;
|
||||
|
||||
/* And, finally, start the child task. On a failure, nxtask_start_vfork()
|
||||
* will discard the TCB by calling nxtask_abort_vfork().
|
||||
/* And, finally, start the child task. On a failure, nxtask_start_fork()
|
||||
* will discard the TCB by calling nxtask_abort_fork().
|
||||
*/
|
||||
|
||||
return nxtask_start_vfork(child);
|
||||
return nxtask_start_fork(child);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/common/arm64_vfork.h
|
||||
* arch/arm64/src/common/arm64_fork.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -18,8 +18,8 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_COMMON_ARM_VFORK_H
|
||||
#define __ARCH_ARM_SRC_COMMON_ARM_VFORK_H
|
||||
#ifndef __ARCH_ARM_SRC_COMMON_ARM_FORK_H
|
||||
#define __ARCH_ARM_SRC_COMMON_ARM_FORK_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
|
@ -32,48 +32,48 @@
|
|||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define VFORK_REG_X0 (0)
|
||||
#define VFORK_REG_X1 (1)
|
||||
#define VFORK_REG_X2 (2)
|
||||
#define VFORK_REG_X3 (3)
|
||||
#define VFORK_REG_X4 (4)
|
||||
#define VFORK_REG_X5 (5)
|
||||
#define VFORK_REG_X6 (6)
|
||||
#define VFORK_REG_X7 (7)
|
||||
#define VFORK_REG_X8 (8)
|
||||
#define VFORK_REG_X9 (9)
|
||||
#define VFORK_REG_X10 (10)
|
||||
#define VFORK_REG_X11 (11)
|
||||
#define VFORK_REG_X12 (12)
|
||||
#define VFORK_REG_X13 (13)
|
||||
#define VFORK_REG_X14 (14)
|
||||
#define VFORK_REG_X15 (15)
|
||||
#define VFORK_REG_X16 (16)
|
||||
#define VFORK_REG_X17 (17)
|
||||
#define VFORK_REG_X18 (18)
|
||||
#define VFORK_REG_X19 (19)
|
||||
#define VFORK_REG_X20 (20)
|
||||
#define VFORK_REG_X21 (21)
|
||||
#define VFORK_REG_X22 (22)
|
||||
#define VFORK_REG_X23 (23)
|
||||
#define VFORK_REG_X24 (24)
|
||||
#define VFORK_REG_X25 (25)
|
||||
#define VFORK_REG_X26 (26)
|
||||
#define VFORK_REG_X27 (27)
|
||||
#define VFORK_REG_X28 (28)
|
||||
#define VFORK_REG_FP (29) /* Frame pointer*/
|
||||
#define VFORK_REG_LR (30) /* Return address*/
|
||||
#define VFORK_REG_SP (31) /* Stack pointer*/
|
||||
#define FORK_REG_X0 (0)
|
||||
#define FORK_REG_X1 (1)
|
||||
#define FORK_REG_X2 (2)
|
||||
#define FORK_REG_X3 (3)
|
||||
#define FORK_REG_X4 (4)
|
||||
#define FORK_REG_X5 (5)
|
||||
#define FORK_REG_X6 (6)
|
||||
#define FORK_REG_X7 (7)
|
||||
#define FORK_REG_X8 (8)
|
||||
#define FORK_REG_X9 (9)
|
||||
#define FORK_REG_X10 (10)
|
||||
#define FORK_REG_X11 (11)
|
||||
#define FORK_REG_X12 (12)
|
||||
#define FORK_REG_X13 (13)
|
||||
#define FORK_REG_X14 (14)
|
||||
#define FORK_REG_X15 (15)
|
||||
#define FORK_REG_X16 (16)
|
||||
#define FORK_REG_X17 (17)
|
||||
#define FORK_REG_X18 (18)
|
||||
#define FORK_REG_X19 (19)
|
||||
#define FORK_REG_X20 (20)
|
||||
#define FORK_REG_X21 (21)
|
||||
#define FORK_REG_X22 (22)
|
||||
#define FORK_REG_X23 (23)
|
||||
#define FORK_REG_X24 (24)
|
||||
#define FORK_REG_X25 (25)
|
||||
#define FORK_REG_X26 (26)
|
||||
#define FORK_REG_X27 (27)
|
||||
#define FORK_REG_X28 (28)
|
||||
#define FORK_REG_FP (29) /* Frame pointer*/
|
||||
#define FORK_REG_LR (30) /* Return address*/
|
||||
#define FORK_REG_SP (31) /* Stack pointer*/
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
#define VFORK_REGS_SIZE (32 + XCPTCONTEXT_FPU_REGS)
|
||||
#define FORK_REGS_SIZE (32 + XCPTCONTEXT_FPU_REGS)
|
||||
#else
|
||||
#define VFORK_REGS_SIZE (32)
|
||||
#define FORK_REGS_SIZE (32)
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
struct vfork_s
|
||||
struct fork_s
|
||||
{
|
||||
uint64_t regs[29];
|
||||
uint64_t fp;
|
||||
|
@ -86,4 +86,4 @@ struct vfork_s
|
|||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_COMMON_ARM_VFORK_H */
|
||||
#endif /* __ARCH_ARM_SRC_COMMON_ARM_FORK_H */
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/common/arm64_vfork_func.S
|
||||
* arch/arm64/src/common/arm64_fork_func.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -26,36 +26,36 @@
|
|||
|
||||
#include "arch/syscall.h"
|
||||
#include "arm64_macro.inc"
|
||||
#include "arm64_vfork.h"
|
||||
#include "arm64_fork.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
.file "arm64_vfork_func.S"
|
||||
.file "arm64_fork_func.S"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vfork
|
||||
* Name: fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the
|
||||
* behavior is undefined if the process created by vfork() either modifies
|
||||
* The fork() function has the same effect as posix fork(), except that the
|
||||
* behavior is undefined if the process created by fork() either modifies
|
||||
* any data other than a variable of type pid_t used to store the return
|
||||
* value from vfork(), or returns from the function in which vfork() was
|
||||
* value from fork(), or returns from the function in which fork() was
|
||||
* called, or calls any other function before successfully calling _exit()
|
||||
* or one of the exec family of functions.
|
||||
*
|
||||
* This thin layer implements vfork by simply calling up_vfork() with the
|
||||
* vfork() context as an argument. The overall sequence is:
|
||||
* This thin layer implements fork by simply calling up_fork() with the
|
||||
* fork() context as an argument. The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork() and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB.
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork() and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB.
|
||||
* This consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -63,69 +63,70 @@
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and
|
||||
* Upon successful completion, fork() returns 0 to the child process and
|
||||
* returns the process ID of the child process to the parent process.
|
||||
* Otherwise, -1 is returned to the parent, no child process is created,
|
||||
* and errno is set to indicate the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
GTEXT(vfork)
|
||||
SECTION_FUNC(text, vfork)
|
||||
GTEXT(fork)
|
||||
SECTION_FUNC(text, fork)
|
||||
/* Create a stack frame */
|
||||
|
||||
mov x0, sp /* Save the value of the stack on entry */
|
||||
stp x29, x30, [sp]
|
||||
sub sp, sp, #8 * VFORK_REGS_SIZE /* Allocate the structure on the stack */
|
||||
sub sp, sp, #8 * FORK_REGS_SIZE /* Allocate the structure on the stack */
|
||||
|
||||
/* CPU registers, save all register*/
|
||||
|
||||
stp x0, x1, [sp, #8 * VFORK_REG_X0]
|
||||
stp x2, x3, [sp, #8 * VFORK_REG_X2]
|
||||
stp x4, x5, [sp, #8 * VFORK_REG_X4]
|
||||
stp x6, x7, [sp, #8 * VFORK_REG_X6]
|
||||
stp x8, x9, [sp, #8 * VFORK_REG_X8]
|
||||
stp x10, x11, [sp, #8 * VFORK_REG_X10]
|
||||
stp x12, x13, [sp, #8 * VFORK_REG_X12]
|
||||
stp x14, x15, [sp, #8 * VFORK_REG_X14]
|
||||
stp x16, x17, [sp, #8 * VFORK_REG_X16]
|
||||
stp x18, x19, [sp, #8 * VFORK_REG_X18]
|
||||
stp x20, x21, [sp, #8 * VFORK_REG_X20]
|
||||
stp x22, x23, [sp, #8 * VFORK_REG_X22]
|
||||
stp x24, x25, [sp, #8 * VFORK_REG_X24]
|
||||
stp x26, x27, [sp, #8 * VFORK_REG_X26]
|
||||
stp x28, x29, [sp, #8 * VFORK_REG_X28]
|
||||
stp x0, x1, [sp, #8 * FORK_REG_X0]
|
||||
stp x2, x3, [sp, #8 * FORK_REG_X2]
|
||||
stp x4, x5, [sp, #8 * FORK_REG_X4]
|
||||
stp x6, x7, [sp, #8 * FORK_REG_X6]
|
||||
stp x8, x9, [sp, #8 * FORK_REG_X8]
|
||||
stp x10, x11, [sp, #8 * FORK_REG_X10]
|
||||
stp x12, x13, [sp, #8 * FORK_REG_X12]
|
||||
stp x14, x15, [sp, #8 * FORK_REG_X14]
|
||||
stp x16, x17, [sp, #8 * FORK_REG_X16]
|
||||
stp x18, x19, [sp, #8 * FORK_REG_X18]
|
||||
stp x20, x21, [sp, #8 * FORK_REG_X20]
|
||||
stp x22, x23, [sp, #8 * FORK_REG_X22]
|
||||
stp x24, x25, [sp, #8 * FORK_REG_X24]
|
||||
stp x26, x27, [sp, #8 * FORK_REG_X26]
|
||||
stp x28, x29, [sp, #8 * FORK_REG_X28]
|
||||
|
||||
/* Save the LR, stack pointer */
|
||||
|
||||
stp x30, x0, [sp, #8 * VFORK_REG_LR]
|
||||
stp x30, x0, [sp, #8 * FORK_REG_LR]
|
||||
|
||||
/* Floating point registers */
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
mov x0, sp
|
||||
stp x0, x30, [sp, #-16]!
|
||||
bl arm64_vfork_fpureg_save
|
||||
bl arm64_fork_fpureg_save
|
||||
ldp x0, x30, [sp], #16
|
||||
#endif
|
||||
|
||||
/* Then, call up_vfork(), passing it a pointer to the stack structure */
|
||||
/* Then, call up_fork(), passing it a pointer to the stack structure */
|
||||
|
||||
mov x0, sp
|
||||
bl up_vfork
|
||||
mov x1, #0
|
||||
bl up_fork
|
||||
|
||||
/* Release the stack data and return the value returned by up_vfork */
|
||||
/* Release the stack data and return the value returned by up_fork */
|
||||
|
||||
add sp, sp, #8 * VFORK_REGS_SIZE
|
||||
add sp, sp, #8 * FORK_REGS_SIZE
|
||||
ldp x29, x30, [sp]
|
||||
|
||||
ret
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
#include "sched/sched.h"
|
||||
#include "arm64_arch.h"
|
||||
#include "arm64_vfork.h"
|
||||
#include "arm64_fork.h"
|
||||
#include "arm64_internal.h"
|
||||
#include "arm64_fatal.h"
|
||||
#include "arm64_fpu.h"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/ceva/src/common/ceva_vfork.c
|
||||
* arch/ceva/src/common/ceva_fork.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -38,49 +38,49 @@
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_vfork
|
||||
* Name: up_fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the
|
||||
* behavior is undefined if the process created by vfork() either modifies
|
||||
* The fork() function has the same effect as posix fork(), except that the
|
||||
* behavior is undefined if the process created by fork() either modifies
|
||||
* any data other than a variable of type pid_t used to store the return
|
||||
* value from vfork(), or returns from the function in which vfork() was
|
||||
* value from fork(), or returns from the function in which fork() was
|
||||
* called, or calls any other function before successfully calling _exit()
|
||||
* or one of the exec family of functions.
|
||||
*
|
||||
* The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork()and calls nxtask_vforksetup().
|
||||
* 3) nxtask_vforksetup() allocates and configures the child task's TCB.
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork()and calls nxtask_forksetup().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB.
|
||||
* This consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
* - Configuration of environment variables
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state()
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Allocate and initialize the stack
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_vforkstart()
|
||||
* 6) nxtask_vforkstart() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* nxtask_vforkabort() may be called if an error occurs between steps 3 & 6.
|
||||
* nxtask_abort_fork() may be called if an error occurs between steps 3 & 6.
|
||||
*
|
||||
* Input Parameters:
|
||||
* regs - Caller context information saved by vfork()
|
||||
* regs - Caller context information saved by fork()
|
||||
*
|
||||
* Return:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and
|
||||
* Upon successful completion, fork() returns 0 to the child process and
|
||||
* returns the process ID of the child process to the parent process.
|
||||
* Otherwise, -1 is returned to the parent, no child process is created,
|
||||
* and errno is set to indicate the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
pid_t up_vfork(const uint32_t *regs)
|
||||
pid_t up_fork(const uint32_t *regs)
|
||||
{
|
||||
#ifdef CONFIG_SCHED_WAITPID
|
||||
struct tcb_s *parent = this_task();
|
||||
|
@ -96,10 +96,10 @@ pid_t up_vfork(const uint32_t *regs)
|
|||
|
||||
/* Allocate and initialize a TCB for the child task. */
|
||||
|
||||
child = nxtask_vforksetup(parent->start, &argsize);
|
||||
child = nxtask_setup_fork(parent->start, &argsize);
|
||||
if (!child)
|
||||
{
|
||||
serr("ERROR: nxtask_vforksetup failed\n");
|
||||
serr("ERROR: nxtask_setup_fork failed\n");
|
||||
return (pid_t)ERROR;
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ pid_t up_vfork(const uint32_t *regs)
|
|||
if (ret != OK)
|
||||
{
|
||||
serr("ERROR: up_create_stack failed: %d\n", ret);
|
||||
nxtask_vforkabort(child, -ret);
|
||||
nxtask_abort_fork(child, -ret);
|
||||
return (pid_t)ERROR;
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ pid_t up_vfork(const uint32_t *regs)
|
|||
/* Make some feeble effort to preserve the stack contents. This is
|
||||
* feeble because the stack surely contains invalid pointers and other
|
||||
* content that will not work in the child context. However, if the
|
||||
* user follows all of the caveats of vfork() usage, even this feeble
|
||||
* user follows all of the caveats of fork() usage, even this feeble
|
||||
* effort is overkill.
|
||||
*/
|
||||
|
||||
|
@ -197,11 +197,11 @@ pid_t up_vfork(const uint32_t *regs)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* And, finally, start the child task. On a failure, nxtask_vforkstart()
|
||||
* will discard the TCB by calling nxtask_vforkabort().
|
||||
/* And, finally, start the child task. On a failure, nxtask_start_fork()
|
||||
* will discard the TCB by calling nxtask_abort_fork().
|
||||
*/
|
||||
|
||||
return nxtask_vforkstart(child);
|
||||
return nxtask_start_fork(child);
|
||||
#else /* CONFIG_SCHED_WAITPID */
|
||||
return (pid_t)ERROR;
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/ceva/src/xc5/vfork.S
|
||||
* arch/ceva/src/xc5/fork.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -31,48 +31,48 @@
|
|||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
.file "vfork.S"
|
||||
.extern _up_vfork
|
||||
.file "fork.S"
|
||||
.extern _up_fork
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vfork
|
||||
* Name: fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the behavior is
|
||||
* undefined if the process created by vfork() either modifies any data other than
|
||||
* a variable of type pid_t used to store the return value from vfork(), or returns
|
||||
* from the function in which vfork() was called, or calls any other function before
|
||||
* The fork() function has the same effect as posix fork(), except that the behavior is
|
||||
* undefined if the process created by fork() either modifies any data other than
|
||||
* a variable of type pid_t used to store the return value from fork(), or returns
|
||||
* from the function in which fork() was called, or calls any other function before
|
||||
* successfully calling _exit() or one of the exec family of functions.
|
||||
*
|
||||
* This thin layer implements vfork by simply calling up_vfork() with the vfork()
|
||||
* This thin layer implements fork by simply calling up_fork() with the fork()
|
||||
* context as an argument. The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork()and calls nxtask_vforksetup().
|
||||
* 3) task_vforksetup() allocates and configures the child task's TCB. This
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork()and calls nxtask_forksetup().
|
||||
* 3) task_forksetup() allocates and configures the child task's TCB. This
|
||||
* consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
* - Configuration of environment variables
|
||||
* - Setup the intput parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state()
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Allocate and initialize the stack
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_vforkstart()
|
||||
* 6) nxtask_vforkstart() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_forkstart()
|
||||
* 6) nxtask_forkstart() then executes the child thread.
|
||||
*
|
||||
* Input Paremeters:
|
||||
* None
|
||||
*
|
||||
* Return:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and returns
|
||||
* Upon successful completion, fork() returns 0 to the child process and returns
|
||||
* the process ID of the child process to the parent process. Otherwise, -1 is
|
||||
* returned to the parent, no child process is created, and errno is set to
|
||||
* indicate the error.
|
||||
|
@ -80,10 +80,10 @@
|
|||
****************************************************************************/
|
||||
|
||||
.text
|
||||
.public _vfork
|
||||
.func_start 3 _vfork
|
||||
.public _fork
|
||||
.func_start 3 _fork
|
||||
|
||||
_vfork:
|
||||
_fork:
|
||||
/* Create a stack frame */
|
||||
|
||||
subs sp, #XCPTCONTEXT_SIZE, sp
|
||||
|
@ -94,19 +94,19 @@ _vfork:
|
|||
mov sp, a1
|
||||
trap
|
||||
|
||||
/* Then, call up_vfork(), passing it a pointer to the stack structure */
|
||||
/* Then, call up_fork(), passing it a pointer to the stack structure */
|
||||
|
||||
mov sp, a0
|
||||
nop
|
||||
push {dw} retreg
|
||||
callr {t} _up_vfork
|
||||
callr {t} _up_fork
|
||||
pop {dw} retreg
|
||||
nop
|
||||
|
||||
/* Release the stack data and return the value returned by up_vfork */
|
||||
/* Release the stack data and return the value returned by up_fork */
|
||||
|
||||
adds sp, #XCPTCONTEXT_SIZE, sp
|
||||
|
||||
ret
|
||||
|
||||
.func_end 3 _vfork
|
||||
.func_end 3 _fork
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/ceva/src/xm6/vfork.S
|
||||
* arch/ceva/src/xm6/fork.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -41,48 +41,48 @@
|
|||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
.file "vfork.S"
|
||||
.extern _up_vfork
|
||||
.file "fork.S"
|
||||
.extern _up_fork
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vfork
|
||||
* Name: fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the behavior is
|
||||
* undefined if the process created by vfork() either modifies any data other than
|
||||
* a variable of type pid_t used to store the return value from vfork(), or returns
|
||||
* from the function in which vfork() was called, or calls any other function before
|
||||
* The fork() function has the same effect as posix fork(), except that the behavior is
|
||||
* undefined if the process created by fork() either modifies any data other than
|
||||
* a variable of type pid_t used to store the return value from fork(), or returns
|
||||
* from the function in which fork() was called, or calls any other function before
|
||||
* successfully calling _exit() or one of the exec family of functions.
|
||||
*
|
||||
* This thin layer implements vfork by simply calling up_vfork() with the vfork()
|
||||
* This thin layer implements fork by simply calling up_fork() with the fork()
|
||||
* context as an argument. The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork()and calls nxtask_vforksetup().
|
||||
* 3) task_vforksetup() allocates and configures the child task's TCB. This
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork()and calls nxtask_forksetup().
|
||||
* 3) task_forksetup() allocates and configures the child task's TCB. This
|
||||
* consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
* - Configuration of environment variables
|
||||
* - Setup the intput parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state()
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Allocate and initialize the stack
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_vforkstart()
|
||||
* 6) nxtask_vforkstart() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_forkstart()
|
||||
* 6) nxtask_forkstart() then executes the child thread.
|
||||
*
|
||||
* Input Paremeters:
|
||||
* None
|
||||
*
|
||||
* Return:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and returns
|
||||
* Upon successful completion, fork() returns 0 to the child process and returns
|
||||
* the process ID of the child process to the parent process. Otherwise, -1 is
|
||||
* returned to the parent, no child process is created, and errno is set to
|
||||
* indicate the error.
|
||||
|
@ -90,10 +90,10 @@
|
|||
****************************************************************************/
|
||||
|
||||
.text
|
||||
.public _vfork
|
||||
.func_start 3 _vfork
|
||||
.public _fork
|
||||
.func_start 3 _fork
|
||||
|
||||
_vfork:
|
||||
_fork:
|
||||
/* Create a stack frame */
|
||||
|
||||
modr (sp.ui).ui +#-XCPTCONTEXT_SIZE /* Allocate the structure on the stack */
|
||||
|
@ -104,18 +104,18 @@ _vfork:
|
|||
mov sp.ui, r1.ui
|
||||
trap {t0}
|
||||
|
||||
/* Then, call up_vfork(), passing it a pointer to the stack structure */
|
||||
/* Then, call up_fork(), passing it a pointer to the stack structure */
|
||||
|
||||
mov sp.ui, r0.ui
|
||||
nop
|
||||
push retreg.ui
|
||||
callr #_up_vfork, ?prx.b
|
||||
callr #_up_fork, ?prx.b
|
||||
pop retreg.ui
|
||||
nop
|
||||
|
||||
/* Release the stack data and return the value returned by up_vfork */
|
||||
/* Release the stack data and return the value returned by up_fork */
|
||||
|
||||
modr (sp.ui).ui +#XCPTCONTEXT_SIZE
|
||||
ret ?prx.b
|
||||
|
||||
.func_end 3 _vfork
|
||||
.func_end 3 _fork
|
|
@ -41,7 +41,7 @@ endchoice
|
|||
config ARCH_MIPS32
|
||||
bool
|
||||
default n
|
||||
select ARCH_HAVE_VFORK
|
||||
select ARCH_HAVE_FORK
|
||||
|
||||
config ARCH_MIPS_M4K
|
||||
bool
|
||||
|
|
|
@ -87,10 +87,10 @@ config MIPS32_TOOLCHAIN_MICROCHIP_XC32_LICENSED
|
|||
config MIPS32_FRAMEPOINTER
|
||||
bool "ABI Uses Frame Pointer"
|
||||
default n
|
||||
depends on ARCH_HAVE_VFORK
|
||||
depends on ARCH_HAVE_FORK
|
||||
---help---
|
||||
Register r30 may be a frame pointer in some ABIs. Or may just be
|
||||
saved register s8. It makes a difference for vfork handling.
|
||||
saved register s8. It makes a difference for fork handling.
|
||||
|
||||
config MIPS32_HAVE_ICACHE
|
||||
bool
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/************************************************************************************
|
||||
* arch/mips/src/mips32/vfork.S
|
||||
* arch/mips/src/mips32/fork.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -24,7 +24,7 @@
|
|||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "mips_vfork.h"
|
||||
#include "mips_fork.h"
|
||||
|
||||
/************************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -34,30 +34,30 @@
|
|||
* Public Symbols
|
||||
************************************************************************************/
|
||||
|
||||
.file "vfork.S"
|
||||
.globl up_vfork
|
||||
.file "fork.S"
|
||||
.globl up_fork
|
||||
|
||||
/************************************************************************************
|
||||
* Public Functions
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
* Name: vfork
|
||||
* Name: fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the behavior is
|
||||
* undefined if the process created by vfork() either modifies any data other than
|
||||
* a variable of type pid_t used to store the return value from vfork(), or returns
|
||||
* from the function in which vfork() was called, or calls any other function before
|
||||
* The fork() function has the same effect as posix fork(), except that the behavior is
|
||||
* undefined if the process created by fork() either modifies any data other than
|
||||
* a variable of type pid_t used to store the return value from fork(), or returns
|
||||
* from the function in which fork() was called, or calls any other function before
|
||||
* successfully calling _exit() or one of the exec family of functions.
|
||||
*
|
||||
* This thin layer implements vfork by simply calling up_vfork() with the vfork()
|
||||
* This thin layer implements fork by simply calling up_fork() with the fork()
|
||||
* context as an argument. The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork() and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB. This
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork() and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB. This
|
||||
* consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -65,17 +65,17 @@
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and returns
|
||||
* Upon successful completion, fork() returns 0 to the child process and returns
|
||||
* the process ID of the child process to the parent process. Otherwise, -1 is
|
||||
* returned to the parent, no child process is created, and errno is set to
|
||||
* indicate the error.
|
||||
|
@ -84,59 +84,59 @@
|
|||
|
||||
.text
|
||||
.align 2
|
||||
.globl vfork
|
||||
.type vfork, function
|
||||
.globl fork
|
||||
.type fork, function
|
||||
.set nomips16
|
||||
#ifdef CONFIG_MIPS_MICROMIPS
|
||||
.set micromips
|
||||
#endif
|
||||
.ent vfork
|
||||
.ent fork
|
||||
|
||||
vfork:
|
||||
fork:
|
||||
/* Create a stack frame */
|
||||
|
||||
move $t0, $sp /* Save the value of the stack on entry */
|
||||
addiu $sp, $sp, -VFORK_SIZEOF /* Allocate the structure on the stack */
|
||||
addiu $sp, $sp, -FORK_SIZEOF /* Allocate the structure on the stack */
|
||||
|
||||
/* CPU registers */
|
||||
/* Save the saved registers */
|
||||
|
||||
sw $s0, VFORK_S0_OFFSET($sp)
|
||||
sw $s1, VFORK_S1_OFFSET($sp)
|
||||
sw $s2, VFORK_S2_OFFSET($sp)
|
||||
sw $s3, VFORK_S3_OFFSET($sp)
|
||||
sw $s4, VFORK_S4_OFFSET($sp)
|
||||
sw $s5, VFORK_S5_OFFSET($sp)
|
||||
sw $s6, VFORK_S6_OFFSET($sp)
|
||||
sw $s7, VFORK_S7_OFFSET($sp)
|
||||
sw $s0, FORK_S0_OFFSET($sp)
|
||||
sw $s1, FORK_S1_OFFSET($sp)
|
||||
sw $s2, FORK_S2_OFFSET($sp)
|
||||
sw $s3, FORK_S3_OFFSET($sp)
|
||||
sw $s4, FORK_S4_OFFSET($sp)
|
||||
sw $s5, FORK_S5_OFFSET($sp)
|
||||
sw $s6, FORK_S6_OFFSET($sp)
|
||||
sw $s7, FORK_S7_OFFSET($sp)
|
||||
|
||||
#ifdef CONFIG_MIPS32_FRAMEPOINTER
|
||||
sw $fp, VFORK_FP_OFFSET($sp)
|
||||
sw $fp, FORK_FP_OFFSET($sp)
|
||||
#else
|
||||
sw $s8, VFORK_S8_OFFSET($sp)
|
||||
sw $s8, FORK_S8_OFFSET($sp)
|
||||
#endif
|
||||
|
||||
/* Save the global pointer, stack pointer, and return address */
|
||||
|
||||
sw $t0, VFORK_SP_OFFSET($sp)
|
||||
sw $ra, VFORK_RA_OFFSET($sp)
|
||||
sw $t0, FORK_SP_OFFSET($sp)
|
||||
sw $ra, FORK_RA_OFFSET($sp)
|
||||
#ifdef MIPS32_SAVE_GP
|
||||
sw $gp, VFORK_GP_OFFSET($sp)
|
||||
sw $gp, FORK_GP_OFFSET($sp)
|
||||
#endif
|
||||
|
||||
/* Floating point registers (not yet) */
|
||||
|
||||
/* Then, call up_vfork(), passing it a pointer to the stack structure */
|
||||
/* Then, call up_fork(), passing it a pointer to the stack structure */
|
||||
|
||||
move $a0, $sp
|
||||
jal up_vfork
|
||||
jal up_fork
|
||||
nop
|
||||
|
||||
/* Release the stack data and return the value returned by up_vfork */
|
||||
/* Release the stack data and return the value returned by up_fork */
|
||||
|
||||
lw $ra, VFORK_RA_OFFSET($sp)
|
||||
addiu $sp, $sp, VFORK_SIZEOF
|
||||
lw $ra, FORK_RA_OFFSET($sp)
|
||||
addiu $sp, $sp, FORK_SIZEOF
|
||||
j $ra
|
||||
|
||||
.end vfork
|
||||
.size vfork, .-vfork
|
||||
.end fork
|
||||
.size fork, .-fork
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/mips/src/mips32/mips_vfork.c
|
||||
* arch/mips/src/mips32/mips_fork.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -35,7 +35,7 @@
|
|||
#include <nuttx/arch.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
#include "mips_vfork.h"
|
||||
#include "mips_fork.h"
|
||||
#include "sched/sched.h"
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -43,22 +43,22 @@
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_vfork
|
||||
* Name: up_fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the
|
||||
* behavior is undefined if the process created by vfork() either modifies
|
||||
* The fork() function has the same effect as posix fork(), except that the
|
||||
* behavior is undefined if the process created by fork() either modifies
|
||||
* any data other than a variable of type pid_t used to store the return
|
||||
* value from vfork(), or returns from the function in which vfork() was
|
||||
* value from fork(), or returns from the function in which fork() was
|
||||
* called, or calls any other function before successfully calling _exit()
|
||||
* or one of the exec family of functions.
|
||||
*
|
||||
* The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork() and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB.
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork() and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB.
|
||||
* this consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -66,27 +66,27 @@
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* nxtask_abort_vfork() may be called if an error occurs between steps 3
|
||||
* nxtask_abort_fork() may be called if an error occurs between steps 3
|
||||
* and 6
|
||||
*
|
||||
* Input Parameters:
|
||||
* context - Caller context information saved by vfork()
|
||||
* context - Caller context information saved by fork()
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and
|
||||
* Upon successful completion, fork() returns 0 to the child process and
|
||||
* returns the process ID of the child process to the parent process.
|
||||
* Otherwise, -1 is returned to the parent, no child process is created,
|
||||
* and errno is set to indicate the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
pid_t up_vfork(const struct vfork_s *context)
|
||||
pid_t up_fork(const struct fork_s *context)
|
||||
{
|
||||
struct tcb_s *parent = this_task();
|
||||
struct task_tcb_s *child;
|
||||
|
@ -127,10 +127,10 @@ pid_t up_vfork(const struct vfork_s *context)
|
|||
|
||||
/* Allocate and initialize a TCB for the child task. */
|
||||
|
||||
child = nxtask_setup_vfork((start_t)context->ra);
|
||||
child = nxtask_setup_fork((start_t)context->ra);
|
||||
if (!child)
|
||||
{
|
||||
sinfo("nxtask_setup_vfork failed\n");
|
||||
sinfo("nxtask_setup_fork failed\n");
|
||||
return (pid_t)ERROR;
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ pid_t up_vfork(const struct vfork_s *context)
|
|||
/* Make some feeble effort to perserve the stack contents. This is
|
||||
* feeble because the stack surely contains invalid pointers and other
|
||||
* content that will not work in the child context. However, if the
|
||||
* user follows all of the caveats of vfork() usage, even this feeble
|
||||
* user follows all of the caveats of fork() usage, even this feeble
|
||||
* effort is overkill.
|
||||
*/
|
||||
|
||||
|
@ -210,9 +210,9 @@ pid_t up_vfork(const struct vfork_s *context)
|
|||
child->cmn.xcp.regs[REG_GP] = context->gp; /* Global pointer */
|
||||
#endif
|
||||
|
||||
/* And, finally, start the child task. On a failure, nxtask_start_vfork()
|
||||
* will discard the TCB by calling nxtask_abort_vfork().
|
||||
/* And, finally, start the child task. On a failure, nxtask_start_fork()
|
||||
* will discard the TCB by calling nxtask_abort_fork().
|
||||
*/
|
||||
|
||||
return nxtask_start_vfork(child);
|
||||
return nxtask_start_fork(child);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/mips/src/mips32/mips_vfork.h
|
||||
* arch/mips/src/mips32/mips_fork.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -18,8 +18,8 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_MIPS_SRC_MIPS32_MIPS_VFORK_H
|
||||
#define __ARCH_MIPS_SRC_MIPS32_MIPS_VFORK_H
|
||||
#ifndef __ARCH_MIPS_SRC_MIPS32_MIPS_FORK_H
|
||||
#define __ARCH_MIPS_SRC_MIPS32_MIPS_FORK_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
|
@ -33,10 +33,10 @@
|
|||
****************************************************************************/
|
||||
|
||||
/* Register r30 may be a frame pointer in some ABIs. Or may just be saved
|
||||
* register s8. It makes a difference for vfork handling.
|
||||
* register s8. It makes a difference for fork handling.
|
||||
*/
|
||||
|
||||
#undef VFORK_HAVE_FP
|
||||
#undef FORK_HAVE_FP
|
||||
|
||||
/* r0 zero Always has the value 0.
|
||||
* r1 at Temporary generally used by assembler.
|
||||
|
@ -59,28 +59,28 @@
|
|||
* r31 ra Return address.
|
||||
*/
|
||||
|
||||
#define VFORK_S0_OFFSET (0*4) /* Saved register s0 */
|
||||
#define VFORK_S1_OFFSET (1*4) /* Saved register s1 */
|
||||
#define VFORK_S2_OFFSET (2*4) /* Saved register s2 */
|
||||
#define VFORK_S3_OFFSET (3*4) /* Saved register s3 */
|
||||
#define VFORK_S4_OFFSET (4*4) /* Saved register s4 */
|
||||
#define VFORK_S5_OFFSET (5*4) /* Saved register s5 */
|
||||
#define VFORK_S6_OFFSET (6*4) /* Saved register s6 */
|
||||
#define VFORK_S7_OFFSET (7*4) /* Saved register s7 */
|
||||
#define FORK_S0_OFFSET (0*4) /* Saved register s0 */
|
||||
#define FORK_S1_OFFSET (1*4) /* Saved register s1 */
|
||||
#define FORK_S2_OFFSET (2*4) /* Saved register s2 */
|
||||
#define FORK_S3_OFFSET (3*4) /* Saved register s3 */
|
||||
#define FORK_S4_OFFSET (4*4) /* Saved register s4 */
|
||||
#define FORK_S5_OFFSET (5*4) /* Saved register s5 */
|
||||
#define FORK_S6_OFFSET (6*4) /* Saved register s6 */
|
||||
#define FORK_S7_OFFSET (7*4) /* Saved register s7 */
|
||||
|
||||
#ifdef CONFIG_MIPS32_FRAMEPOINTER
|
||||
# define VFORK_FP_OFFSET (8*4) /* Frame pointer */
|
||||
# define FORK_FP_OFFSET (8*4) /* Frame pointer */
|
||||
#else
|
||||
# define VFORK_S8_OFFSET (8*4) /* Saved register s8 */
|
||||
# define FORK_S8_OFFSET (8*4) /* Saved register s8 */
|
||||
#endif
|
||||
|
||||
#define VFORK_SP_OFFSET (9*4) /* Stack pointer*/
|
||||
#define VFORK_RA_OFFSET (10*4) /* Return address*/
|
||||
#define FORK_SP_OFFSET (9*4) /* Stack pointer*/
|
||||
#define FORK_RA_OFFSET (10*4) /* Return address*/
|
||||
#ifdef MIPS32_SAVE_GP
|
||||
# define VFORK_GP_OFFSET (11*4) /* Global pointer */
|
||||
# define VFORK_SIZEOF (12*4)
|
||||
# define FORK_GP_OFFSET (11*4) /* Global pointer */
|
||||
# define FORK_SIZEOF (12*4)
|
||||
#else
|
||||
# define VFORK_SIZEOF (11*4)
|
||||
# define FORK_SIZEOF (11*4)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -88,7 +88,7 @@
|
|||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
struct vfork_s
|
||||
struct fork_s
|
||||
{
|
||||
/* CPU registers */
|
||||
|
||||
|
@ -115,4 +115,4 @@ struct vfork_s
|
|||
};
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_MIPS_SRC_MIPS32_MIPS_VFORK_H */
|
||||
#endif /* __ARCH_MIPS_SRC_MIPS32_MIPS_FORK_H */
|
|
@ -24,7 +24,7 @@ HEAD_ASRC = pic32mx_head.S
|
|||
|
||||
# Common MIPS files
|
||||
|
||||
CMN_ASRCS = mips_syscall0.S vfork.S
|
||||
CMN_ASRCS = mips_syscall0.S fork.S
|
||||
CMN_CSRCS = mips_allocateheap.c mips_copystate.c mips_createstack.c
|
||||
CMN_CSRCS += mips_doirq.c mips_exit.c mips_getintstack.c mips_initialize.c
|
||||
CMN_CSRCS += mips_initialstate.c mips_irq.c mips_lowputs.c mips_mdelay.c
|
||||
|
@ -32,7 +32,7 @@ CMN_CSRCS += mips_modifyreg8.c mips_modifyreg16.c mips_modifyreg32.c
|
|||
CMN_CSRCS += mips_nputs.c mips_releasestack.c mips_registerdump.c
|
||||
CMN_CSRCS += mips_schedulesigaction.c mips_sigdeliver.c mips_swint0.c
|
||||
CMN_CSRCS += mips_stackframe.c mips_switchcontext.c mips_saveusercontext.c
|
||||
CMN_CSRCS += mips_udelay.c mips_usestack.c mips_vfork.c
|
||||
CMN_CSRCS += mips_udelay.c mips_usestack.c mips_fork.c
|
||||
|
||||
# Configuration dependent common files
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ HEAD_ASRC = pic32mz_head.S
|
|||
|
||||
# Common MIPS files
|
||||
|
||||
CMN_ASRCS = mips_syscall0.S vfork.S mips_cache.S
|
||||
CMN_ASRCS = mips_syscall0.S fork.S mips_cache.S
|
||||
CMN_CSRCS = mips_allocateheap.c mips_copystate.c mips_createstack.c
|
||||
CMN_CSRCS += mips_doirq.c mips_exit.c mips_getintstack.c mips_initialize.c
|
||||
CMN_CSRCS += mips_initialstate.c mips_irq.c mips_lowputs.c mips_mdelay.c
|
||||
|
@ -32,7 +32,7 @@ CMN_CSRCS += mips_modifyreg8.c mips_modifyreg16.c mips_modifyreg32.c
|
|||
CMN_CSRCS += mips_nputs.c mips_releasestack.c mips_registerdump.c
|
||||
CMN_CSRCS += mips_schedulesigaction.c mips_sigdeliver.c mips_swint0.c
|
||||
CMN_CSRCS += mips_stackframe.c mips_switchcontext.c mips_saveusercontext.c
|
||||
CMN_CSRCS += mips_udelay.c mips_usestack.c mips_vfork.c
|
||||
CMN_CSRCS += mips_udelay.c mips_usestack.c mips_fork.c
|
||||
|
||||
# Configuration dependent common files
|
||||
|
||||
|
|
|
@ -65,9 +65,9 @@ ifeq ($(CONFIG_STACK_COLORATION),y)
|
|||
CMN_CSRCS += riscv_checkstack.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
|
||||
CMN_ASRCS += vfork.S
|
||||
CMN_CSRCS += riscv_vfork.c
|
||||
ifeq ($(CONFIG_ARCH_HAVE_FORK),y)
|
||||
CMN_ASRCS += fork.S
|
||||
CMN_CSRCS += riscv_fork.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SCHED_THREAD_LOCAL),y)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/risc-v/src/common/vfork.S
|
||||
* arch/risc-v/src/common/fork.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "riscv_vfork.h"
|
||||
#include "riscv_fork.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -35,32 +35,32 @@
|
|||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
.file "vfork.S"
|
||||
.globl up_vfork
|
||||
.globl vfork
|
||||
.file "fork.S"
|
||||
.globl up_fork
|
||||
.globl fork
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vfork
|
||||
* Name: fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the
|
||||
* behavior is undefined if the process created by vfork() either modifies
|
||||
* The fork() function has the same effect as posix fork(), except that the
|
||||
* behavior is undefined if the process created by fork() either modifies
|
||||
* any data other than a variable of type pid_t used to store the return
|
||||
* value from vfork(), or returns from the function in which vfork() was
|
||||
* value from fork(), or returns from the function in which fork() was
|
||||
* called, or calls any other function before successfully calling _exit()
|
||||
* or one of the exec family of functions.
|
||||
*
|
||||
* This thin layer implements vfork by simply calling up_vfork() with the
|
||||
* vfork() context as an argument. The overall sequence is:
|
||||
* This thin layer implements fork by simply calling up_fork() with the
|
||||
* fork() context as an argument. The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork() and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB.
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork() and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB.
|
||||
* This consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -68,84 +68,84 @@
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and
|
||||
* Upon successful completion, fork() returns 0 to the child process and
|
||||
* returns the process ID of the child process to the parent process.
|
||||
* Otherwise, -1 is returned to the parent, no child process is created,
|
||||
* and errno is set to indicate the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.type vfork, function
|
||||
.type fork, function
|
||||
|
||||
vfork:
|
||||
fork:
|
||||
/* Create a stack frame */
|
||||
|
||||
addi sp, sp, -VFORK_SIZEOF
|
||||
addi sp, sp, -FORK_SIZEOF
|
||||
|
||||
/* CPU registers */
|
||||
/* Save the volatile registers */
|
||||
|
||||
REGSTORE s1, VFORK_S1_OFFSET(sp)
|
||||
REGSTORE s2, VFORK_S2_OFFSET(sp)
|
||||
REGSTORE s3, VFORK_S3_OFFSET(sp)
|
||||
REGSTORE s4, VFORK_S4_OFFSET(sp)
|
||||
REGSTORE s5, VFORK_S5_OFFSET(sp)
|
||||
REGSTORE s6, VFORK_S6_OFFSET(sp)
|
||||
REGSTORE s7, VFORK_S7_OFFSET(sp)
|
||||
REGSTORE s8, VFORK_S8_OFFSET(sp)
|
||||
REGSTORE s9, VFORK_S9_OFFSET(sp)
|
||||
REGSTORE s10, VFORK_S10_OFFSET(sp)
|
||||
REGSTORE s11, VFORK_S11_OFFSET(sp)
|
||||
REGSTORE s1, FORK_S1_OFFSET(sp)
|
||||
REGSTORE s2, FORK_S2_OFFSET(sp)
|
||||
REGSTORE s3, FORK_S3_OFFSET(sp)
|
||||
REGSTORE s4, FORK_S4_OFFSET(sp)
|
||||
REGSTORE s5, FORK_S5_OFFSET(sp)
|
||||
REGSTORE s6, FORK_S6_OFFSET(sp)
|
||||
REGSTORE s7, FORK_S7_OFFSET(sp)
|
||||
REGSTORE s8, FORK_S8_OFFSET(sp)
|
||||
REGSTORE s9, FORK_S9_OFFSET(sp)
|
||||
REGSTORE s10, FORK_S10_OFFSET(sp)
|
||||
REGSTORE s11, FORK_S11_OFFSET(sp)
|
||||
|
||||
/* Save the frame pointer, stack pointer, and return address */
|
||||
|
||||
#ifdef CONFIG_RISCV_FRAMEPOINTER
|
||||
REGSTORE fp, VFORK_FP_OFFSET(sp)
|
||||
REGSTORE fp, FORK_FP_OFFSET(sp)
|
||||
#else
|
||||
REGSTORE s0, VFORK_S0_OFFSET(sp)
|
||||
REGSTORE s0, FORK_S0_OFFSET(sp)
|
||||
#endif
|
||||
|
||||
addi s0, sp, VFORK_SIZEOF
|
||||
REGSTORE s0, VFORK_SP_OFFSET(sp) /* original SP */
|
||||
REGSTORE x1, VFORK_RA_OFFSET(sp) /* return address */
|
||||
addi s0, sp, FORK_SIZEOF
|
||||
REGSTORE s0, FORK_SP_OFFSET(sp) /* original SP */
|
||||
REGSTORE x1, FORK_RA_OFFSET(sp) /* return address */
|
||||
|
||||
/* Floating point registers */
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
FSTORE fs0, VFORK_FS0_OFFSET(sp)
|
||||
FSTORE fs1, VFORK_FS1_OFFSET(sp)
|
||||
FSTORE fs2, VFORK_FS2_OFFSET(sp)
|
||||
FSTORE fs3, VFORK_FS3_OFFSET(sp)
|
||||
FSTORE fs4, VFORK_FS4_OFFSET(sp)
|
||||
FSTORE fs5, VFORK_FS5_OFFSET(sp)
|
||||
FSTORE fs6, VFORK_FS6_OFFSET(sp)
|
||||
FSTORE fs7, VFORK_FS7_OFFSET(sp)
|
||||
FSTORE fs8, VFORK_FS8_OFFSET(sp)
|
||||
FSTORE fs9, VFORK_FS9_OFFSET(sp)
|
||||
FSTORE fs10, VFORK_FS10_OFFSET(sp)
|
||||
FSTORE fs11, VFORK_FS11_OFFSET(sp)
|
||||
FSTORE fs0, FORK_FS0_OFFSET(sp)
|
||||
FSTORE fs1, FORK_FS1_OFFSET(sp)
|
||||
FSTORE fs2, FORK_FS2_OFFSET(sp)
|
||||
FSTORE fs3, FORK_FS3_OFFSET(sp)
|
||||
FSTORE fs4, FORK_FS4_OFFSET(sp)
|
||||
FSTORE fs5, FORK_FS5_OFFSET(sp)
|
||||
FSTORE fs6, FORK_FS6_OFFSET(sp)
|
||||
FSTORE fs7, FORK_FS7_OFFSET(sp)
|
||||
FSTORE fs8, FORK_FS8_OFFSET(sp)
|
||||
FSTORE fs9, FORK_FS9_OFFSET(sp)
|
||||
FSTORE fs10, FORK_FS10_OFFSET(sp)
|
||||
FSTORE fs11, FORK_FS11_OFFSET(sp)
|
||||
#endif
|
||||
|
||||
/* Then, call up_vfork(), passing it a pointer to the stack frame */
|
||||
/* Then, call up_fork(), passing it a pointer to the stack frame */
|
||||
|
||||
mv a0, sp
|
||||
call up_vfork
|
||||
call up_fork
|
||||
|
||||
/* Release the stack frame and return the value returned by up_vfork */
|
||||
/* Release the stack frame and return the value returned by up_fork */
|
||||
|
||||
REGLOAD x1, VFORK_RA_OFFSET(sp)
|
||||
addi sp, sp, VFORK_SIZEOF
|
||||
REGLOAD x1, FORK_RA_OFFSET(sp)
|
||||
addi sp, sp, FORK_SIZEOF
|
||||
ret
|
||||
|
||||
.size vfork, .-vfork
|
||||
.size fork, .-fork
|
||||
.end
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/risc-v/src/common/riscv_vfork.c
|
||||
* arch/risc-v/src/common/riscv_fork.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -34,7 +34,7 @@
|
|||
#include <nuttx/arch.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
#include "riscv_vfork.h"
|
||||
#include "riscv_fork.h"
|
||||
#include "riscv_internal.h"
|
||||
|
||||
#include "sched/sched.h"
|
||||
|
@ -52,22 +52,22 @@
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_vfork
|
||||
* Name: up_fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the
|
||||
* behavior is undefined if the process created by vfork() either modifies
|
||||
* The fork() function has the same effect as posix fork(), except that the
|
||||
* behavior is undefined if the process created by fork() either modifies
|
||||
* any data other than a variable of type pid_t used to store the return
|
||||
* value from vfork(), or returns from the function in which vfork() was
|
||||
* value from fork(), or returns from the function in which fork() was
|
||||
* called, or calls any other function before successfully calling _exit()
|
||||
* or one of the exec family of functions.
|
||||
*
|
||||
* The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork() and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB.
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork() and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB.
|
||||
* This consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -75,29 +75,29 @@
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* nxtask_abort_vfork() may be called if an error occurs between steps 3
|
||||
* nxtask_abort_fork() may be called if an error occurs between steps 3
|
||||
* and 6.
|
||||
*
|
||||
* Input Parameters:
|
||||
* context - Caller context information saved by vfork()
|
||||
* context - Caller context information saved by fork()
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and
|
||||
* Upon successful completion, fork() returns 0 to the child process and
|
||||
* returns the process ID of the child process to the parent process.
|
||||
* Otherwise, -1 is returned to the parent, no child process is created,
|
||||
* and errno is set to indicate the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_HAVE_VFORK
|
||||
#ifdef CONFIG_ARCH_HAVE_FORK
|
||||
|
||||
pid_t up_vfork(const struct vfork_s *context)
|
||||
pid_t up_fork(const struct fork_s *context)
|
||||
{
|
||||
struct tcb_s *parent = this_task();
|
||||
struct task_tcb_s *child;
|
||||
|
@ -136,10 +136,10 @@ pid_t up_vfork(const struct vfork_s *context)
|
|||
|
||||
/* Allocate and initialize a TCB for the child task. */
|
||||
|
||||
child = nxtask_setup_vfork((start_t)context->ra);
|
||||
child = nxtask_setup_fork((start_t)context->ra);
|
||||
if (!child)
|
||||
{
|
||||
sinfo("nxtask_setup_vfork failed\n");
|
||||
sinfo("nxtask_setup_fork failed\n");
|
||||
return (pid_t)ERROR;
|
||||
}
|
||||
|
||||
|
@ -160,7 +160,7 @@ pid_t up_vfork(const struct vfork_s *context)
|
|||
/* Make some feeble effort to preserve the stack contents. This is
|
||||
* feeble because the stack surely contains invalid pointers and other
|
||||
* content that will not work in the child context. However, if the
|
||||
* user follows all of the caveats of vfork() usage, even this feeble
|
||||
* user follows all of the caveats of fork() usage, even this feeble
|
||||
* effort is overkill.
|
||||
*/
|
||||
|
||||
|
@ -264,11 +264,11 @@ pid_t up_vfork(const struct vfork_s *context)
|
|||
}
|
||||
#endif /* CONFIG_LIB_SYSCALL */
|
||||
|
||||
/* And, finally, start the child task. On a failure, nxtask_start_vfork()
|
||||
* will discard the TCB by calling nxtask_abort_vfork().
|
||||
/* And, finally, start the child task. On a failure, nxtask_start_fork()
|
||||
* will discard the TCB by calling nxtask_abort_fork().
|
||||
*/
|
||||
|
||||
return nxtask_start_vfork(child);
|
||||
return nxtask_start_fork(child);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_HAVE_VFORK */
|
||||
#endif /* CONFIG_ARCH_HAVE_FORK */
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/risc-v/src/common/riscv_vfork.h
|
||||
* arch/risc-v/src/common/riscv_fork.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -18,8 +18,8 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_RISCV_SRC_COMMON_RISCV_VFORK_H
|
||||
#define __ARCH_RISCV_SRC_COMMON_RISCV_VFORK_H
|
||||
#ifndef __ARCH_RISCV_SRC_COMMON_RISCV_FORK_H
|
||||
#define __ARCH_RISCV_SRC_COMMON_RISCV_FORK_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
|
@ -35,10 +35,10 @@
|
|||
****************************************************************************/
|
||||
|
||||
/* Register x8 may be a frame pointer in some ABIs. Or may just be saved
|
||||
* register s0. It makes a difference for vfork handling.
|
||||
* register s0. It makes a difference for fork handling.
|
||||
*/
|
||||
|
||||
#undef VFORK_HAVE_FP
|
||||
#undef FORK_HAVE_FP
|
||||
|
||||
/* Register ABI Name Description Saver
|
||||
*
|
||||
|
@ -62,59 +62,59 @@
|
|||
* f28–31 ft8–11 FP temporaries Caller
|
||||
*/
|
||||
|
||||
#define VFORK_S1_OFFSET (1*INT_REG_SIZE) /* Saved register s1 */
|
||||
#define VFORK_S2_OFFSET (2*INT_REG_SIZE) /* Saved register s2 */
|
||||
#define VFORK_S3_OFFSET (3*INT_REG_SIZE) /* Saved register s3 */
|
||||
#define VFORK_S4_OFFSET (4*INT_REG_SIZE) /* Saved register s4 */
|
||||
#define VFORK_S5_OFFSET (5*INT_REG_SIZE) /* Saved register s5 */
|
||||
#define VFORK_S6_OFFSET (6*INT_REG_SIZE) /* Saved register s6 */
|
||||
#define VFORK_S7_OFFSET (7*INT_REG_SIZE) /* Saved register s7 */
|
||||
#define VFORK_S8_OFFSET (8*INT_REG_SIZE) /* Saved register s8 */
|
||||
#define VFORK_S9_OFFSET (9*INT_REG_SIZE) /* Saved register s9 */
|
||||
#define VFORK_S10_OFFSET (10*INT_REG_SIZE) /* Saved register s10 */
|
||||
#define VFORK_S11_OFFSET (11*INT_REG_SIZE) /* Saved register s11 */
|
||||
#define FORK_S1_OFFSET (1*INT_REG_SIZE) /* Saved register s1 */
|
||||
#define FORK_S2_OFFSET (2*INT_REG_SIZE) /* Saved register s2 */
|
||||
#define FORK_S3_OFFSET (3*INT_REG_SIZE) /* Saved register s3 */
|
||||
#define FORK_S4_OFFSET (4*INT_REG_SIZE) /* Saved register s4 */
|
||||
#define FORK_S5_OFFSET (5*INT_REG_SIZE) /* Saved register s5 */
|
||||
#define FORK_S6_OFFSET (6*INT_REG_SIZE) /* Saved register s6 */
|
||||
#define FORK_S7_OFFSET (7*INT_REG_SIZE) /* Saved register s7 */
|
||||
#define FORK_S8_OFFSET (8*INT_REG_SIZE) /* Saved register s8 */
|
||||
#define FORK_S9_OFFSET (9*INT_REG_SIZE) /* Saved register s9 */
|
||||
#define FORK_S10_OFFSET (10*INT_REG_SIZE) /* Saved register s10 */
|
||||
#define FORK_S11_OFFSET (11*INT_REG_SIZE) /* Saved register s11 */
|
||||
|
||||
#ifdef CONFIG_RISCV_FRAMEPOINTER
|
||||
# define VFORK_FP_OFFSET (0*INT_REG_SIZE) /* Frame pointer */
|
||||
# define FORK_FP_OFFSET (0*INT_REG_SIZE) /* Frame pointer */
|
||||
#else
|
||||
# define VFORK_S0_OFFSET (0*INT_REG_SIZE) /* Saved register s0 */
|
||||
# define FORK_S0_OFFSET (0*INT_REG_SIZE) /* Saved register s0 */
|
||||
#endif
|
||||
|
||||
#define VFORK_SP_OFFSET (12*INT_REG_SIZE) /* Stack pointer*/
|
||||
#define VFORK_RA_OFFSET (13*INT_REG_SIZE) /* Return address*/
|
||||
#define FORK_SP_OFFSET (12*INT_REG_SIZE) /* Stack pointer*/
|
||||
#define FORK_RA_OFFSET (13*INT_REG_SIZE) /* Return address*/
|
||||
#ifdef RISCV_SAVE_GP
|
||||
# define VFORK_GP_OFFSET (14*INT_REG_SIZE) /* Global pointer */
|
||||
# define VFORK_INT_SIZE (15*INT_REG_SIZE)
|
||||
# define FORK_GP_OFFSET (14*INT_REG_SIZE) /* Global pointer */
|
||||
# define FORK_INT_SIZE (15*INT_REG_SIZE)
|
||||
#else
|
||||
# define VFORK_INT_SIZE (14*INT_REG_SIZE)
|
||||
# define FORK_INT_SIZE (14*INT_REG_SIZE)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
# define VFORK_FS0_OFFSET (VFORK_INT_SIZE + 0*FPU_REG_FULL_SIZE)
|
||||
# define VFORK_FS1_OFFSET (VFORK_INT_SIZE + 1*FPU_REG_FULL_SIZE)
|
||||
# define VFORK_FS2_OFFSET (VFORK_INT_SIZE + 2*FPU_REG_FULL_SIZE)
|
||||
# define VFORK_FS3_OFFSET (VFORK_INT_SIZE + 3*FPU_REG_FULL_SIZE)
|
||||
# define VFORK_FS4_OFFSET (VFORK_INT_SIZE + 4*FPU_REG_FULL_SIZE)
|
||||
# define VFORK_FS5_OFFSET (VFORK_INT_SIZE + 5*FPU_REG_FULL_SIZE)
|
||||
# define VFORK_FS6_OFFSET (VFORK_INT_SIZE + 6*FPU_REG_FULL_SIZE)
|
||||
# define VFORK_FS7_OFFSET (VFORK_INT_SIZE + 7*FPU_REG_FULL_SIZE)
|
||||
# define VFORK_FS8_OFFSET (VFORK_INT_SIZE + 8*FPU_REG_FULL_SIZE)
|
||||
# define VFORK_FS9_OFFSET (VFORK_INT_SIZE + 9*FPU_REG_FULL_SIZE)
|
||||
# define VFORK_FS10_OFFSET (VFORK_INT_SIZE + 10*FPU_REG_FULL_SIZE)
|
||||
# define VFORK_FS11_OFFSET (VFORK_INT_SIZE + 11*FPU_REG_FULL_SIZE)
|
||||
# define VFORK_FPU_SIZE (12*FPU_REG_FULL_SIZE)
|
||||
# define FORK_FS0_OFFSET (FORK_INT_SIZE + 0*FPU_REG_FULL_SIZE)
|
||||
# define FORK_FS1_OFFSET (FORK_INT_SIZE + 1*FPU_REG_FULL_SIZE)
|
||||
# define FORK_FS2_OFFSET (FORK_INT_SIZE + 2*FPU_REG_FULL_SIZE)
|
||||
# define FORK_FS3_OFFSET (FORK_INT_SIZE + 3*FPU_REG_FULL_SIZE)
|
||||
# define FORK_FS4_OFFSET (FORK_INT_SIZE + 4*FPU_REG_FULL_SIZE)
|
||||
# define FORK_FS5_OFFSET (FORK_INT_SIZE + 5*FPU_REG_FULL_SIZE)
|
||||
# define FORK_FS6_OFFSET (FORK_INT_SIZE + 6*FPU_REG_FULL_SIZE)
|
||||
# define FORK_FS7_OFFSET (FORK_INT_SIZE + 7*FPU_REG_FULL_SIZE)
|
||||
# define FORK_FS8_OFFSET (FORK_INT_SIZE + 8*FPU_REG_FULL_SIZE)
|
||||
# define FORK_FS9_OFFSET (FORK_INT_SIZE + 9*FPU_REG_FULL_SIZE)
|
||||
# define FORK_FS10_OFFSET (FORK_INT_SIZE + 10*FPU_REG_FULL_SIZE)
|
||||
# define FORK_FS11_OFFSET (FORK_INT_SIZE + 11*FPU_REG_FULL_SIZE)
|
||||
# define FORK_FPU_SIZE (12*FPU_REG_FULL_SIZE)
|
||||
#else
|
||||
# define VFORK_FPU_SIZE (0)
|
||||
# define FORK_FPU_SIZE (0)
|
||||
#endif
|
||||
|
||||
#define VFORK_SIZEOF STACK_ALIGN_UP(VFORK_INT_SIZE + VFORK_FPU_SIZE)
|
||||
#define FORK_SIZEOF STACK_ALIGN_UP(FORK_INT_SIZE + FORK_FPU_SIZE)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
struct vfork_s
|
||||
struct fork_s
|
||||
{
|
||||
/* CPU registers */
|
||||
|
||||
|
@ -159,4 +159,4 @@ struct vfork_s
|
|||
};
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_RISCV_SRC_COMMON_RISCV_VFORK_H */
|
||||
#endif /* __ARCH_RISCV_SRC_COMMON_RISCV_FORK_H */
|
|
@ -46,16 +46,16 @@ endif
|
|||
|
||||
ifeq ($(CONFIG_HOST_X86_64),y)
|
||||
ifeq ($(CONFIG_SIM_M32),y)
|
||||
ASRCS += sim_vfork_x86.S
|
||||
ASRCS += sim_fork_x86.S
|
||||
else
|
||||
ASRCS += sim_vfork_x86_64.S
|
||||
ASRCS += sim_fork_x86_64.S
|
||||
endif
|
||||
else ifeq ($(CONFIG_HOST_X86),y)
|
||||
ASRCS += sim_vfork_x86.S
|
||||
ASRCS += sim_fork_x86.S
|
||||
else ifeq ($(CONFIG_HOST_ARM),y)
|
||||
ASRCS += sim_vfork_arm.S
|
||||
ASRCS += sim_fork_arm.S
|
||||
else ifeq ($(CONFIG_HOST_ARM64),y)
|
||||
ASRCS += sim_vfork_arm64.S
|
||||
ASRCS += sim_fork_arm64.S
|
||||
endif
|
||||
|
||||
AOBJS = $(ASRCS:.S=$(OBJEXT))
|
||||
|
@ -70,10 +70,8 @@ ifeq ($(CONFIG_SCHED_BACKTRACE),y)
|
|||
CSRCS += sim_backtrace.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
|
||||
ifeq ($(CONFIG_SCHED_WAITPID),y)
|
||||
CSRCS += sim_vfork.c
|
||||
endif
|
||||
ifeq ($(CONFIG_ARCH_HAVE_FORK),y)
|
||||
CSRCS += sim_fork.c
|
||||
endif
|
||||
|
||||
VPATH = :sim
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/sim/src/sim/sim_vfork.c
|
||||
* arch/sim/src/sim/sim_fork.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -43,22 +43,22 @@
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_vfork
|
||||
* Name: up_fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the
|
||||
* behavior is undefined if the process created by vfork() either modifies
|
||||
* The fork() function has the same effect as posix fork(), except that the
|
||||
* behavior is undefined if the process created by fork() either modifies
|
||||
* any data other than a variable of type pid_t used to store the return
|
||||
* value from vfork(), or returns from the function in which vfork() was
|
||||
* value from fork(), or returns from the function in which fork() was
|
||||
* called, or calls any other function before successfully calling _exit()
|
||||
* or one of the exec family of functions.
|
||||
*
|
||||
* The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork() and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB.
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork() and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB.
|
||||
* This consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -66,17 +66,17 @@
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* nxtask_abort_vfork() may be called if an error occurs between steps 3 and
|
||||
* nxtask_abort_fork() may be called if an error occurs between steps 3 and
|
||||
* 6.
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and
|
||||
* Upon successful completion, fork() returns 0 to the child process and
|
||||
* returns the process ID of the child process to the parent process.
|
||||
* Otherwise, -1 is returned to the parent, no child process is created,
|
||||
* and errno is set to indicate the error.
|
||||
|
@ -86,7 +86,7 @@
|
|||
#ifdef CONFIG_SIM_ASAN
|
||||
nosanitize_address
|
||||
#endif
|
||||
pid_t up_vfork(const xcpt_reg_t *context)
|
||||
pid_t up_fork(const xcpt_reg_t *context)
|
||||
{
|
||||
struct tcb_s *parent = this_task();
|
||||
struct task_tcb_s *child;
|
||||
|
@ -98,16 +98,16 @@ pid_t up_vfork(const xcpt_reg_t *context)
|
|||
xcpt_reg_t stacktop;
|
||||
xcpt_reg_t stackutil;
|
||||
|
||||
sinfo("vfork context [%p]:\n", context);
|
||||
sinfo("fork context [%p]:\n", context);
|
||||
sinfo(" frame pointer:%lx sp:%lx pc:%lx\n",
|
||||
context[JB_FP], context[JB_SP], context[JB_PC]);
|
||||
|
||||
/* Allocate and initialize a TCB for the child task. */
|
||||
|
||||
child = nxtask_setup_vfork((start_t)context[JB_PC]);
|
||||
child = nxtask_setup_fork((start_t)context[JB_PC]);
|
||||
if (!child)
|
||||
{
|
||||
serr("ERROR: nxtask_setup_vfork failed\n");
|
||||
serr("ERROR: nxtask_setup_fork failed\n");
|
||||
return (pid_t)ERROR;
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,7 @@ pid_t up_vfork(const xcpt_reg_t *context)
|
|||
/* Make some feeble effort to preserve the stack contents. This is
|
||||
* feeble because the stack surely contains invalid pointers and other
|
||||
* content that will not work in the child context. However, if the
|
||||
* user follows all of the caveats of vfork() usage, even this feeble
|
||||
* user follows all of the caveats of fork() usage, even this feeble
|
||||
* effort is overkill.
|
||||
*/
|
||||
|
||||
|
@ -169,9 +169,9 @@ pid_t up_vfork(const xcpt_reg_t *context)
|
|||
child->cmn.xcp.regs[JB_FP] = newfp; /* Frame pointer */
|
||||
child->cmn.xcp.regs[JB_SP] = newsp; /* Stack pointer */
|
||||
|
||||
/* And, finally, start the child task. On a failure, nxtask_start_vfork()
|
||||
* will discard the TCB by calling nxtask_abort_vfork().
|
||||
/* And, finally, start the child task. On a failure, nxtask_start_fork()
|
||||
* will discard the TCB by calling nxtask_abort_fork().
|
||||
*/
|
||||
|
||||
return nxtask_start_vfork(child);
|
||||
return nxtask_start_fork(child);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/************************************************************************************
|
||||
* arch/sim/src/sim/sim_vfork_arm.S
|
||||
* arch/sim/src/sim/sim_fork_arm.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -33,30 +33,30 @@
|
|||
* Public Symbols
|
||||
************************************************************************************/
|
||||
|
||||
.file "vfork.S"
|
||||
.globl up_vfork
|
||||
.file "fork.S"
|
||||
.globl up_fork
|
||||
|
||||
/************************************************************************************
|
||||
* Public Functions
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
* Name: vfork
|
||||
* Name: fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the behavior is
|
||||
* undefined if the process created by vfork() either modifies any data other than
|
||||
* a variable of type pid_t used to store the return value from vfork(), or returns
|
||||
* from the function in which vfork() was called, or calls any other function before
|
||||
* The fork() function has the same effect as posix fork(), except that the behavior is
|
||||
* undefined if the process created by fork() either modifies any data other than
|
||||
* a variable of type pid_t used to store the return value from fork(), or returns
|
||||
* from the function in which fork() was called, or calls any other function before
|
||||
* successfully calling _exit() or one of the exec family of functions.
|
||||
*
|
||||
* This thin layer implements vfork by simply calling up_vfork() with the vfork()
|
||||
* This thin layer implements fork by simply calling up_fork() with the fork()
|
||||
* context as an argument. The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork() and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB. This
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork() and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB. This
|
||||
* consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -64,17 +64,17 @@
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and returns
|
||||
* Upon successful completion, fork() returns 0 to the child process and returns
|
||||
* the process ID of the child process to the parent process. Otherwise, -1 is
|
||||
* returned to the parent, no child process is created, and errno is set to
|
||||
* indicate the error.
|
||||
|
@ -82,18 +82,18 @@
|
|||
************************************************************************************/
|
||||
|
||||
.text
|
||||
.globl vfork
|
||||
.type vfork, @function
|
||||
vfork:
|
||||
.globl fork
|
||||
.type fork, @function
|
||||
fork:
|
||||
sub sp, sp, #XCPTCONTEXT_SIZE
|
||||
mov r0, sp
|
||||
bl setjmp
|
||||
|
||||
subs r0, #1
|
||||
jz child
|
||||
bl up_vfork
|
||||
bl up_fork
|
||||
child:
|
||||
add sp, sp, #XCPTCONTEXT_SIZE
|
||||
ret
|
||||
.size vfork, . - vfork
|
||||
.size fork, . - fork
|
||||
.end
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/sim/src/sim/sim_vfork_arm64.S
|
||||
* arch/sim/src/sim/sim_fork_arm64.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -41,8 +41,8 @@
|
|||
* Public Symbols
|
||||
***************************************************************************/
|
||||
|
||||
.file "up_vfork_arm64.S"
|
||||
.globl SYMBOL(up_vfork)
|
||||
.file "up_fork_arm64.S"
|
||||
.globl SYMBOL(up_fork)
|
||||
.globl SYMBOL(setjmp)
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -50,23 +50,23 @@
|
|||
***************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vfork
|
||||
* Name: fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the
|
||||
* behavior is undefined if the process created by vfork() either modifies
|
||||
* The fork() function has the same effect as posix fork(), except that the
|
||||
* behavior is undefined if the process created by fork() either modifies
|
||||
* any data other than a variable of type pid_t used to store the return
|
||||
* value from vfork(), or returns from the function in which vfork() was
|
||||
* value from fork(), or returns from the function in which fork() was
|
||||
* called, or calls any other function before successfully calling _exit()
|
||||
* or one of the exec family of functions.
|
||||
*
|
||||
* This thin layer implements vfork by simply calling up_vfork() with the
|
||||
* vfork() context as an argument. The overall sequence is:
|
||||
* This thin layer implements fork by simply calling up_fork() with the
|
||||
* fork() context as an argument. The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork() and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB.
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork() and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB.
|
||||
* This consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -74,17 +74,17 @@
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and
|
||||
* Upon successful completion, fork() returns 0 to the child process and
|
||||
* returns the process ID of the child process to the parent process.
|
||||
* Otherwise, -1 is returned to the parent, no child process is created,
|
||||
* and errno is set to indicate the error.
|
||||
|
@ -92,10 +92,10 @@
|
|||
***************************************************************************/
|
||||
|
||||
.text
|
||||
.globl SYMBOL(vfork)
|
||||
.globl SYMBOL(fork)
|
||||
.align 4
|
||||
|
||||
SYMBOL(vfork):
|
||||
SYMBOL(fork):
|
||||
|
||||
stp x29, x30, [sp] /* save FP/LR register */
|
||||
sub sp, sp, #XCPTCONTEXT_SIZE /* area from stack for setjmp() */
|
||||
|
@ -106,8 +106,8 @@ SYMBOL(vfork):
|
|||
subs x0, x0, #1 /* 0: parent / 1: child */
|
||||
cbz x0, 1f /* child --> return */
|
||||
|
||||
mov x0, sp /* pass stack area to up_vfork() */
|
||||
bl SYMBOL(up_vfork) /* further process task creation */
|
||||
mov x0, sp /* pass stack area to up_fork() */
|
||||
bl SYMBOL(up_fork) /* further process task creation */
|
||||
|
||||
1:
|
||||
add sp, sp, #XCPTCONTEXT_SIZE /* release area from stack */
|
|
@ -1,5 +1,5 @@
|
|||
/************************************************************************************
|
||||
* arch/sim/src/sim/sim_vfork_x86.S
|
||||
* arch/sim/src/sim/sim_fork_x86.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -41,30 +41,30 @@
|
|||
* Public Symbols
|
||||
************************************************************************************/
|
||||
|
||||
.file "vfork.S"
|
||||
.globl up_vfork
|
||||
.file "fork.S"
|
||||
.globl up_fork
|
||||
|
||||
/************************************************************************************
|
||||
* Public Functions
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
* Name: vfork
|
||||
* Name: fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the behavior is
|
||||
* undefined if the process created by vfork() either modifies any data other than
|
||||
* a variable of type pid_t used to store the return value from vfork(), or returns
|
||||
* from the function in which vfork() was called, or calls any other function before
|
||||
* The fork() function has the same effect as posix fork(), except that the behavior is
|
||||
* undefined if the process created by fork() either modifies any data other than
|
||||
* a variable of type pid_t used to store the return value from fork(), or returns
|
||||
* from the function in which fork() was called, or calls any other function before
|
||||
* successfully calling _exit() or one of the exec family of functions.
|
||||
*
|
||||
* This thin layer implements vfork by simply calling up_vfork() with the vfork()
|
||||
* This thin layer implements fork by simply calling up_fork() with the fork()
|
||||
* context as an argument. The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork() and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB. This
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork() and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB. This
|
||||
* consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -72,17 +72,17 @@
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and returns
|
||||
* Upon successful completion, fork() returns 0 to the child process and returns
|
||||
* the process ID of the child process to the parent process. Otherwise, -1 is
|
||||
* returned to the parent, no child process is created, and errno is set to
|
||||
* indicate the error.
|
||||
|
@ -90,22 +90,22 @@
|
|||
************************************************************************************/
|
||||
|
||||
.text
|
||||
.globl SYMBOL(vfork)
|
||||
.globl SYMBOL(fork)
|
||||
#ifdef __ELF__
|
||||
.type SYMBOL(vfork), @function
|
||||
.type SYMBOL(fork), @function
|
||||
#endif
|
||||
|
||||
SYMBOL(vfork):
|
||||
SYMBOL(fork):
|
||||
sub $XCPTCONTEXT_SIZE, %esp
|
||||
push %esp
|
||||
call SYMBOL(setjmp)
|
||||
|
||||
sub $1, %eax
|
||||
jz child
|
||||
call SYMBOL(up_vfork)
|
||||
call SYMBOL(up_fork)
|
||||
child:
|
||||
add $XCPTCONTEXT_SIZE+4, %esp
|
||||
ret
|
||||
#ifdef __ELF__
|
||||
.size SYMBOL(vfork), . - SYMBOL(vfork)
|
||||
.size SYMBOL(fork), . - SYMBOL(fork)
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/************************************************************************************
|
||||
* arch/sim/src/sim/sim_vfork_x86_64.S
|
||||
* arch/sim/src/sim/sim_fork_x86_64.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -41,30 +41,30 @@
|
|||
* Public Symbols
|
||||
************************************************************************************/
|
||||
|
||||
.file "vfork.S"
|
||||
.globl up_vfork
|
||||
.file "fork.S"
|
||||
.globl up_fork
|
||||
|
||||
/************************************************************************************
|
||||
* Public Functions
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
* Name: vfork
|
||||
* Name: fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the behavior is
|
||||
* undefined if the process created by vfork() either modifies any data other than
|
||||
* a variable of type pid_t used to store the return value from vfork(), or returns
|
||||
* from the function in which vfork() was called, or calls any other function before
|
||||
* The fork() function has the same effect as posix fork(), except that the behavior is
|
||||
* undefined if the process created by fork() either modifies any data other than
|
||||
* a variable of type pid_t used to store the return value from fork(), or returns
|
||||
* from the function in which fork() was called, or calls any other function before
|
||||
* successfully calling _exit() or one of the exec family of functions.
|
||||
*
|
||||
* This thin layer implements vfork by simply calling up_vfork() with the vfork()
|
||||
* This thin layer implements fork by simply calling up_fork() with the fork()
|
||||
* context as an argument. The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() collects context information and
|
||||
* transfers control up up_vfork().
|
||||
* 2) up_vfork() and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB. This
|
||||
* 1) User code calls fork(). fork() collects context information and
|
||||
* transfers control up up_fork().
|
||||
* 2) up_fork() and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB. This
|
||||
* consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -72,17 +72,17 @@
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and returns
|
||||
* Upon successful completion, fork() returns 0 to the child process and returns
|
||||
* the process ID of the child process to the parent process. Otherwise, -1 is
|
||||
* returned to the parent, no child process is created, and errno is set to
|
||||
* indicate the error.
|
||||
|
@ -90,12 +90,12 @@
|
|||
************************************************************************************/
|
||||
|
||||
.text
|
||||
.globl SYMBOL(vfork)
|
||||
.globl SYMBOL(fork)
|
||||
#ifdef __ELF__
|
||||
.type SYMBOL(vfork), @function
|
||||
.type SYMBOL(fork), @function
|
||||
#endif
|
||||
|
||||
SYMBOL(vfork):
|
||||
SYMBOL(fork):
|
||||
sub $XCPTCONTEXT_SIZE, %rsp
|
||||
#ifdef CONFIG_SIM_X8664_MICROSOFT
|
||||
mov %rsp, %rcx
|
||||
|
@ -106,10 +106,11 @@ SYMBOL(vfork):
|
|||
|
||||
sub $1, %eax
|
||||
jz child
|
||||
call SYMBOL(up_vfork)
|
||||
|
||||
call SYMBOL(up_fork)
|
||||
child:
|
||||
add $XCPTCONTEXT_SIZE, %rsp
|
||||
ret
|
||||
#ifdef __ELF__
|
||||
.size SYMBOL(vfork), . - SYMBOL(vfork)
|
||||
.size SYMBOL(fork), . - SYMBOL(fork)
|
||||
#endif
|
|
@ -1078,12 +1078,12 @@ void nxtask_startup(main_t entrypt, int argc, FAR char *argv[]);
|
|||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Internal vfork support. The overall sequence is:
|
||||
* Internal fork support. The overall sequence is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() is provided in architecture-specific
|
||||
* 1) User code calls fork(). fork() is provided in architecture-specific
|
||||
* code.
|
||||
* 2) vfork()and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB.
|
||||
* 2) fork()and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB.
|
||||
* This consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -1091,20 +1091,20 @@ void nxtask_startup(main_t entrypt, int argc, FAR char *argv[]);
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) vfork() provides any additional operating context. vfork must:
|
||||
* 4) fork() provides any additional operating context. fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* nxtask_abort_vfork() may be called if an error occurs between
|
||||
* nxtask_abort_fork() may be called if an error occurs between
|
||||
* steps 3 and 6.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct task_tcb_s *nxtask_setup_vfork(start_t retaddr);
|
||||
pid_t nxtask_start_vfork(FAR struct task_tcb_s *child);
|
||||
void nxtask_abort_vfork(FAR struct task_tcb_s *child, int errcode);
|
||||
FAR struct task_tcb_s *nxtask_setup_fork(start_t retaddr);
|
||||
pid_t nxtask_start_fork(FAR struct task_tcb_s *child);
|
||||
void nxtask_abort_fork(FAR struct task_tcb_s *child, int errcode);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: group_argvstr
|
||||
|
|
|
@ -114,8 +114,8 @@ SYSCALL_LOOKUP(task_setcancelstate, 2)
|
|||
|
||||
/* The following can be individually enabled */
|
||||
|
||||
#if defined(CONFIG_SCHED_WAITPID) && defined(CONFIG_ARCH_HAVE_VFORK)
|
||||
SYSCALL_LOOKUP(vfork, 0)
|
||||
#ifdef CONFIG_ARCH_HAVE_FORK
|
||||
SYSCALL_LOOKUP(fork, 0)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCHED_WAITPID
|
||||
|
|
|
@ -307,6 +307,7 @@ extern "C"
|
|||
|
||||
/* Task Control Interfaces */
|
||||
|
||||
pid_t fork(void);
|
||||
pid_t vfork(void);
|
||||
pid_t getpid(void);
|
||||
pid_t getpgrp(void);
|
||||
|
|
|
@ -48,6 +48,12 @@ ifneq ($(CONFIG_DISABLE_MOUNTPOINTS),y)
|
|||
CSRCS += lib_truncate.c lib_posix_fallocate.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_HAVE_FORK),y)
|
||||
ifeq ($(CONFIG_SCHED_WAITPID),y)
|
||||
CSRCS += lib_vfork.c
|
||||
endif
|
||||
endif
|
||||
|
||||
# Add the unistd directory to the build
|
||||
|
||||
DEPPATH += --dep-path unistd
|
||||
|
|
76
libs/libc/unistd/lib_vfork.c
Normal file
76
libs/libc/unistd/lib_vfork.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/****************************************************************************
|
||||
* libs/libc/unistd/lib_vfork.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 <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#if defined(CONFIG_ARCH_HAVE_FORK) && defined(CONFIG_SCHED_WAITPID)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vfork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function is implemented based on fork() function, on
|
||||
* vfork(), the parent task need to wait until the child task is performing
|
||||
* exec or running finished.
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and
|
||||
* returns the process ID of the child process to the parent process.
|
||||
* Otherwise, -1 is returned to the parent, no child process is created,
|
||||
* and errno is set to indicate the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
pid_t vfork(void)
|
||||
{
|
||||
int status = 0;
|
||||
int ret;
|
||||
pid_t pid = fork();
|
||||
|
||||
if (pid != 0)
|
||||
{
|
||||
/* we are in parent task, and we need to wait the child task
|
||||
* until running finished or performing exec
|
||||
*/
|
||||
|
||||
ret = waitpid(pid, &status, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
serr("ERROR: waitpid failed: %d\n", get_errno());
|
||||
}
|
||||
}
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_HAVE_FORK && CONFIG_SCHED_WAITPID */
|
|
@ -29,10 +29,8 @@ ifeq ($(CONFIG_SCHED_HAVE_PARENT),y)
|
|||
CSRCS += task_getppid.c task_reparent.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
|
||||
ifeq ($(CONFIG_SCHED_WAITPID),y)
|
||||
CSRCS += task_vfork.c
|
||||
endif
|
||||
ifeq ($(CONFIG_ARCH_HAVE_FORK),y)
|
||||
CSRCS += task_fork.c
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_BUILD_KERNEL),y)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* sched/task/task_vfork.c
|
||||
* sched/task/task_fork.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -40,33 +40,33 @@
|
|||
#include "task/task.h"
|
||||
#include "tls/tls.h"
|
||||
|
||||
/* vfork() requires architecture-specific support as well as waipid(). */
|
||||
/* fork() requires architecture-specific support as well as waipid(). */
|
||||
|
||||
#if defined(CONFIG_ARCH_HAVE_VFORK) && defined(CONFIG_SCHED_WAITPID)
|
||||
#ifdef CONFIG_ARCH_HAVE_FORK
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxtask_setup_vfork
|
||||
* Name: nxtask_setup_fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the
|
||||
* behavior is undefined if the process created by vfork() either modifies
|
||||
* The fork() function has the same effect as posix fork(), except that the
|
||||
* behavior is undefined if the process created by fork() either modifies
|
||||
* any data other than a variable of type pid_t used to store the return
|
||||
* value from vfork(), or returns from the function in which vfork() was
|
||||
* value from fork(), or returns from the function in which fork() was
|
||||
* called, or calls any other function before successfully calling _exit()
|
||||
* or one of the exec family of functions.
|
||||
*
|
||||
* This function provides one step in the overall vfork() sequence: It
|
||||
* This function provides one step in the overall fork() sequence: It
|
||||
* Allocates and initializes the child task's TCB. The overall sequence
|
||||
* is:
|
||||
*
|
||||
* 1) User code calls vfork(). vfork() is provided in
|
||||
* 1) User code calls fork(). fork() is provided in
|
||||
* architecture-specific code.
|
||||
* 2) vfork()and calls nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB.
|
||||
* 2) fork()and calls nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB.
|
||||
* This consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -74,24 +74,24 @@
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) up_vfork() provides any additional operating context. up_vfork must:
|
||||
* 4) up_fork() provides any additional operating context. up_fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) up_vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) up_fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* Input Parameters:
|
||||
* retaddr - Return address
|
||||
* argsize - Location to return the argument size
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, nxtask_setup_vfork() returns a pointer to
|
||||
* Upon successful completion, nxtask_setup_fork() returns a pointer to
|
||||
* newly allocated and initialized child task's TCB. NULL is returned
|
||||
* on any failure and the errno is set appropriately.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct task_tcb_s *nxtask_setup_vfork(start_t retaddr)
|
||||
FAR struct task_tcb_s *nxtask_setup_fork(start_t retaddr)
|
||||
{
|
||||
FAR struct tcb_s *ptcb = this_task();
|
||||
FAR struct tcb_s *parent;
|
||||
|
@ -226,24 +226,24 @@ errout:
|
|||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxtask_start_vfork
|
||||
* Name: nxtask_start_fork
|
||||
*
|
||||
* Description:
|
||||
* The vfork() function has the same effect as fork(), except that the
|
||||
* behavior is undefined if the process created by vfork() either modifies
|
||||
* The fork() function has the same effect as fork(), except that the
|
||||
* behavior is undefined if the process created by fork() either modifies
|
||||
* any data other than a variable of type pid_t used to store the return
|
||||
* value from vfork(), or returns from the function in which vfork() was
|
||||
* value from fork(), or returns from the function in which fork() was
|
||||
* called, or calls any other function before successfully calling _exit()
|
||||
* or one of the exec family of functions.
|
||||
*
|
||||
* This function provides one step in the overall vfork() sequence: It
|
||||
* This function provides one step in the overall fork() sequence: It
|
||||
* starts execution of the previously initialized TCB. The overall
|
||||
* sequence is:
|
||||
*
|
||||
* 1) User code calls vfork()
|
||||
* 2) Architecture-specific code provides vfork()and calls
|
||||
* nxtask_setup_vfork().
|
||||
* 3) nxtask_setup_vfork() allocates and configures the child task's TCB.
|
||||
* 1) User code calls fork()
|
||||
* 2) Architecture-specific code provides fork()and calls
|
||||
* nxtask_setup_fork().
|
||||
* 3) nxtask_setup_fork() allocates and configures the child task's TCB.
|
||||
* This consists of:
|
||||
* - Allocation of the child task's TCB.
|
||||
* - Initialization of file descriptors and streams
|
||||
|
@ -251,29 +251,28 @@ errout:
|
|||
* - Allocate and initialize the stack
|
||||
* - Setup the input parameters for the task.
|
||||
* - Initialization of the TCB (including call to up_initial_state())
|
||||
* 4) vfork() provides any additional operating context. vfork must:
|
||||
* 4) fork() provides any additional operating context. fork must:
|
||||
* - Initialize special values in any CPU registers that were not
|
||||
* already configured by up_initial_state()
|
||||
* 5) vfork() then calls nxtask_start_vfork()
|
||||
* 6) nxtask_start_vfork() then executes the child thread.
|
||||
* 5) fork() then calls nxtask_start_fork()
|
||||
* 6) nxtask_start_fork() then executes the child thread.
|
||||
*
|
||||
* Input Parameters:
|
||||
* retaddr - The return address from vfork() where the child task
|
||||
* will be started.
|
||||
* child - The task_tcb_s struct instance that created by
|
||||
* nxtask_setup_fork() method
|
||||
* wait_child - whether need to wait until the child is running finished
|
||||
*
|
||||
* Returned Value:
|
||||
* Upon successful completion, vfork() returns 0 to the child process and
|
||||
* Upon successful completion, fork() returns 0 to the child process and
|
||||
* returns the process ID of the child process to the parent process.
|
||||
* Otherwise, -1 is returned to the parent, no child process is created,
|
||||
* and errno is set to indicate the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
pid_t nxtask_start_vfork(FAR struct task_tcb_s *child)
|
||||
pid_t nxtask_start_fork(FAR struct task_tcb_s *child)
|
||||
{
|
||||
pid_t pid;
|
||||
int rc = 0;
|
||||
int ret;
|
||||
|
||||
sinfo("Starting Child TCB=%p\n", child);
|
||||
DEBUGASSERT(child);
|
||||
|
@ -294,45 +293,22 @@ pid_t nxtask_start_vfork(FAR struct task_tcb_s *child)
|
|||
|
||||
nxtask_activate((FAR struct tcb_s *)child);
|
||||
|
||||
/* The child task has not yet ran because pre-emption is disabled.
|
||||
* The child task has the same priority as the parent task, so that
|
||||
* would typically be the case anyway. However, in the SMP
|
||||
* configuration, the child thread might have already ran on
|
||||
* another CPU if pre-emption were not disabled.
|
||||
*
|
||||
* It is a requirement that the parent environment be stable while
|
||||
* vfork runs; the child thread is still dependent on things in the
|
||||
* parent thread... like the pointers into parent thread's stack
|
||||
* which will still appear in the child's registers and environment.
|
||||
*
|
||||
* We assure that by waiting for the child thread to exit before
|
||||
* returning to the parent thread. NOTE that pre-emption will be
|
||||
* re-enabled while we are waiting, giving the child thread the
|
||||
* opportunity to run.
|
||||
*/
|
||||
|
||||
ret = waitpid(pid, &rc, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
serr("ERROR: waitpid failed: %d\n", get_errno());
|
||||
}
|
||||
|
||||
sched_unlock();
|
||||
return pid;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxtask_abort_vfork
|
||||
* Name: nxtask_abort_fork
|
||||
*
|
||||
* Description:
|
||||
* Recover from any errors after nxtask_setup_vfork() was called.
|
||||
* Recover from any errors after nxtask_setup_fork() was called.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void nxtask_abort_vfork(FAR struct task_tcb_s *child, int errcode)
|
||||
void nxtask_abort_fork(FAR struct task_tcb_s *child, int errcode)
|
||||
{
|
||||
/* The TCB was added to the active task list by nxtask_setup_scheduler() */
|
||||
|
||||
|
@ -345,4 +321,4 @@ void nxtask_abort_vfork(FAR struct task_tcb_s *child, int errcode)
|
|||
set_errno(errcode);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_HAVE_VFORK && CONFIG_SCHED_WAITPID */
|
||||
#endif /* CONFIG_ARCH_HAVE_FORK */
|
|
@ -29,6 +29,7 @@
|
|||
"fchmod","sys/stat.h","","int","int","mode_t"
|
||||
"fchown","unistd.h","","int","int","uid_t","gid_t"
|
||||
"fcntl","fcntl.h","","int","int","int","...","int"
|
||||
"fork","unistd.h","defined(CONFIG_ARCH_HAVE_FORK)","pid_t"
|
||||
"fs_fdopen","nuttx/fs/fs.h","defined(CONFIG_FILE_STREAM)","int","int","int","FAR struct tcb_s *","FAR struct file_struct **"
|
||||
"fstat","sys/stat.h","","int","int","FAR struct stat *"
|
||||
"fstatfs","sys/statfs.h","","int","int","FAR struct statfs *"
|
||||
|
@ -204,7 +205,6 @@
|
|||
"unlink","unistd.h","!defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char *"
|
||||
"unsetenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int","FAR const char *"
|
||||
"utimens","sys/stat.h","","int","FAR const char *","const struct timespec [2]|FAR const struct timespec *"
|
||||
"vfork","unistd.h","defined(CONFIG_SCHED_WAITPID) && defined(CONFIG_ARCH_HAVE_VFORK)","pid_t"
|
||||
"wait","sys/wait.h","defined(CONFIG_SCHED_WAITPID) && defined(CONFIG_SCHED_HAVE_PARENT)","pid_t","FAR int *"
|
||||
"waitid","sys/wait.h","defined(CONFIG_SCHED_WAITPID) && defined(CONFIG_SCHED_HAVE_PARENT)","int","idtype_t","id_t"," FAR siginfo_t *","int"
|
||||
"waitpid","sys/wait.h","defined(CONFIG_SCHED_WAITPID)","pid_t","pid_t","FAR int *","int"
|
||||
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
Loading…
Reference in a new issue