From 3524f4b9ce4e1c12dd30dda7cb9a161406485ee6 Mon Sep 17 00:00:00 2001 From: guoshichao Date: Sun, 16 Jul 2023 11:34:17 +0800 Subject: [PATCH] libs/libc/fork: add lib_fork implementation 1. add lib_fork api in libs/libc, we need a fork() api to implement the fork relative method, such as pthread_atfork 2. rename the assembly fork entry function name to up_fork(), and rename the up_fork() to arch specific name, such as sim_fork()/arm_fork()/mips_fork() etc. Signed-off-by: guoshichao --- arch/arm/src/common/arm_fork.c | 12 ++--- arch/arm/src/common/gnu/fork.S | 24 +++++----- arch/arm/src/common/iar/fork.S | 24 +++++----- arch/arm64/src/common/arm64_fork.c | 11 ++--- arch/arm64/src/common/arm64_fork_func.S | 18 ++++---- arch/ceva/src/common/ceva_fork.c | 13 +++--- arch/ceva/src/xc5/fork.S | 26 ++++++----- arch/ceva/src/xm6/fork.S | 26 ++++++----- arch/mips/src/mips32/fork.S | 30 +++++++------ arch/mips/src/mips32/mips_fork.c | 13 +++--- arch/risc-v/src/common/fork.S | 22 +++++----- arch/risc-v/src/common/riscv_fork.c | 13 +++--- arch/sim/src/sim/sim_fork.c | 12 ++--- arch/sim/src/sim/sim_fork_arm.S | 24 +++++----- arch/sim/src/sim/sim_fork_arm64.S | 24 +++++----- arch/sim/src/sim/sim_fork_x86.S | 20 +++++---- arch/sim/src/sim/sim_fork_x86_64.S | 22 +++++----- include/nuttx/arch.h | 17 ++++++++ include/sys/syscall_lookup.h | 2 +- libs/libc/unistd/CMakeLists.txt | 7 +++ libs/libc/unistd/Make.defs | 1 + libs/libc/unistd/lib_fork.c | 58 +++++++++++++++++++++++++ syscall/syscall.csv | 2 +- 23 files changed, 265 insertions(+), 156 deletions(-) create mode 100644 libs/libc/unistd/lib_fork.c diff --git a/arch/arm/src/common/arm_fork.c b/arch/arm/src/common/arm_fork.c index 9f99da3c66..3f50fbe8be 100644 --- a/arch/arm/src/common/arm_fork.c +++ b/arch/arm/src/common/arm_fork.c @@ -44,7 +44,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: up_fork + * Name: arm_fork * * Description: * The fork() function has the same effect as posix fork(), except that the @@ -57,8 +57,8 @@ * The overall sequence is: * * 1) User code calls fork(). fork() collects context information and - * transfers control up up_fork(). - * 2) up_fork() and calls nxtask_setup_fork(). + * transfers control up arm_fork(). + * 2) arm_fork() and calls nxtask_setup_fork(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. * This consists of: * - Allocation of the child task's TCB. @@ -67,10 +67,10 @@ * - Allocate and initialize the stack * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state()) - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) arm_fork() provides any additional operating context. arm_fork must: * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) arm_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * nxtask_abort_fork() may be called if an error occurs between steps 3 and @@ -87,7 +87,7 @@ * ****************************************************************************/ -pid_t up_fork(const struct fork_s *context) +pid_t arm_fork(const struct fork_s *context) { struct tcb_s *parent = this_task(); struct task_tcb_s *child; diff --git a/arch/arm/src/common/gnu/fork.S b/arch/arm/src/common/gnu/fork.S index 8ebb9cbb54..7697561a27 100644 --- a/arch/arm/src/common/gnu/fork.S +++ b/arch/arm/src/common/gnu/fork.S @@ -34,9 +34,11 @@ ****************************************************************************/ /**************************************************************************** - * Name: fork + * Name: up_fork * * Description: + * The up_fork() function is the base of fork() function that provided in + * libc, and fork() is implemented as a wrapper of up_fork() function. * The fork() function has the same effect as posix fork(), except that the * behavior is undefined if the process created by fork() either modifies * any data other than a variable of type pid_t used to store the return @@ -49,7 +51,7 @@ * * 1) User code calls fork(). fork() collects context information and * transfers control up up_fork(). - * 2) up_fork() and calls nxtask_setup_fork(). + * 2) arm_fork() and calls nxtask_setup_fork(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. * This consists of: * - Allocation of the child task's TCB. @@ -58,10 +60,10 @@ * - Allocate and initialize the stack * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state()) - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) arm_fork() provides any additional operating context. arm_fork must: * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) arm_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * Input Parameters: @@ -75,10 +77,10 @@ * ****************************************************************************/ - .globl fork - .type fork, function + .globl up_fork + .type up_fork, function -fork: +up_fork: /* Create a stack frame */ mov r0, sp /* Save the value of the stack on entry */ @@ -97,12 +99,12 @@ fork: mov r5, lr /* Copy lr to a low register */ stmia r1!, {r0,r5} /* Save sp and lr in the structure */ - /* Then, call up_fork(), passing it a pointer to the stack structure */ + /* Then, call arm_fork(), passing it a pointer to the stack structure */ mov r0, sp - bl up_fork + bl arm_fork - /* Recover r4-r7 that were destroyed before up_fork was called */ + /* Recover r4-r7 that were destroyed before arm_fork was called */ mov r1, sp ldmia r1!, {r4-r7} @@ -114,5 +116,5 @@ fork: add sp, sp, #FORK_SIZEOF bx lr - .size fork, .-fork + .size up_fork, .-up_fork .end diff --git a/arch/arm/src/common/iar/fork.S b/arch/arm/src/common/iar/fork.S index b94ff57f45..bdff61c3dc 100644 --- a/arch/arm/src/common/iar/fork.S +++ b/arch/arm/src/common/iar/fork.S @@ -26,7 +26,7 @@ #include "arm_fork.h" - MODULE fork + MODULE up_fork SECTION .text:CODE:NOROOT(2) /**************************************************************************** @@ -37,17 +37,19 @@ * Public Symbols ****************************************************************************/ - PUBLIC fork - EXTERN up_fork + PUBLIC up_fork + EXTERN arm_fork /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: fork + * Name: up_fork * * Description: + * The up_fork() function is the base of fork() function that provided in + * libc, and fork() is implemented as a wrapper of up_fork() function. * The fork() function has the same effect as posix fork(), except that the * behavior is undefined if the process created by fork() either modifies * any data other than a variable of type pid_t used to store the return @@ -60,7 +62,7 @@ * * 1) User code calls fork(). fork() collects context information and * transfers control up up_fork(). - * 2) up_fork() and calls nxtask_setup_fork(). + * 2) arm_fork() and calls nxtask_setup_fork(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. * This consists of: * - Allocation of the child task's TCB. @@ -69,10 +71,10 @@ * - Allocate and initialize the stack * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state()) - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) arm_fork() provides any additional operating context. arm_fork must: * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) arm_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * Input Parameters: @@ -88,7 +90,7 @@ THUMB -fork: +up_fork: /* Create a stack frame */ mov r0, sp /* Save the value of the stack on entry */ @@ -113,12 +115,12 @@ fork: /* Floating point registers (not yet) */ - /* Then, call up_fork(), passing it a pointer to the stack structure */ + /* Then, call arm_fork(), passing it a pointer to the stack structure */ mov r0, sp - bl up_fork + bl arm_fork - /* Release the stack data and return the value returned by up_fork */ + /* Release the stack data and return the value returned by arm_fork */ ldr lr, [sp, #FORK_LR_OFFSET] add sp, sp, #FORK_SIZEOF diff --git a/arch/arm64/src/common/arm64_fork.c b/arch/arm64/src/common/arm64_fork.c index b5124f186a..aea3d57044 100644 --- a/arch/arm64/src/common/arm64_fork.c +++ b/arch/arm64/src/common/arm64_fork.c @@ -88,8 +88,8 @@ void arm64_fork_fpureg_save(struct fork_s *context) * The overall sequence is: * * 1) User code calls fork(). fork() collects context information and - * transfers control up up_fork(). - * 2) up_fork() and calls nxtask_setup_fork(). + * transfers control up arm64_fork(). + * 2) arm64_fork() and calls nxtask_setup_fork(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. * This consists of: * - Allocation of the child task's TCB. @@ -98,10 +98,11 @@ void arm64_fork_fpureg_save(struct fork_s *context) * - Allocate and initialize the stack * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state()) - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) arm64_fork() provides any additional operating context. arm64_fork + * must: * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) arm64_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * nxtask_abort_fork() may be called if an error occurs between steps 3 and @@ -118,7 +119,7 @@ void arm64_fork_fpureg_save(struct fork_s *context) * ****************************************************************************/ -pid_t up_fork(const struct fork_s *context) +pid_t arm64_fork(const struct fork_s *context) { struct tcb_s *parent = this_task(); struct task_tcb_s *child; diff --git a/arch/arm64/src/common/arm64_fork_func.S b/arch/arm64/src/common/arm64_fork_func.S index 093d781bc4..789802348e 100644 --- a/arch/arm64/src/common/arm64_fork_func.S +++ b/arch/arm64/src/common/arm64_fork_func.S @@ -42,6 +42,8 @@ * Name: fork * * Description: + * The up_fork() function is the base of fork() function that provided in + * libc, and fork() is implemented as a wrapper of up_fork() function. * The fork() function has the same effect as posix fork(), except that the * behavior is undefined if the process created by fork() either modifies * any data other than a variable of type pid_t used to store the return @@ -54,7 +56,7 @@ * * 1) User code calls fork(). fork() collects context information and * transfers control up up_fork(). - * 2) up_fork() and calls nxtask_setup_fork(). + * 2) arm64_fork() and calls nxtask_setup_fork(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. * This consists of: * - Allocation of the child task's TCB. @@ -63,10 +65,10 @@ * - Allocate and initialize the stack * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state()) - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) arm64_fork() provides any additional operating context. arm64_fork must: * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) arm64_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * Input Parameters: @@ -80,8 +82,8 @@ * ****************************************************************************/ -GTEXT(fork) -SECTION_FUNC(text, fork) +GTEXT(up_fork) +SECTION_FUNC(text, up_fork) /* Create a stack frame */ mov x0, sp /* Save the value of the stack on entry */ @@ -118,13 +120,13 @@ SECTION_FUNC(text, fork) ldp x0, x30, [sp], #16 #endif - /* Then, call up_fork(), passing it a pointer to the stack structure */ + /* Then, call arm64_fork(), passing it a pointer to the stack structure */ mov x0, sp mov x1, #0 - bl up_fork + bl arm64_fork - /* Release the stack data and return the value returned by up_fork */ + /* Release the stack data and return the value returned by arm64_fork */ add sp, sp, #8 * FORK_REGS_SIZE ldp x29, x30, [sp] diff --git a/arch/ceva/src/common/ceva_fork.c b/arch/ceva/src/common/ceva_fork.c index 54e30cc39c..c03bf4c47a 100644 --- a/arch/ceva/src/common/ceva_fork.c +++ b/arch/ceva/src/common/ceva_fork.c @@ -38,7 +38,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: up_fork + * Name: ceva_fork * * Description: * The fork() function has the same effect as posix fork(), except that the @@ -51,8 +51,8 @@ * The overall sequence is: * * 1) User code calls fork(). fork() collects context information and - * transfers control up up_fork(). - * 2) up_fork()and calls nxtask_forksetup(). + * transfers control up ceva_fork(). + * 2) ceva_fork()and calls nxtask_forksetup(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. * This consists of: * - Allocation of the child task's TCB. @@ -60,11 +60,12 @@ * - Configuration of environment variables * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state() - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) ceva_fork() provides any additional operating context. ceva_fork + * must: * - Allocate and initialize the stack * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) ceva_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * nxtask_abort_fork() may be called if an error occurs between steps 3 & 6. @@ -80,7 +81,7 @@ * ****************************************************************************/ -pid_t up_fork(const uint32_t *regs) +pid_t ceva_fork(const uint32_t *regs) { #ifdef CONFIG_SCHED_WAITPID struct tcb_s *parent = this_task(); diff --git a/arch/ceva/src/xc5/fork.S b/arch/ceva/src/xc5/fork.S index e7340f1356..a8aecc43df 100644 --- a/arch/ceva/src/xc5/fork.S +++ b/arch/ceva/src/xc5/fork.S @@ -32,16 +32,18 @@ ****************************************************************************/ .file "fork.S" - .extern _up_fork + .extern ceva_fork /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: fork + * Name: up_fork * * Description: + * The up_fork() function is the base of fork() function that provided in + * libc, and fork() is implemented as a wrapper of up_fork() function. * The fork() function has the same effect as posix fork(), except that the behavior is * undefined if the process created by fork() either modifies any data other than * a variable of type pid_t used to store the return value from fork(), or returns @@ -53,7 +55,7 @@ * * 1) User code calls fork(). fork() collects context information and * transfers control up up_fork(). - * 2) up_fork()and calls nxtask_forksetup(). + * 2) ceva_fork()and calls nxtask_forksetup(). * 3) task_forksetup() allocates and configures the child task's TCB. This * consists of: * - Allocation of the child task's TCB. @@ -61,11 +63,11 @@ * - Configuration of environment variables * - Setup the intput parameters for the task. * - Initialization of the TCB (including call to up_initial_state() - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) ceva_fork() provides any additional operating context. ceva_fork must: * - Allocate and initialize the stack * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_forkstart() + * 5) ceva_fork() then calls nxtask_forkstart() * 6) nxtask_forkstart() then executes the child thread. * * Input Paremeters: @@ -80,10 +82,10 @@ ****************************************************************************/ .text - .public _fork - .func_start 3 _fork + .public up_fork + .func_start 3 up_fork -_fork: +up_fork: /* Create a stack frame */ subs sp, #XCPTCONTEXT_SIZE, sp @@ -94,19 +96,19 @@ _fork: mov sp, a1 trap - /* Then, call up_fork(), passing it a pointer to the stack structure */ + /* Then, call ceva_fork(), passing it a pointer to the stack structure */ mov sp, a0 nop push {dw} retreg - callr {t} _up_fork + callr {t} ceva_fork pop {dw} retreg nop - /* Release the stack data and return the value returned by up_fork */ + /* Release the stack data and return the value returned by ceva_fork */ adds sp, #XCPTCONTEXT_SIZE, sp ret - .func_end 3 _fork + .func_end 3 up_fork diff --git a/arch/ceva/src/xm6/fork.S b/arch/ceva/src/xm6/fork.S index 0098bdef18..f6d5a54c33 100644 --- a/arch/ceva/src/xm6/fork.S +++ b/arch/ceva/src/xm6/fork.S @@ -42,16 +42,18 @@ ****************************************************************************/ .file "fork.S" - .extern _up_fork + .extern up_fork /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: fork + * Name: up_fork * * Description: + * The up_fork() function is the base of fork() function that provided in + * libc, and fork() is implemented as a wrapper of up_fork() function. * The fork() function has the same effect as posix fork(), except that the behavior is * undefined if the process created by fork() either modifies any data other than * a variable of type pid_t used to store the return value from fork(), or returns @@ -63,7 +65,7 @@ * * 1) User code calls fork(). fork() collects context information and * transfers control up up_fork(). - * 2) up_fork()and calls nxtask_forksetup(). + * 2) ceva_fork()and calls nxtask_forksetup(). * 3) task_forksetup() allocates and configures the child task's TCB. This * consists of: * - Allocation of the child task's TCB. @@ -71,11 +73,11 @@ * - Configuration of environment variables * - Setup the intput parameters for the task. * - Initialization of the TCB (including call to up_initial_state() - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) ceva_fork() provides any additional operating context. ceva_fork must: * - Allocate and initialize the stack * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_forkstart() + * 5) ceva_fork() then calls nxtask_forkstart() * 6) nxtask_forkstart() then executes the child thread. * * Input Paremeters: @@ -90,10 +92,10 @@ ****************************************************************************/ .text - .public _fork - .func_start 3 _fork + .public up_fork + .func_start 3 up_fork -_fork: +up_fork: /* Create a stack frame */ modr (sp.ui).ui +#-XCPTCONTEXT_SIZE /* Allocate the structure on the stack */ @@ -104,18 +106,18 @@ _fork: mov sp.ui, r1.ui trap {t0} - /* Then, call up_fork(), passing it a pointer to the stack structure */ + /* Then, call ceva_fork(), passing it a pointer to the stack structure */ mov sp.ui, r0.ui nop push retreg.ui - callr #_up_fork, ?prx.b + callr #ceva_fork, ?prx.b pop retreg.ui nop - /* Release the stack data and return the value returned by up_fork */ + /* Release the stack data and return the value returned by ceva_fork */ modr (sp.ui).ui +#XCPTCONTEXT_SIZE ret ?prx.b - .func_end 3 _fork + .func_end 3 up_fork diff --git a/arch/mips/src/mips32/fork.S b/arch/mips/src/mips32/fork.S index 9f13d5390d..0399785e37 100644 --- a/arch/mips/src/mips32/fork.S +++ b/arch/mips/src/mips32/fork.S @@ -35,16 +35,18 @@ ************************************************************************************/ .file "fork.S" - .globl up_fork + .globl mips_fork /************************************************************************************ * Public Functions ************************************************************************************/ /************************************************************************************ - * Name: fork + * Name: up_fork * * Description: + * The up_fork() function is the base of fork() function that provided in + * libc, and fork() is implemented as a wrapper of up_fork() function. * The fork() function has the same effect as posix fork(), except that the behavior is * undefined if the process created by fork() either modifies any data other than * a variable of type pid_t used to store the return value from fork(), or returns @@ -56,7 +58,7 @@ * * 1) User code calls fork(). fork() collects context information and * transfers control up up_fork(). - * 2) up_fork() and calls nxtask_setup_fork(). + * 2) mips_fork() and calls nxtask_setup_fork(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. This * consists of: * - Allocation of the child task's TCB. @@ -65,10 +67,10 @@ * - Allocate and initialize the stack * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state()) - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) mips_fork() provides any additional operating context. mips_fork must: * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) mips_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * Input Parameters: @@ -84,15 +86,15 @@ .text .align 2 - .globl fork - .type fork, function + .globl up_fork + .type up_fork, function .set nomips16 #ifdef CONFIG_MIPS_MICROMIPS .set micromips #endif - .ent fork + .ent up_fork -fork: +up_fork: /* Create a stack frame */ move $t0, $sp /* Save the value of the stack on entry */ @@ -126,17 +128,17 @@ fork: /* Floating point registers (not yet) */ - /* Then, call up_fork(), passing it a pointer to the stack structure */ + /* Then, call mips_fork(), passing it a pointer to the stack structure */ move $a0, $sp - jal up_fork + jal mips_fork nop - /* Release the stack data and return the value returned by up_fork */ + /* Release the stack data and return the value returned by mips_fork */ lw $ra, FORK_RA_OFFSET($sp) addiu $sp, $sp, FORK_SIZEOF j $ra - .end fork - .size fork, .-fork + .end up_fork + .size up_fork, .-up_fork diff --git a/arch/mips/src/mips32/mips_fork.c b/arch/mips/src/mips32/mips_fork.c index dccab0e04f..dc4c91bb35 100644 --- a/arch/mips/src/mips32/mips_fork.c +++ b/arch/mips/src/mips32/mips_fork.c @@ -43,7 +43,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: up_fork + * Name: mips_fork * * Description: * The fork() function has the same effect as posix fork(), except that the @@ -56,8 +56,8 @@ * The overall sequence is: * * 1) User code calls fork(). fork() collects context information and - * transfers control up up_fork(). - * 2) up_fork() and calls nxtask_setup_fork(). + * transfers control up mips_fork(). + * 2) mips_fork() and calls nxtask_setup_fork(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. * this consists of: * - Allocation of the child task's TCB. @@ -66,10 +66,11 @@ * - Allocate and initialize the stack * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state()) - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) mips_fork() provides any additional operating context. mips_fork + * must: * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) mips_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * nxtask_abort_fork() may be called if an error occurs between steps 3 @@ -86,7 +87,7 @@ * ****************************************************************************/ -pid_t up_fork(const struct fork_s *context) +pid_t mips_fork(const struct fork_s *context) { struct tcb_s *parent = this_task(); struct task_tcb_s *child; diff --git a/arch/risc-v/src/common/fork.S b/arch/risc-v/src/common/fork.S index f627fb47c7..37d4bc9cfe 100644 --- a/arch/risc-v/src/common/fork.S +++ b/arch/risc-v/src/common/fork.S @@ -36,8 +36,8 @@ ****************************************************************************/ .file "fork.S" + .globl riscv_fork .globl up_fork - .globl fork /**************************************************************************** * Public Functions @@ -47,6 +47,8 @@ * Name: fork * * Description: + * The up_fork() function is the base of fork() function that provided in + * libc, and fork() is implemented as a wrapper of up_fork() function. * The fork() function has the same effect as posix fork(), except that the * behavior is undefined if the process created by fork() either modifies * any data other than a variable of type pid_t used to store the return @@ -59,7 +61,7 @@ * * 1) User code calls fork(). fork() collects context information and * transfers control up up_fork(). - * 2) up_fork() and calls nxtask_setup_fork(). + * 2) riscv_fork() and calls nxtask_setup_fork(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. * This consists of: * - Allocation of the child task's TCB. @@ -68,10 +70,10 @@ * - Allocate and initialize the stack * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state()) - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) riscv_fork() provides any additional operating context. riscv_fork must: * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) riscv_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * Input Parameters: @@ -85,9 +87,9 @@ * ****************************************************************************/ -.type fork, function +.type up_fork, function -fork: +up_fork: /* Create a stack frame */ addi sp, sp, -FORK_SIZEOF @@ -136,16 +138,16 @@ fork: FSTORE fs11, FORK_FS11_OFFSET(sp) #endif - /* Then, call up_fork(), passing it a pointer to the stack frame */ + /* Then, call riscv_fork(), passing it a pointer to the stack frame */ mv a0, sp - call up_fork + call riscv_fork - /* Release the stack frame and return the value returned by up_fork */ + /* Release the stack frame and return the value returned by riscv_fork */ REGLOAD x1, FORK_RA_OFFSET(sp) addi sp, sp, FORK_SIZEOF ret - .size fork, .-fork + .size up_fork, .-up_fork .end diff --git a/arch/risc-v/src/common/riscv_fork.c b/arch/risc-v/src/common/riscv_fork.c index ad69e10516..53ac2f3740 100644 --- a/arch/risc-v/src/common/riscv_fork.c +++ b/arch/risc-v/src/common/riscv_fork.c @@ -52,7 +52,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: up_fork + * Name: riscv_fork * * Description: * The fork() function has the same effect as posix fork(), except that the @@ -65,8 +65,8 @@ * The overall sequence is: * * 1) User code calls fork(). fork() collects context information and - * transfers control up up_fork(). - * 2) up_fork() and calls nxtask_setup_fork(). + * transfers control up riscv_fork(). + * 2) riscv_fork() and calls nxtask_setup_fork(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. * This consists of: * - Allocation of the child task's TCB. @@ -75,10 +75,11 @@ * - Allocate and initialize the stack * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state()) - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) riscv_fork() provides any additional operating context. riscv_fork + * must: * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) riscv_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * nxtask_abort_fork() may be called if an error occurs between steps 3 @@ -97,7 +98,7 @@ #ifdef CONFIG_ARCH_HAVE_FORK -pid_t up_fork(const struct fork_s *context) +pid_t riscv_fork(const struct fork_s *context) { struct tcb_s *parent = this_task(); struct task_tcb_s *child; diff --git a/arch/sim/src/sim/sim_fork.c b/arch/sim/src/sim/sim_fork.c index a999764201..ec14cae37f 100644 --- a/arch/sim/src/sim/sim_fork.c +++ b/arch/sim/src/sim/sim_fork.c @@ -43,7 +43,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: up_fork + * Name: sim_fork * * Description: * The fork() function has the same effect as posix fork(), except that the @@ -56,8 +56,8 @@ * The overall sequence is: * * 1) User code calls fork(). fork() collects context information and - * transfers control up up_fork(). - * 2) up_fork() and calls nxtask_setup_fork(). + * transfers control up sim_fork(). + * 2) sim_fork() and calls nxtask_setup_fork(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. * This consists of: * - Allocation of the child task's TCB. @@ -66,10 +66,10 @@ * - Allocate and initialize the stack * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state()) - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) sim_fork() provides any additional operating context. sim_fork must: * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) sim_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * nxtask_abort_fork() may be called if an error occurs between steps 3 and @@ -86,7 +86,7 @@ #ifdef CONFIG_SIM_ASAN nosanitize_address #endif -pid_t up_fork(const xcpt_reg_t *context) +pid_t sim_fork(const xcpt_reg_t *context) { struct tcb_s *parent = this_task(); struct task_tcb_s *child; diff --git a/arch/sim/src/sim/sim_fork_arm.S b/arch/sim/src/sim/sim_fork_arm.S index d246915bc8..42ac56b094 100644 --- a/arch/sim/src/sim/sim_fork_arm.S +++ b/arch/sim/src/sim/sim_fork_arm.S @@ -34,16 +34,18 @@ ************************************************************************************/ .file "fork.S" - .globl up_fork + .globl sim_fork /************************************************************************************ * Public Functions ************************************************************************************/ /************************************************************************************ - * Name: fork + * Name: up_fork * * Description: + * The up_fork() function is the base of fork() function that provided in + * libc, and fork() is implemented as a wrapper of up_fork() function. * The fork() function has the same effect as posix fork(), except that the behavior is * undefined if the process created by fork() either modifies any data other than * a variable of type pid_t used to store the return value from fork(), or returns @@ -54,8 +56,8 @@ * context as an argument. The overall sequence is: * * 1) User code calls fork(). fork() collects context information and - * transfers control up up_fork(). - * 2) up_fork() and calls nxtask_setup_fork(). + * transfers control up sim_fork(). + * 2) sim_fork() and calls nxtask_setup_fork(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. This * consists of: * - Allocation of the child task's TCB. @@ -64,10 +66,10 @@ * - Allocate and initialize the stack * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state()) - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) sim_fork() provides any additional operating context. sim_fork must: * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) sim_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * Input Parameters: @@ -82,18 +84,18 @@ ************************************************************************************/ .text - .globl fork - .type fork, @function -fork: + .globl up_fork + .type up_fork, @function +up_fork: sub sp, sp, #XCPTCONTEXT_SIZE mov r0, sp bl setjmp subs r0, #1 jz child - bl up_fork + bl sim_fork child: add sp, sp, #XCPTCONTEXT_SIZE ret - .size fork, . - fork + .size up_fork, . - up_fork .end diff --git a/arch/sim/src/sim/sim_fork_arm64.S b/arch/sim/src/sim/sim_fork_arm64.S index 075833ab36..0055c2fd02 100644 --- a/arch/sim/src/sim/sim_fork_arm64.S +++ b/arch/sim/src/sim/sim_fork_arm64.S @@ -42,7 +42,7 @@ ***************************************************************************/ .file "up_fork_arm64.S" - .globl SYMBOL(up_fork) + .globl SYMBOL(sim_fork) .globl SYMBOL(setjmp) /**************************************************************************** @@ -50,9 +50,11 @@ ***************************************************************************/ /**************************************************************************** - * Name: fork + * Name: up_fork * * Description: + * The up_fork() function is the base of fork() function that provided in + * libc, and fork() is implemented as a wrapper of up_fork() function. * The fork() function has the same effect as posix fork(), except that the * behavior is undefined if the process created by fork() either modifies * any data other than a variable of type pid_t used to store the return @@ -60,12 +62,12 @@ * called, or calls any other function before successfully calling _exit() * or one of the exec family of functions. * - * This thin layer implements fork by simply calling up_fork() with the + * This thin layer implements fork by simply calling sim_fork() with the * fork() context as an argument. The overall sequence is: * * 1) User code calls fork(). fork() collects context information and - * transfers control up up_fork(). - * 2) up_fork() and calls nxtask_setup_fork(). + * transfers control up sim_fork(). + * 2) sim_fork() and calls nxtask_setup_fork(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. * This consists of: * - Allocation of the child task's TCB. @@ -74,10 +76,10 @@ * - Allocate and initialize the stack * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state()) - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) sim_fork() provides any additional operating context. sim_fork must: * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) sim_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * Input Parameters: @@ -92,10 +94,10 @@ ***************************************************************************/ .text - .globl SYMBOL(fork) + .globl SYMBOL(up_fork) .align 4 -SYMBOL(fork): +SYMBOL(up_fork): stp x29, x30, [sp] /* save FP/LR register */ sub sp, sp, #XCPTCONTEXT_SIZE /* area from stack for setjmp() */ @@ -106,8 +108,8 @@ SYMBOL(fork): subs x0, x0, #1 /* 0: parent / 1: child */ cbz x0, 1f /* child --> return */ - mov x0, sp /* pass stack area to up_fork() */ - bl SYMBOL(up_fork) /* further process task creation */ + mov x0, sp /* pass stack area to sim_fork() */ + bl SYMBOL(sim_fork) /* further process task creation */ 1: add sp, sp, #XCPTCONTEXT_SIZE /* release area from stack */ diff --git a/arch/sim/src/sim/sim_fork_x86.S b/arch/sim/src/sim/sim_fork_x86.S index 91b6ab309e..a06b137d87 100644 --- a/arch/sim/src/sim/sim_fork_x86.S +++ b/arch/sim/src/sim/sim_fork_x86.S @@ -49,9 +49,11 @@ ************************************************************************************/ /************************************************************************************ - * Name: fork + * Name: up_fork * * Description: + * The up_fork() function is the base of fork() function that provided in + * libc, and fork() is implemented as a wrapper of up_fork() function. * The fork() function has the same effect as posix fork(), except that the behavior is * undefined if the process created by fork() either modifies any data other than * a variable of type pid_t used to store the return value from fork(), or returns @@ -63,7 +65,7 @@ * * 1) User code calls fork(). fork() collects context information and * transfers control up up_fork(). - * 2) up_fork() and calls nxtask_setup_fork(). + * 2) sim_fork() and calls nxtask_setup_fork(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. This * consists of: * - Allocation of the child task's TCB. @@ -72,10 +74,10 @@ * - Allocate and initialize the stack * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state()) - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) sim_fork() provides any additional operating context. sim_fork must: * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) sim_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * Input Parameters: @@ -90,22 +92,22 @@ ************************************************************************************/ .text - .globl SYMBOL(fork) + .globl SYMBOL(up_fork) #ifdef __ELF__ - .type SYMBOL(fork), @function + .type SYMBOL(up_fork), @function #endif -SYMBOL(fork): +SYMBOL(up_fork): sub $XCPTCONTEXT_SIZE, %esp push %esp call SYMBOL(setjmp) sub $1, %eax jz child - call SYMBOL(up_fork) + call SYMBOL(sim_fork) child: add $XCPTCONTEXT_SIZE+4, %esp ret #ifdef __ELF__ - .size SYMBOL(fork), . - SYMBOL(fork) + .size SYMBOL(up_fork), . - SYMBOL(up_fork) #endif diff --git a/arch/sim/src/sim/sim_fork_x86_64.S b/arch/sim/src/sim/sim_fork_x86_64.S index 1af28f3e16..165fe82ac4 100644 --- a/arch/sim/src/sim/sim_fork_x86_64.S +++ b/arch/sim/src/sim/sim_fork_x86_64.S @@ -42,16 +42,18 @@ ************************************************************************************/ .file "fork.S" - .globl up_fork + .globl sim_fork /************************************************************************************ * Public Functions ************************************************************************************/ /************************************************************************************ - * Name: fork + * Name: up_fork * * Description: + * The up_fork() function is the base of fork() function that provided in + * libc, and fork() is implemented as a wrapper of up_fork() function. * The fork() function has the same effect as posix fork(), except that the behavior is * undefined if the process created by fork() either modifies any data other than * a variable of type pid_t used to store the return value from fork(), or returns @@ -63,7 +65,7 @@ * * 1) User code calls fork(). fork() collects context information and * transfers control up up_fork(). - * 2) up_fork() and calls nxtask_setup_fork(). + * 2) sim_fork() and calls nxtask_setup_fork(). * 3) nxtask_setup_fork() allocates and configures the child task's TCB. This * consists of: * - Allocation of the child task's TCB. @@ -72,10 +74,10 @@ * - Allocate and initialize the stack * - Setup the input parameters for the task. * - Initialization of the TCB (including call to up_initial_state()) - * 4) up_fork() provides any additional operating context. up_fork must: + * 4) sim_fork() provides any additional operating context. sim_fork must: * - Initialize special values in any CPU registers that were not * already configured by up_initial_state() - * 5) up_fork() then calls nxtask_start_fork() + * 5) sim_fork() then calls nxtask_start_fork() * 6) nxtask_start_fork() then executes the child thread. * * Input Parameters: @@ -90,12 +92,12 @@ ************************************************************************************/ .text - .globl SYMBOL(fork) + .globl SYMBOL(up_fork) #ifdef __ELF__ - .type SYMBOL(fork), @function + .type SYMBOL(up_fork), @function #endif -SYMBOL(fork): +SYMBOL(up_fork): sub $XCPTCONTEXT_SIZE, %rsp #ifdef CONFIG_SIM_X8664_MICROSOFT mov %rsp, %rcx @@ -107,10 +109,10 @@ SYMBOL(fork): sub $1, %eax jz child - call SYMBOL(up_fork) + call SYMBOL(sim_fork) child: add $XCPTCONTEXT_SIZE, %rsp ret #ifdef __ELF__ - .size SYMBOL(fork), . - SYMBOL(fork) + .size SYMBOL(up_fork), . - SYMBOL(up_fork) #endif diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index ee7328b7a4..2beb586d50 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -168,6 +168,23 @@ extern initializer_t _einit[]; * logic from architecture-specific code. ****************************************************************************/ +/**************************************************************************** + * Name: up_fork + * + * Description: + * The up_fork() function is the base of fork() function that provided in + * libc, and fork() is implemented as a wrapper of up_fork() function. + * + * Returned Value: + * Upon successful completion, up_fork() returns 0 to the child process + * and returns the process ID of the child process to the parent process. + * Otherwise, -1 is returned to the parent, no child process is created, + * and errno is set to indicate the error. + * + ****************************************************************************/ + +pid_t up_fork(void); + /**************************************************************************** * Name: up_initialize * diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h index 1babc16e3a..6b18801f2b 100644 --- a/include/sys/syscall_lookup.h +++ b/include/sys/syscall_lookup.h @@ -115,7 +115,7 @@ SYSCALL_LOOKUP(task_setcancelstate, 2) /* The following can be individually enabled */ #ifdef CONFIG_ARCH_HAVE_FORK - SYSCALL_LOOKUP(fork, 0) + SYSCALL_LOOKUP(up_fork, 0) #endif #ifdef CONFIG_SCHED_WAITPID diff --git a/libs/libc/unistd/CMakeLists.txt b/libs/libc/unistd/CMakeLists.txt index 25a3d4d843..8783b8225e 100644 --- a/libs/libc/unistd/CMakeLists.txt +++ b/libs/libc/unistd/CMakeLists.txt @@ -80,4 +80,11 @@ if(NOT CONFIG_DISABLE_MOUNTPOINTS) list(APPEND SRCS lib_truncate.c lib_posix_fallocate.c) endif() +if(CONFIG_ARCH_HAVE_FORK) + list(APPEND SRCS lib_fork.c) + if(CONFIG_SCHED_WAITPID) + list(APPEND SRCS lib_vfork.c) + endif() +endif() + target_sources(c PRIVATE ${SRCS}) diff --git a/libs/libc/unistd/Make.defs b/libs/libc/unistd/Make.defs index d480781929..66ba8184fe 100644 --- a/libs/libc/unistd/Make.defs +++ b/libs/libc/unistd/Make.defs @@ -49,6 +49,7 @@ CSRCS += lib_truncate.c lib_posix_fallocate.c endif ifeq ($(CONFIG_ARCH_HAVE_FORK),y) +CSRCS += lib_fork.c ifeq ($(CONFIG_SCHED_WAITPID),y) CSRCS += lib_vfork.c endif diff --git a/libs/libc/unistd/lib_fork.c b/libs/libc/unistd/lib_fork.c new file mode 100644 index 0000000000..e1a6463990 --- /dev/null +++ b/libs/libc/unistd/lib_fork.c @@ -0,0 +1,58 @@ +/**************************************************************************** + * libs/libc/unistd/lib_fork.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 +#include + +#include + +#if defined(CONFIG_ARCH_HAVE_FORK) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fork + * + * Description: + * The fork() function is a wrapper of up_fork() syscall + * + * Returned Value: + * Upon successful completion, fork() returns 0 to the child process and + * returns the process ID of the child process to the parent process. + * Otherwise, -1 is returned to the parent, no child process is created, + * and errno is set to indicate the error. + * + ****************************************************************************/ + +pid_t fork(void) +{ + pid_t pid; + pid = up_fork(); + + return pid; +} + +#endif /* CONFIG_ARCH_HAVE_FORK */ diff --git a/syscall/syscall.csv b/syscall/syscall.csv index b680c40311..7428e37f7d 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -29,7 +29,6 @@ "fchmod","sys/stat.h","","int","int","mode_t" "fchown","unistd.h","","int","int","uid_t","gid_t" "fcntl","fcntl.h","","int","int","int","...","int" -"fork","unistd.h","defined(CONFIG_ARCH_HAVE_FORK)","pid_t" "fs_fdopen","nuttx/fs/fs.h","defined(CONFIG_FILE_STREAM)","int","int","int","FAR struct tcb_s *","FAR struct file_struct **" "fstat","sys/stat.h","","int","int","FAR struct stat *" "fstatfs","sys/statfs.h","","int","int","FAR struct statfs *" @@ -204,6 +203,7 @@ "umount2","sys/mount.h","!defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char *","unsigned int" "unlink","unistd.h","!defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char *" "unsetenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int","FAR const char *" +"up_fork","nuttx/arch.h","defined(CONFIG_ARCH_HAVE_FORK)","pid_t" "utimens","sys/stat.h","","int","FAR const char *","const struct timespec [2]|FAR const struct timespec *" "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"