blob: 790aa8cd43f42199676b6b20ead32a4a2c374e99 [file] [log] [blame]
/************************************************************************************
* arch/mips/src/mips32/fork.S
*
* SPDX-License-Identifier: Apache-2.0
*
* 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 "mips_fork.h"
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
/************************************************************************************
* Public Symbols
************************************************************************************/
.file "fork.S"
.globl mips_fork
/************************************************************************************
* Public Functions
************************************************************************************/
/************************************************************************************
* 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
* from the function in which fork() was called, or calls any other function before
* successfully calling _exit() or one of the exec family of functions.
*
* This thin layer implements fork by simply calling up_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) 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.
* - Initialization of file descriptors and streams
* - Configuration of environment variables
* - Allocate and initialize the stack
* - Setup the input parameters for the task.
* - Initialization of the TCB (including call to up_initial_state())
* 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) mips_fork() then calls nxtask_start_fork()
* 6) nxtask_start_fork() then executes the child thread.
*
* Input Parameters:
* None
*
* 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.
*
************************************************************************************/
.text
.align 2
.globl up_fork
.type up_fork, function
.set nomips16
#ifdef CONFIG_MIPS_MICROMIPS
.set micromips
#endif
.ent up_fork
up_fork:
/* Create a stack frame */
move $t0, $sp /* Save the value of the stack on entry */
addiu $sp, $sp, -FORK_SIZEOF /* Allocate the structure on the stack */
/* CPU registers */
/* Save the saved registers */
sw $s0, FORK_S0_OFFSET($sp)
sw $s1, FORK_S1_OFFSET($sp)
sw $s2, FORK_S2_OFFSET($sp)
sw $s3, FORK_S3_OFFSET($sp)
sw $s4, FORK_S4_OFFSET($sp)
sw $s5, FORK_S5_OFFSET($sp)
sw $s6, FORK_S6_OFFSET($sp)
sw $s7, FORK_S7_OFFSET($sp)
#ifdef CONFIG_MIPS32_FRAMEPOINTER
sw $fp, FORK_FP_OFFSET($sp)
#else
sw $s8, FORK_S8_OFFSET($sp)
#endif
/* Save the global pointer, stack pointer, and return address */
sw $t0, FORK_SP_OFFSET($sp)
sw $ra, FORK_RA_OFFSET($sp)
#ifdef MIPS32_SAVE_GP
sw $gp, FORK_GP_OFFSET($sp)
#endif
/* Floating point registers (not yet) */
/* Then, call mips_fork(), passing it a pointer to the stack structure */
move $a0, $sp
jal mips_fork
nop
/* 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 up_fork
.size up_fork, .-up_fork