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