diff --git a/.github/workflows/arch.yml b/.github/workflows/arch.yml new file mode 100644 index 0000000000000..0fc899332cc78 --- /dev/null +++ b/.github/workflows/arch.yml @@ -0,0 +1,160 @@ +# Identify the Arch for the PR and select the applicable builds +name: Arch + +on: + workflow_call: + inputs: + os: + description: "Operating System hosting the build: Linux, macOS or msys2" + required: true + type: string + boards: + description: "List of All Builds: [arm-01, risc-v-01, xtensa-01, ...]" + required: true + type: string + outputs: + skip_all_builds: + description: "Set to 1 if all builds should be skipped" + value: ${{ jobs.Select-Builds.outputs.skip_all_builds }} + selected_builds: + description: "Selected Builds for the PR: [arm-01, risc-v-01, xtensa-01, ...]" + value: ${{ jobs.Select-Builds.outputs.selected_builds }} + +jobs: + Select-Builds: + runs-on: ubuntu-latest + + outputs: + skip_all_builds: ${{ steps.select-builds.outputs.skip_all_builds }} + selected_builds: ${{ steps.select-builds.outputs.selected_builds }} + + steps: + + # Get the Arch for the PR: arm, arm64, risc-v, xtensa, ... + - name: Get arch + id: get-arch + run: | + + # If PR is Not Created or Modified: Build all targets + pr=${{github.event.pull_request.number}} + if [[ "$pr" == "" ]]; then + exit + fi + + # Get the Labels for the PR: "Arch: risc-v \n Size: XS" + # If GitHub CLI Fails: Build all targets + labels=$(gh pr view $pr --repo $GITHUB_REPOSITORY --json labels --jq '.labels[] | .name' || echo "") + numlabels=$(gh pr view $pr --repo $GITHUB_REPOSITORY --json labels --jq '.[] | length' || echo "") + echo "numlabels=$numlabels" | tee -a $GITHUB_OUTPUT + + # Identify the Size and Arch Labels + if [[ "$labels" == *"Size: "* ]]; then + echo 'labels_contain_size=1' | tee -a $GITHUB_OUTPUT + fi + if [[ "$labels" == *"Arch: arm64"* ]]; then + echo 'arch_contains_arm64=1' | tee -a $GITHUB_OUTPUT + elif [[ "$labels" == *"Arch: arm"* ]]; then + echo 'arch_contains_arm=1' | tee -a $GITHUB_OUTPUT + elif [[ "$labels" == *"Arch: risc-v"* ]]; then + echo 'arch_contains_riscv=1' | tee -a $GITHUB_OUTPUT + elif [[ "$labels" == *"Arch: simulator"* ]]; then + echo 'arch_contains_sim=1' | tee -a $GITHUB_OUTPUT + elif [[ "$labels" == *"Arch: x86_64"* ]]; then + echo 'arch_contains_x86_64=1' | tee -a $GITHUB_OUTPUT + elif [[ "$labels" == *"Arch: xtensa"* ]]; then + echo 'arch_contains_xtensa=1' | tee -a $GITHUB_OUTPUT + fi + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Select the Builds for the PR: arm-01, risc-v-01, xtensa-01, ... + - name: Select builds + id: select-builds + run: | + + # Fetch the outputs from the previous step + arch_contains_arm=${{ steps.get-arch.outputs.arch_contains_arm }} + arch_contains_arm64=${{ steps.get-arch.outputs.arch_contains_arm64 }} + arch_contains_riscv=${{ steps.get-arch.outputs.arch_contains_riscv }} + arch_contains_sim=${{ steps.get-arch.outputs.arch_contains_sim }} + arch_contains_x86_64=${{ steps.get-arch.outputs.arch_contains_x86_64 }} + arch_contains_xtensa=${{ steps.get-arch.outputs.arch_contains_xtensa }} + labels_contain_size=${{ steps.get-arch.outputs.labels_contain_size }} + numlabels=${{ steps.get-arch.outputs.numlabels }} + + # inputs.boards is a JSON Array: ["arm-01", "risc-v-01", "xtensa-01", ...] + # We compact and remove the newlines + boards=$( echo '${{ inputs.boards }}' | jq --compact-output ".") + numboards=$( echo "$boards" | jq "length" ) + + # We consider only PRs with 2 labels, including size + if [[ "$numlabels" != "2" || "$labels_contain_size" != "1" ]]; then + echo "selected_builds=$boards" | tee -a $GITHUB_OUTPUT + exit + fi + + # For every board + for (( i=0; i> $GITHUB_OUTPUT - fi - fi - - # If "Arch: risc-v" is the only non-size label, then build risc-v-01, risc-v-02 - if [[ "$arch_contains_riscv" == "1" ]]; then - if [[ "${{matrix.boards}}" == "risc-v"* ]]; then - echo Allow build: ${{matrix.boards}} - else - echo Skip build: ${{matrix.boards}} - echo "skip_build=1" >> $GITHUB_OUTPUT - fi - fi - - # If "Arch: xtensa" is the only non-size label, then build xtensa-01, xtensa-02 - if [[ "$arch_contains_xtensa" == "1" ]]; then - if [[ "${{matrix.boards}}" == "xtensa"* ]]; then - echo Allow build: ${{matrix.boards}} - else - echo Skip build: ${{matrix.boards}} - echo "skip_build=1" >> $GITHUB_OUTPUT - fi - fi - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Download Source Artifact - if: ${{ steps.get-arch.outputs.skip_build != '1' }} uses: actions/download-artifact@v4 with: name: source-bundle path: . - name: Extract sources - if: ${{ steps.get-arch.outputs.skip_build != '1' }} run: tar zxf sources.tar.gz - name: Docker Login - if: ${{ steps.get-arch.outputs.skip_build != '1' }} uses: docker/login-action@v3 with: registry: ghcr.io @@ -215,15 +162,12 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Docker Pull - if: ${{ steps.get-arch.outputs.skip_build != '1' }} run: docker pull ghcr.io/apache/nuttx/apache-nuttx-ci-linux - name: Export NuttX Repo SHA - if: ${{ steps.get-arch.outputs.skip_build != '1' }} run: echo "nuttx_sha=`git -C sources/nuttx rev-parse HEAD`" >> $GITHUB_ENV - name: Run builds - if: ${{ steps.get-arch.outputs.skip_build != '1' }} uses: ./sources/nuttx/.github/actions/ci-container env: BLOBDIR: /tools/blobs @@ -247,15 +191,26 @@ jobs: path: buildartifacts/ continue-on-error: true + # Select the macOS Builds based on PR Arch Label + macOS-Arch: + uses: apache/nuttx/.github/workflows/arch.yml@master + needs: Fetch-Source + with: + os: Linux + boards: | + ["macos", "sim-01", "sim-02"] + + # Run the selected macOS Builds macOS: permissions: contents: none runs-on: macos-13 - needs: Fetch-Source + needs: macOS-Arch + if: ${{ needs.macOS-Arch.outputs.skip_all_builds != '1' }} strategy: max-parallel: 2 matrix: - boards: [macos, sim-01, sim-02] + boards: ${{ fromJSON(needs.macOS-Arch.outputs.selected_builds) }} steps: - name: Download Source Artifact uses: actions/download-artifact@v4 @@ -296,14 +251,25 @@ jobs: path: buildartifacts/ continue-on-error: true - msys2: + # Select the msys2 Builds based on PR Arch Label + msys2-Arch: + uses: apache/nuttx/.github/workflows/arch.yml@master needs: Fetch-Source + with: + os: Linux + boards: | + ["msys2"] + + # Run the selected msys2 Builds + msys2: + needs: msys2-Arch + if: ${{ needs.msys2-Arch.outputs.skip_all_builds != '1' }} runs-on: windows-latest strategy: fail-fast: false max-parallel: 1 matrix: - boards: [msys2] + boards: ${{ fromJSON(needs.msys2-Arch.outputs.selected_builds) }} defaults: run: diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a3c52fa15268..62ca601c07d81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,9 +204,7 @@ set(ENV{HOST_BSD} n) set(ENV{HOST_WINDOWS} n) set(ENV{HOST_OTHER} n) -# We define host include(nuttx_sethost) -nuttx_sethost() include(nuttx_parse_function_args) include(nuttx_add_subdirectory) @@ -321,12 +319,7 @@ if(NOT EXISTS ${CMAKE_BINARY_DIR}/.config OR NOT "${NUTTX_DEFCONFIG}" STREQUAL set(ENV{KCONFIG_CONFIG} ${CMAKE_BINARY_DIR}/.config.compressed) # Do olddefconfig step to expand the abbreviated defconfig into normal config - execute_process( - COMMAND olddefconfig - ERROR_VARIABLE KCONFIG_ERROR - OUTPUT_VARIABLE KCONFIG_OUTPUT - RESULT_VARIABLE KCONFIG_STATUS - WORKING_DIRECTORY ${NUTTX_DIR}) + nuttx_olddefconfig() file(RENAME ${CMAKE_BINARY_DIR}/.config.compressed ${CMAKE_BINARY_DIR}/.config) @@ -335,22 +328,23 @@ if(NOT EXISTS ${CMAKE_BINARY_DIR}/.config OR NOT "${NUTTX_DEFCONFIG}" STREQUAL # store original expanded .config configure_file(${CMAKE_BINARY_DIR}/.config ${CMAKE_BINARY_DIR}/.config.orig COPYONLY) - if(KCONFIG_ERROR) - message(WARNING "Kconfig Configuration Error: ${KCONFIG_ERROR}") - endif() - if(KCONFIG_STATUS AND NOT KCONFIG_STATUS EQUAL 0) - message( - FATAL_ERROR - "Failed to initialize Kconfig configuration: ${KCONFIG_OUTPUT}") - endif() + # We define host + nuttx_sethost() set(NUTTX_DEFCONFIG_SAVED ${NUTTX_DEFCONFIG} CACHE INTERNAL "Saved defconfig path" FORCE) # Print configuration choices - + message(STATUS " CMake ${CMAKE_VERSION}") + if(CMAKE_GENERATOR MATCHES "Ninja") + execute_process( + COMMAND ninja --version + OUTPUT_VARIABLE ninja_version + OUTPUT_STRIP_TRAILING_WHITESPACE) + message(STATUS " Ninja ${ninja_version}") + endif() message(STATUS " Board: ${NUTTX_BOARD}") message(STATUS " Config: ${NUTTX_CONFIG}") message(STATUS " Appdir: ${NUTTX_APPS_DIR}") diff --git a/Documentation/components/drivers/special/segger.rst b/Documentation/components/drivers/special/segger.rst index 29097de3b82ac..e22a420afd6d8 100644 --- a/Documentation/components/drivers/special/segger.rst +++ b/Documentation/components/drivers/special/segger.rst @@ -17,7 +17,7 @@ Supported Segger drivers: Segger SystemView ================= -Steps to enable SystemView support: +1. Steps to enable SystemView support: #. Make sure your architecture supports a high-performance counter. In most cases it will be: @@ -62,3 +62,14 @@ Steps to enable SystemView support: In case SystemView returns buffer overflow errors, you should increase ``CONFIG_NOTE_RTT_BUFFER_SIZE_UP``. + +2. Use SystemView for heap tracing: + +Refer to example configuration at ``stm32f429i-disco/configs/systemview``. +Make sure that ``CONFIG_SCHED_INSTRUMENTATION_HEAP`` is enabled. + +Example of screenshot from SystemView: + +.. image:: sysview.png + :width: 800px + :align: center diff --git a/Documentation/components/drivers/special/sysview.png b/Documentation/components/drivers/special/sysview.png new file mode 100644 index 0000000000000..d5f8709631504 Binary files /dev/null and b/Documentation/components/drivers/special/sysview.png differ diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 24d5999fe8d3a..73256b887ed27 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -676,18 +676,20 @@ config ARCH_CHIP_MPS config ARCH_CHIP_QEMU_ARM bool "QEMU virt platform (ARMv7a)" - select ARCH_HAVE_PSCI select ARCH_HAVE_POWEROFF select ARCH_HAVE_RESET select ARCH_IDLE_CUSTOM + select ARM_HAVE_PSCI + select ARM_HAVE_NEON ---help--- QEMU virt platform (ARMv7a) config ARCH_CHIP_GOLDFISH_ARM bool "GOLDFISH virt platform (ARMv7a)" - select ARCH_HAVE_PSCI select ARCH_HAVE_POWEROFF select ARCH_HAVE_RESET + select ARM_HAVE_PSCI + select ARM_HAVE_NEON ---help--- GOLDFISH virt platform (ARMv7a) @@ -1139,8 +1141,8 @@ config ARM_THUMB bool "Thumb Mode" default n -config ARCH_HAVE_PSCI - bool "ARM PCSI (Power State Coordination Interface) Support" +config ARM_HAVE_PSCI + bool "ARM PSCI (Power State Coordination Interface) Support" default n ---help--- This Power State Coordination Interface (PSCI) defines @@ -1188,6 +1190,13 @@ config ARM_HAVE_PACBTI ---help--- Decide whether support PACBTI(Pointer Authentication and Branch Target Identification) Extension +config ARM_PSCI + bool "Enabled PSCI" + depends on ARM_HAVE_PSCI + default n + ---help--- + See ARM_HAVE_PSCI for details + config ARM_FPU_ABI_SOFT bool "Soft Float ABI" default n diff --git a/arch/arm/include/arm/irq.h b/arch/arm/include/arm/irq.h index a3321d7c62c05..246410e47d4f6 100644 --- a/arch/arm/include/arm/irq.h +++ b/arch/arm/include/arm/irq.h @@ -127,12 +127,6 @@ #ifndef __ASSEMBLY__ struct xcptcontext { - /* The following function pointer is non-zero if there - * are pending signals to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of the context used during * signal processing. */ diff --git a/arch/arm/include/armv6-m/irq.h b/arch/arm/include/armv6-m/irq.h index 752e3ed394008..6d142accfa988 100644 --- a/arch/arm/include/armv6-m/irq.h +++ b/arch/arm/include/armv6-m/irq.h @@ -152,12 +152,6 @@ struct xcpt_syscall_s struct xcptcontext { - /* The following function pointer is non-zero if there - * are pending signals to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of the context used during * signal processing. */ diff --git a/arch/arm/include/armv7-a/irq.h b/arch/arm/include/armv7-a/irq.h index 6ca190b07155c..803d5807d3eab 100644 --- a/arch/arm/include/armv7-a/irq.h +++ b/arch/arm/include/armv7-a/irq.h @@ -253,12 +253,6 @@ struct xcpt_syscall_s struct xcptcontext { - /* The following function pointer is non-zero if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of the context used during * signal processing. */ diff --git a/arch/arm/include/armv7-m/irq.h b/arch/arm/include/armv7-m/irq.h index 88db5d3ba36d0..c387899f6053f 100644 --- a/arch/arm/include/armv7-m/irq.h +++ b/arch/arm/include/armv7-m/irq.h @@ -212,12 +212,6 @@ struct xcpt_syscall_s struct xcptcontext { - /* The following function pointer is non-zero if there - * are pending signals to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of the context used during * signal processing. */ diff --git a/arch/arm/include/armv7-r/irq.h b/arch/arm/include/armv7-r/irq.h index 6a00fbdbc321b..402606a546a19 100644 --- a/arch/arm/include/armv7-r/irq.h +++ b/arch/arm/include/armv7-r/irq.h @@ -253,12 +253,6 @@ struct xcpt_syscall_s struct xcptcontext { - /* The following function pointer is non-zero if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of the context used during * signal processing. */ diff --git a/arch/arm/include/armv8-m/irq.h b/arch/arm/include/armv8-m/irq.h index f14d84f6553e8..fb23d569b7db8 100644 --- a/arch/arm/include/armv8-m/irq.h +++ b/arch/arm/include/armv8-m/irq.h @@ -223,12 +223,6 @@ struct xcpt_syscall_s struct xcptcontext { - /* The following function pointer is non-zero if there - * are pending signals to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of the context used during * signal processing. */ diff --git a/arch/arm/include/armv8-r/irq.h b/arch/arm/include/armv8-r/irq.h index 360b4a74585f8..c3be8199f3bfd 100644 --- a/arch/arm/include/armv8-r/irq.h +++ b/arch/arm/include/armv8-r/irq.h @@ -253,12 +253,6 @@ struct xcpt_syscall_s struct xcptcontext { - /* The following function pointer is non-zero if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of the context used during * signal processing. */ diff --git a/arch/arm/include/tlsr82/irq.h b/arch/arm/include/tlsr82/irq.h index 7cf890854278c..751baa6f61d74 100644 --- a/arch/arm/include/tlsr82/irq.h +++ b/arch/arm/include/tlsr82/irq.h @@ -158,12 +158,6 @@ #ifndef __ASSEMBLY__ struct xcptcontext { - /* The following function pointer is non-zero if there - * are pending signals to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved register array pointer used during * signal processing. */ diff --git a/arch/arm/src/arm/arm_schedulesigaction.c b/arch/arm/src/arm/arm_schedulesigaction.c index a0a4017bf4235..1eca541afadb6 100644 --- a/arch/arm/src/arm/arm_schedulesigaction.c +++ b/arch/arm/src/arm/arm_schedulesigaction.c @@ -75,70 +75,61 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->xcp.sigdeliver = sigdeliver; + /* In this case just deliver the signal now. */ - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. - */ - - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); - - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. */ - else - { - /* Save the return lr and cpsr and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + tcb->xcp.saved_regs = tcb->xcp.regs; - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled - */ + /* Then set up to vector to the trampoline with interrupts + * disabled + */ - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT; + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_CPSR] = PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT; #ifdef CONFIG_ARM_THUMB - tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; + tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; #endif - } } } diff --git a/arch/arm/src/arm/arm_sigdeliver.c b/arch/arm/src/arm/arm_sigdeliver.c index 21a0b98baac5d..22589d1e6e77e 100644 --- a/arch/arm/src/arm/arm_sigdeliver.c +++ b/arch/arm/src/arm/arm_sigdeliver.c @@ -59,8 +59,8 @@ void arm_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always @@ -72,7 +72,7 @@ void arm_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -92,7 +92,7 @@ void arm_sigdeliver(void) * could be modified by a hostile program. */ - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/arm/src/armv6-m/arm_schedulesigaction.c b/arch/arm/src/armv6-m/arm_schedulesigaction.c index 4e5da4c5efd95..9eeda2acb31cc 100644 --- a/arch/arm/src/armv6-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv6-m/arm_schedulesigaction.c @@ -78,103 +78,60 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - DEBUGASSERT(tcb != NULL && sigdeliver != NULL); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (tcb->xcp.sigdeliver == NULL) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* In this case just deliver the signal now. + * REVISIT: Signal handle will run in a critical section! */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); - - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handle will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - else - { - /* CASE 2: The task that needs to receive the signal is running. - * This could happen if the task is running on another CPU OR if - * we are in an interrupt handler and the task is running on this - * CPU. In the former case, we will have to PAUSE the other CPU - * first. But in either case, we will have to modify the return - * state as well as the state in the TCB. - */ - - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ - -#ifdef CONFIG_SMP - int cpu = tcb->cpu; - int me = this_cpu(); - - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - } -#endif - - /* Save the return PC, CPSR and either the BASEPRI or PRIMASK - * registers (and perhaps also the LR). These will be restored - * by the signal trampoline after the signal has been delivered. - */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + else + { + /* Save the return PC, CPSR and either the BASEPRI or PRIMASK + * registers (and perhaps also the LR). These will be restored + * by the signal trampoline after the signal has been delivered. + */ - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + tcb->xcp.saved_regs = tcb->xcp.regs; - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode to be - * here. - */ + /* Then set up to vector to the trampoline with interrupts + * disabled. We must already be in privileged thread mode to be + * here. + */ - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_PRIMASK] = 1; - tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T; + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_PRIMASK] = 1; + tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; -#endif - -#ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } + tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; + tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; + tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; #endif - } } } diff --git a/arch/arm/src/armv6-m/arm_sigdeliver.c b/arch/arm/src/armv6-m/arm_sigdeliver.c index d8390b375ca23..fb039d57d8851 100644 --- a/arch/arm/src/armv6-m/arm_sigdeliver.c +++ b/arch/arm/src/armv6-m/arm_sigdeliver.c @@ -68,8 +68,8 @@ void arm_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); retry: #ifdef CONFIG_SMP @@ -101,7 +101,7 @@ void arm_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -148,7 +148,7 @@ void arm_sigdeliver(void) * could be modified by a hostile program. */ - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of * execution. diff --git a/arch/arm/src/armv7-a/CMakeLists.txt b/arch/arm/src/armv7-a/CMakeLists.txt index 042be6cffbc71..79d62c70e6c21 100644 --- a/arch/arm/src/armv7-a/CMakeLists.txt +++ b/arch/arm/src/armv7-a/CMakeLists.txt @@ -112,7 +112,7 @@ if(CONFIG_SMP) list(APPEND SRCS arm_cpustart.c arm_cpupause.c arm_cpuidlestack.c arm_scu.c) endif() -if(CONFIG_ARCH_HAVE_PSCI) +if(CONFIG_ARM_PSCI) list(APPEND SRCS arm_cpu_psci.c arm_smccc.S) endif() diff --git a/arch/arm/src/armv7-a/Make.defs b/arch/arm/src/armv7-a/Make.defs index f757e3d11c454..2be76df65e429 100644 --- a/arch/arm/src/armv7-a/Make.defs +++ b/arch/arm/src/armv7-a/Make.defs @@ -98,7 +98,7 @@ ifeq ($(CONFIG_SMP),y) CMN_CSRCS += arm_scu.c endif -ifeq ($(CONFIG_ARCH_HAVE_PSCI),y) +ifeq ($(CONFIG_ARM_PSCI),y) CMN_ASRCS += arm_smccc.S CMN_CSRCS += arm_cpu_psci.c endif diff --git a/arch/arm/src/armv7-a/arm_schedulesigaction.c b/arch/arm/src/armv7-a/arm_schedulesigaction.c index 187af9b18ba63..9ac4edec49941 100644 --- a/arch/arm/src/armv7-a/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-a/arm_schedulesigaction.c @@ -77,98 +77,56 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on this CPU. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); - - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - else - { - /* CASE 2: The task that needs to receive the signal is running. - * This could happen if the task is running on another CPU OR if - * we are in an interrupt handler and the task is running on this - * CPU. In the former case, we will have to PAUSE the other CPU - * first. But in either case, we will have to modify the return - * state as well as the state in the TCB. - */ - - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ - -#ifdef CONFIG_SMP - int cpu = tcb->cpu; - int me = this_cpu(); - - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - } -#endif - - /* Save the return lr and cpsr and one scratch register. These - * will be restored by the signal trampoline after the signals - * have been delivered. - */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + else + { + /* Save the return lr and cpsr and one scratch register. These + * will be restored by the signal trampoline after the signals + * have been delivered. + */ - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + tcb->xcp.saved_regs = tcb->xcp.regs; - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled - */ + /* Then set up to vector to the trampoline with interrupts + * disabled + */ - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); #ifdef CONFIG_ARM_THUMB - tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; -#endif - -#ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } + tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; #endif - } } } diff --git a/arch/arm/src/armv7-a/arm_sigdeliver.c b/arch/arm/src/armv7-a/arm_sigdeliver.c index e1777e5ae256e..98ac0e115b6fd 100644 --- a/arch/arm/src/armv7-a/arm_sigdeliver.c +++ b/arch/arm/src/armv7-a/arm_sigdeliver.c @@ -68,8 +68,8 @@ void arm_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); retry: #ifdef CONFIG_SMP @@ -101,7 +101,7 @@ void arm_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -148,7 +148,7 @@ void arm_sigdeliver(void) * could be modified by a hostile program. */ - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/arm/src/armv7-a/arm_syscall.c b/arch/arm/src/armv7-a/arm_syscall.c index e2791e1817ceb..8ad689db5a8d7 100644 --- a/arch/arm/src/armv7-a/arm_syscall.c +++ b/arch/arm/src/armv7-a/arm_syscall.c @@ -430,7 +430,7 @@ uint32_t *arm_syscall(uint32_t *regs) /* Copy "info" into user stack */ - if (rtcb->xcp.sigdeliver) + if (rtcb->sigdeliver) { usp = rtcb->xcp.saved_regs[REG_SP]; } diff --git a/arch/arm/src/armv7-m/arm_schedulesigaction.c b/arch/arm/src/armv7-m/arm_schedulesigaction.c index 531e295bbd84d..8d4749ca2a492 100644 --- a/arch/arm/src/armv7-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-m/arm_schedulesigaction.c @@ -79,107 +79,64 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - DEBUGASSERT(tcb != NULL && sigdeliver != NULL); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (tcb->xcp.sigdeliver == NULL) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* In this case just deliver the signal now. + * REVISIT: Signal handle will run in a critical section! */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); - - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handle will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - else - { - /* CASE 2: The task that needs to receive the signal is running. - * This could happen if the task is running on another CPU OR if - * we are in an interrupt handler and the task is running on this - * CPU. In the former case, we will have to PAUSE the other CPU - * first. But in either case, we will have to modify the return - * state as well as the state in the TCB. - */ - - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ - -#ifdef CONFIG_SMP - int cpu = tcb->cpu; - int me = this_cpu(); - - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - } -#endif - - /* Save the return PC, CPSR and either the BASEPRI or PRIMASK - * registers (and perhaps also the LR). These will be restored - * by the signal trampoline after the signal has been delivered. - */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + else + { + /* Save the return PC, CPSR and either the BASEPRI or PRIMASK + * registers (and perhaps also the LR). These will be restored + * by the signal trampoline after the signal has been delivered. + */ - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + tcb->xcp.saved_regs = tcb->xcp.regs; - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode to be - * here. - */ + /* Then set up to vector to the trampoline with interrupts + * disabled. We must already be in privileged thread mode to be + * here. + */ - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; #ifdef CONFIG_ARMV7M_USEBASEPRI - tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; + tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; #else - tcb->xcp.regs[REG_PRIMASK] = 1; + tcb->xcp.regs[REG_PRIMASK] = 1; #endif - tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T; + tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; -#endif - -#ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } + tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; + tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; + tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; #endif - } } } diff --git a/arch/arm/src/armv7-m/arm_sigdeliver.c b/arch/arm/src/armv7-m/arm_sigdeliver.c index 961ca31b59880..524f2c445b691 100644 --- a/arch/arm/src/armv7-m/arm_sigdeliver.c +++ b/arch/arm/src/armv7-m/arm_sigdeliver.c @@ -68,8 +68,8 @@ void arm_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); retry: #ifdef CONFIG_SMP @@ -105,7 +105,7 @@ void arm_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -156,7 +156,7 @@ void arm_sigdeliver(void) * could be modified by a hostile program. */ - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of * execution. diff --git a/arch/arm/src/armv7-r/arm_schedulesigaction.c b/arch/arm/src/armv7-r/arm_schedulesigaction.c index b21a0c9188d59..4946d0e0ac39f 100644 --- a/arch/arm/src/armv7-r/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-r/arm_schedulesigaction.c @@ -75,90 +75,56 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); - - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - else - { - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ - -#ifdef CONFIG_SMP - int cpu = tcb->cpu; - int me = this_cpu(); - - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - } -#endif - - /* Save the return lr and cpsr and one scratch register. These - * will be restored by the signal trampoline after the signals - * have been delivered. - */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + else + { + /* Save the return lr and cpsr and one scratch register. These + * will be restored by the signal trampoline after the signals + * have been delivered. + */ - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + tcb->xcp.saved_regs = tcb->xcp.regs; - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled - */ + /* Then set up to vector to the trampoline with interrupts + * disabled + */ - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); #ifdef CONFIG_ARM_THUMB - tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; -#endif - -#ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } + tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; #endif - } } } diff --git a/arch/arm/src/armv7-r/arm_sigdeliver.c b/arch/arm/src/armv7-r/arm_sigdeliver.c index c21b77ed10b17..2f72c1beeee5f 100644 --- a/arch/arm/src/armv7-r/arm_sigdeliver.c +++ b/arch/arm/src/armv7-r/arm_sigdeliver.c @@ -68,8 +68,8 @@ void arm_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); retry: #ifdef CONFIG_SMP @@ -101,7 +101,7 @@ void arm_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -145,7 +145,7 @@ void arm_sigdeliver(void) * could be modified by a hostile program. */ - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/arm/src/armv7-r/arm_syscall.c b/arch/arm/src/armv7-r/arm_syscall.c index d7dcdbcfe9728..aa01170622e48 100644 --- a/arch/arm/src/armv7-r/arm_syscall.c +++ b/arch/arm/src/armv7-r/arm_syscall.c @@ -427,7 +427,7 @@ uint32_t *arm_syscall(uint32_t *regs) /* Copy "info" into user stack */ - if (rtcb->xcp.sigdeliver) + if (rtcb->sigdeliver) { usp = rtcb->xcp.saved_regs[REG_SP]; } diff --git a/arch/arm/src/armv8-m/arm_schedulesigaction.c b/arch/arm/src/armv8-m/arm_schedulesigaction.c index 42b0ccfb06445..ea12ca1e488e4 100644 --- a/arch/arm/src/armv8-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv8-m/arm_schedulesigaction.c @@ -79,107 +79,64 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - DEBUGASSERT(tcb != NULL && sigdeliver != NULL); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (tcb->xcp.sigdeliver == NULL) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* In this case just deliver the signal now. + * REVISIT: Signal handle will run in a critical section! */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); - - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handle will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - else - { - /* CASE 2: The task that needs to receive the signal is running. - * This could happen if the task is running on another CPU OR if - * we are in an interrupt handler and the task is running on this - * CPU. In the former case, we will have to PAUSE the other CPU - * first. But in either case, we will have to modify the return - * state as well as the state in the TCB. - */ - - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ - -#ifdef CONFIG_SMP - int cpu = tcb->cpu; - int me = this_cpu(); - - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - } -#endif - - /* Save the return PC, CPSR and either the BASEPRI or PRIMASK - * registers (and perhaps also the LR). These will be restored - * by the signal trampoline after the signal has been delivered. - */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + else + { + /* Save the return PC, CPSR and either the BASEPRI or PRIMASK + * registers (and perhaps also the LR). These will be restored + * by the signal trampoline after the signal has been delivered. + */ - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + tcb->xcp.saved_regs = tcb->xcp.regs; - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode to be - * here. - */ + /* Then set up to vector to the trampoline with interrupts + * disabled. We must already be in privileged thread mode to be + * here. + */ - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; #ifdef CONFIG_ARMV8M_USEBASEPRI - tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; + tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; #else - tcb->xcp.regs[REG_PRIMASK] = 1; + tcb->xcp.regs[REG_PRIMASK] = 1; #endif - tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T; + tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; -#endif - -#ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } + tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; + tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; + tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; #endif - } } } diff --git a/arch/arm/src/armv8-m/arm_sigdeliver.c b/arch/arm/src/armv8-m/arm_sigdeliver.c index f8588136fbc97..2db03f17d166b 100644 --- a/arch/arm/src/armv8-m/arm_sigdeliver.c +++ b/arch/arm/src/armv8-m/arm_sigdeliver.c @@ -68,8 +68,8 @@ void arm_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); retry: #ifdef CONFIG_SMP @@ -105,7 +105,7 @@ void arm_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -156,7 +156,7 @@ void arm_sigdeliver(void) * could be modified by a hostile program. */ - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of * execution. diff --git a/arch/arm/src/armv8-r/arm_schedulesigaction.c b/arch/arm/src/armv8-r/arm_schedulesigaction.c index 1ceba997f7f34..94f1111c37b1c 100644 --- a/arch/arm/src/armv8-r/arm_schedulesigaction.c +++ b/arch/arm/src/armv8-r/arm_schedulesigaction.c @@ -75,90 +75,56 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); - - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - else - { - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ - -#ifdef CONFIG_SMP - int cpu = tcb->cpu; - int me = this_cpu(); - - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - } -#endif - - /* Save the return lr and cpsr and one scratch register. These - * will be restored by the signal trampoline after the signals - * have been delivered. - */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + else + { + /* Save the return lr and cpsr and one scratch register. These + * will be restored by the signal trampoline after the signals + * have been delivered. + */ - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + tcb->xcp.saved_regs = tcb->xcp.regs; - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled - */ + /* Then set up to vector to the trampoline with interrupts + * disabled + */ - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); #ifdef CONFIG_ARM_THUMB - tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; -#endif - -#ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } + tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; #endif - } } } diff --git a/arch/arm/src/armv8-r/arm_sigdeliver.c b/arch/arm/src/armv8-r/arm_sigdeliver.c index e249869434dd1..29a422040c2fb 100644 --- a/arch/arm/src/armv8-r/arm_sigdeliver.c +++ b/arch/arm/src/armv8-r/arm_sigdeliver.c @@ -68,8 +68,8 @@ void arm_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); retry: #ifdef CONFIG_SMP @@ -101,7 +101,7 @@ void arm_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -145,7 +145,7 @@ void arm_sigdeliver(void) * could be modified by a hostile program. */ - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/arm/src/armv8-r/arm_syscall.c b/arch/arm/src/armv8-r/arm_syscall.c index 285613ed4b057..abf3b191f4743 100644 --- a/arch/arm/src/armv8-r/arm_syscall.c +++ b/arch/arm/src/armv8-r/arm_syscall.c @@ -426,7 +426,7 @@ uint32_t *arm_syscall(uint32_t *regs) /* Copy "info" into user stack */ - if (rtcb->xcp.sigdeliver) + if (rtcb->sigdeliver) { usp = rtcb->xcp.saved_regs[REG_SP]; } diff --git a/arch/arm/src/cxd56xx/cxd56_sdhci.c b/arch/arm/src/cxd56xx/cxd56_sdhci.c index d2246ca1e22af..06ce83a559971 100644 --- a/arch/arm/src/cxd56xx/cxd56_sdhci.c +++ b/arch/arm/src/cxd56xx/cxd56_sdhci.c @@ -1358,6 +1358,8 @@ static sdio_capset_t cxd56_sdio_capabilities(struct sdio_dev_s *dev) #ifdef CONFIG_CXD56_SDIO_WIDTH_D1_ONLY caps |= SDIO_CAPS_1BIT_ONLY; +#else + caps |= SDIO_CAPS_4BIT; #endif #ifdef CONFIG_CXD56_SDIO_DMA caps |= SDIO_CAPS_DMASUPPORTED; diff --git a/arch/arm/src/goldfish/CMakeLists.txt b/arch/arm/src/goldfish/CMakeLists.txt new file mode 100644 index 0000000000000..229763209b5e1 --- /dev/null +++ b/arch/arm/src/goldfish/CMakeLists.txt @@ -0,0 +1,27 @@ +# ############################################################################## +# arch/arm/src/goldfish/CMakeLists.txt +# +# 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. +# +# ############################################################################## +set(SRCS goldfish_boot.c goldfish_irq.c goldfish_pgalloc.c goldfish_memorymap.c + goldfish_serial.c goldfish_timer.c) + +if(CONFIG_SMP) + list(APPEND SRCS goldfish_cpuboot.c) +endif() + +target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/arm/src/goldfish/Make.defs b/arch/arm/src/goldfish/Make.defs index 8b939669fa02a..e3d93e34f774d 100644 --- a/arch/arm/src/goldfish/Make.defs +++ b/arch/arm/src/goldfish/Make.defs @@ -21,6 +21,10 @@ include armv7-a/Make.defs # goldfish-specific C source files -CHIP_CSRCS = goldfish_boot.c goldfish_serial.c goldfish_irq.c goldfish_timer.c goldfish_memorymap.c -CHIP_CSRCS += goldfish_pgalloc.c +CHIP_CSRCS = goldfish_boot.c +CHIP_CSRCS += goldfish_irq.c goldfish_pgalloc.c +CHIP_CSRCS += goldfish_memorymap.c goldfish_serial.c goldfish_timer.c +ifeq ($(CONFIG_SMP),y) +CHIP_CSRCS += goldfish_cpuboot.c +endif diff --git a/arch/arm/src/goldfish/goldfish_boot.c b/arch/arm/src/goldfish/goldfish_boot.c index b9bf51f473b8d..816b138af1ddd 100644 --- a/arch/arm/src/goldfish/goldfish_boot.c +++ b/arch/arm/src/goldfish/goldfish_boot.c @@ -25,14 +25,22 @@ #include #include "arm_internal.h" +#include "arm_cpu_psci.h" #include "goldfish_irq.h" #include "goldfish_memorymap.h" +#include "smp.h" +#include "gic.h" #ifdef CONFIG_DEVICE_TREE # include #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION +# include +# include +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -47,9 +55,11 @@ void arm_boot(void) { +#ifdef CONFIG_ARCH_PERF_EVENTS /* Perf init */ up_perf_init(0); +#endif /* Set the page table for section */ @@ -57,12 +67,12 @@ void arm_boot(void) arm_fpuconfig(); -#ifdef CONFIG_DEVICE_TREE - fdt_register((const char *)0x40000000); +#ifdef CONFIG_ARM_PSCI + arm_psci_init("smc"); #endif -#if defined(CONFIG_ARCH_HAVE_PSCI) - arm_psci_init("smc"); +#ifdef CONFIG_DEVICE_TREE + fdt_register((const char *)0x40000000); #endif #ifdef USE_EARLYSERIALINIT @@ -73,3 +83,16 @@ void arm_boot(void) arm_earlyserialinit(); #endif } + +#if defined(CONFIG_ARM_PSCI) && defined(CONFIG_SMP) +int up_cpu_start(int cpu) +{ +#ifdef CONFIG_SCHED_INSTRUMENTATION + /* Notify of the start event */ + + sched_note_cpu_start(this_task_inirq(), cpu); +#endif + + return psci_cpu_on(cpu, (uintptr_t)__start); +} +#endif diff --git a/arch/arm/src/goldfish/goldfish_cpuboot.c b/arch/arm/src/goldfish/goldfish_cpuboot.c new file mode 100644 index 0000000000000..160731937c3ca --- /dev/null +++ b/arch/arm/src/goldfish/goldfish_cpuboot.c @@ -0,0 +1,124 @@ +/**************************************************************************** + * arch/arm/src/goldfish/goldfish_cpuboot.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 + +#include +#include +#include +#include +#include + +#include "arm_internal.h" +#include "sctlr.h" +#include "scu.h" +#include "gic.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Symbols defined via the linker script */ + +#ifdef CONFIG_ARCH_LOWVECTORS +extern uint8_t _vector_start[]; /* Beginning of vector block */ +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_cpu_boot + * + * Description: + * Continues the C-level initialization started by the assembly language + * __cpu[n]_start function. At a minimum, this function needs to + * initialize interrupt handling and, perhaps, wait on WFI for + * arm_cpu_start() to issue an SGI. + * + * This function must be provided by the each ARMv7-A MCU and implement + * MCU-specific initialization logic. + * + * Input Parameters: + * cpu - The CPU index. This is the same value that would be obtained by + * calling up_cpu_index(); + * + * Returned Value: + * Does not return. + * + ****************************************************************************/ + +void arm_cpu_boot(int cpu) +{ + /* Enable SMP cache coherency for the CPU */ + + arm_enable_smp(cpu); + + /* Initialize the FPU */ + + arm_fpuconfig(); + + /* Initialize the Generic Interrupt Controller (GIC) for CPUn (n != 0) */ + + arm_gic_initialize(); + +#ifdef CONFIG_ARCH_LOWVECTORS + /* If CONFIG_ARCH_LOWVECTORS is defined, then the vectors located at the + * beginning of the .text region must appear at address at the address + * specified in the VBAR. There are two ways to accomplish this: + * + * 1. By explicitly mapping the beginning of .text region with a page + * table entry so that the virtual address zero maps to the beginning + * of the .text region. VBAR == 0x0000:0000. + * + * 2. Set the Cortex-A5 VBAR register so that the vector table address + * is moved to a location other than 0x0000:0000. + * + * The second method is used by this logic. + */ + + /* Set the VBAR register to the address of the vector table */ + + DEBUGASSERT((((uintptr_t)_vector_start) & ~VBAR_MASK) == 0); + cp15_wrvbar((uint32_t)_vector_start); +#endif /* CONFIG_ARCH_LOWVECTORS */ + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + /* And finally, enable interrupts */ + + up_irq_enable(); +#endif + + /* The next thing that we expect to happen is for logic running on CPU0 + * to call up_cpu_start() which generate an SGI and a context switch to + * the configured NuttX IDLE task. + * Transfer control to the IDLE task. + */ + + nx_idle_trampoline(); +} diff --git a/arch/arm/src/qemu/qemu_boot.c b/arch/arm/src/qemu/qemu_boot.c index b61c243d03d53..82f4a8e93051e 100644 --- a/arch/arm/src/qemu/qemu_boot.c +++ b/arch/arm/src/qemu/qemu_boot.c @@ -25,15 +25,27 @@ #include #include "arm_internal.h" +#include "arm_cpu_psci.h" -#include "qemu_boot.h" #include "qemu_irq.h" #include "qemu_memorymap.h" +#include "smp.h" +#include "gic.h" #ifdef CONFIG_DEVICE_TREE # include #endif +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_SYSLOG_RPMSG +static char g_syslog_rpmsg_buf[4096]; +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -48,9 +60,11 @@ void arm_boot(void) { +#ifdef CONFIG_ARCH_PERF_EVENTS /* Perf init */ up_perf_init(0); +#endif /* Set the page table for section */ @@ -58,7 +72,7 @@ void arm_boot(void) arm_fpuconfig(); -#if defined(CONFIG_ARCH_HAVE_PSCI) +#ifdef CONFIG_ARM_PSCI arm_psci_init("hvc"); #endif @@ -74,11 +88,20 @@ void arm_boot(void) arm_earlyserialinit(); #endif - /* Now we can enable all other CPUs. The enabled CPUs will start execution - * at __cpuN_start and, after very low-level CPU initialization has been - * performed, will branch to arm_cpu_boot() - * (see arch/arm/src/armv7-a/smp.h) - */ +#ifdef CONFIG_SYSLOG_RPMSG + syslog_rpmsg_init_early(g_syslog_rpmsg_buf, sizeof(g_syslog_rpmsg_buf)); +#endif +} + +#if defined(CONFIG_ARM_PSCI) && defined(CONFIG_SMP) +int up_cpu_start(int cpu) +{ +#ifdef CONFIG_SCHED_INSTRUMENTATION + /* Notify of the start event */ - qemu_cpu_enable(); + sched_note_cpu_start(this_task_inirq(), cpu); +#endif + + return psci_cpu_on(cpu, (uintptr_t)__start); } +#endif diff --git a/arch/arm/src/qemu/qemu_boot.h b/arch/arm/src/qemu/qemu_boot.h deleted file mode 100644 index 3e3a1dbf1a5df..0000000000000 --- a/arch/arm/src/qemu/qemu_boot.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** - * arch/arm/src/qemu/qemu_boot.h - * - * 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. - * - ****************************************************************************/ - -#ifndef __ARCH_ARM_SRC_QEMU_QEMU_BOOT_H -#define __ARCH_ARM_SRC_QEMU_QEMU_BOOT_H - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Public Function Prototypes - ****************************************************************************/ - -#ifndef __ASSEMBLY__ - -#undef EXTERN -#if defined(__cplusplus) -#define EXTERN extern "C" -extern "C" -{ -#else -#define EXTERN extern -#endif - -/**************************************************************************** - * Name: qemu_cpu_enable - * - * Description: - * Called from CPU0 to enable all other CPUs. The enabled CPUs will start - * execution at __cpuN_start and, after very low-level CPU initialization - * has been performed, will branch to arm_cpu_boot() - * (see arch/arm/src/armv7-a/smp.h) - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef CONFIG_SMP -void qemu_cpu_enable(void); -#else -# define qemu_cpu_enable() -#endif - -#undef EXTERN -#if defined(__cplusplus) -} -#endif - -#endif /* __ASSEMBLY__ */ -#endif /* __ARCH_ARM_SRC_QEMU_QEMU_BOOT_H */ diff --git a/arch/arm/src/qemu/qemu_cpuboot.c b/arch/arm/src/qemu/qemu_cpuboot.c index e77006b5b0a16..8bfd61b0b5181 100644 --- a/arch/arm/src/qemu/qemu_cpuboot.c +++ b/arch/arm/src/qemu/qemu_cpuboot.c @@ -31,34 +31,11 @@ #include #include +#include "init/init.h" #include "arm_internal.h" #include "sctlr.h" -#include "smp.h" #include "scu.h" #include "gic.h" -#include "mmu.h" -#include "barriers.h" -#include "arm_cpu_psci.h" - -#ifdef CONFIG_SMP - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -static const start_t g_cpu_boot[CONFIG_SMP_NCPUS] = -{ - 0, -#if CONFIG_SMP_NCPUS > 1 - __cpu1_start, -#endif -#if CONFIG_SMP_NCPUS > 2 - __cpu2_start, -#endif -#if CONFIG_SMP_NCPUS > 3 - __cpu3_start -#endif -}; /* Symbols defined via the linker script */ @@ -68,35 +45,6 @@ extern uint8_t _vector_start[]; /* Beginning of vector block */ * Public Functions ****************************************************************************/ -/**************************************************************************** - * Name: qemu_cpu_enable - * - * Description: - * Called from CPU0 to enable all other CPUs. The enabled CPUs will start - * execution at __cpuN_start and, after very low-level CPU initialization - * has been performed, will branch to arm_cpu_boot() - * (see arch/arm/src/armv7-a/smp.h) - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -void qemu_cpu_enable(void) -{ - int cpu; - - for (cpu = 1; cpu < CONFIG_SMP_NCPUS; cpu++) - { - /* Then enable the CPU */ - - psci_cpu_on(CORE_TO_MPID(cpu, 0), (uintptr_t)g_cpu_boot[cpu]); - } -} - /**************************************************************************** * Name: arm_cpu_boot * @@ -118,6 +66,7 @@ void qemu_cpu_enable(void) * ****************************************************************************/ +#ifdef CONFIG_SMP void arm_cpu_boot(int cpu) { /* Enable SMP cache coherency for the CPU */ @@ -159,14 +108,8 @@ void arm_cpu_boot(int cpu) up_irq_enable(); #endif - /* The next thing that we expect to happen is for logic running on CPU0 - * to call up_cpu_start() which generate an SGI and a context switch to - * the configured NuttX IDLE task. - */ + /* Then transfer control to the IDLE task */ - for (; ; ) - { - asm("WFI"); - } + nx_idle_trampoline(); } #endif /* CONFIG_SMP */ diff --git a/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c b/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c index 4e90afee3a804..cf2176e3ad46b 100644 --- a/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c +++ b/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c @@ -75,67 +75,58 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->xcp.sigdeliver = sigdeliver; + /* In this case just deliver the signal now. */ - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. - */ - - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); - - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. */ - else - { - /* Save the return lr and cpsr and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + tcb->xcp.saved_regs = tcb->xcp.regs; - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *)((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *)((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled - */ + /* Then set up to vector to the trampoline with interrupts + * disabled + */ - tcb->xcp.regs[REG_LR] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT; - tcb->xcp.regs[REG_IRQ_EN] = 0; - } + tcb->xcp.regs[REG_LR] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT; + tcb->xcp.regs[REG_IRQ_EN] = 0; } } diff --git a/arch/arm64/include/irq.h b/arch/arm64/include/irq.h index b4ce09ce284f0..47571b2a58fa3 100644 --- a/arch/arm64/include/irq.h +++ b/arch/arm64/include/irq.h @@ -243,12 +243,6 @@ extern "C" struct xcptcontext { - /* The following function pointer is non-zero if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - #ifdef CONFIG_BUILD_KERNEL /* This is the saved address to use when returning from a user-space * signal handler. diff --git a/arch/arm64/src/common/arm64_schedulesigaction.c b/arch/arm64/src/common/arm64_schedulesigaction.c index 5f1dbe63b87d3..cbfc897dedec4 100644 --- a/arch/arm64/src/common/arm64_schedulesigaction.c +++ b/arch/arm64/src/common/arm64_schedulesigaction.c @@ -112,62 +112,35 @@ void arm64_init_signal_process(struct tcb_s *tcb, struct regs_context *regs) * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - else - { -#ifdef CONFIG_SMP - int cpu = tcb->cpu; - int me = this_cpu(); - - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - } -#endif - - /* Save the return lr and cpsr and one scratch register. These - * will be restored by the signal trampoline after the signals - * have been delivered. - */ - - tcb->xcp.saved_reg = tcb->xcp.regs; - - /* create signal process context */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + else + { + /* Save the return lr and cpsr and one scratch register. These + * will be restored by the signal trampoline after the signals + * have been delivered. + */ - arm64_init_signal_process(tcb, NULL); + tcb->xcp.saved_reg = tcb->xcp.regs; -#ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ + /* create signal process context */ - if (cpu != me) - { - up_cpu_resume(cpu); - } -#endif - } + arm64_init_signal_process(tcb, NULL); } } diff --git a/arch/arm64/src/common/arm64_sigdeliver.c b/arch/arm64/src/common/arm64_sigdeliver.c index 0d46a98410db9..2a0fdd65cc343 100644 --- a/arch/arm64/src/common/arm64_sigdeliver.c +++ b/arch/arm64/src/common/arm64_sigdeliver.c @@ -70,8 +70,8 @@ void arm64_sigdeliver(void) #endif sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); retry: #ifdef CONFIG_SMP @@ -103,7 +103,7 @@ void arm64_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -150,7 +150,7 @@ void arm64_sigdeliver(void) * could be modified by a hostile program. */ - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ rtcb->xcp.regs = rtcb->xcp.saved_reg; /* Then restore the correct state for this thread of execution. */ diff --git a/arch/avr/include/avr/irq.h b/arch/avr/include/avr/irq.h index a0df8a95e2e49..df9a82dbae498 100644 --- a/arch/avr/include/avr/irq.h +++ b/arch/avr/include/avr/irq.h @@ -93,12 +93,6 @@ #ifndef __ASSEMBLY__ struct xcptcontext { - /* The following function pointer is non-zero if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of PC and SR used during signal processing. * * REVISIT: Because there is only one copy of these save areas, diff --git a/arch/avr/include/avr32/irq.h b/arch/avr/include/avr32/irq.h index 755d9086ceb49..ed8e064bc62dc 100644 --- a/arch/avr/include/avr32/irq.h +++ b/arch/avr/include/avr32/irq.h @@ -93,12 +93,6 @@ #ifndef __ASSEMBLY__ struct xcptcontext { - /* The following function pointer is non-zero if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of PC and SR used during signal processing. * * REVISIT: Because there is only one copy of these save areas, diff --git a/arch/avr/src/avr/avr_schedulesigaction.c b/arch/avr/src/avr/avr_schedulesigaction.c index 251556aa91b63..02f7d16132966 100644 --- a/arch/avr/src/avr/avr_schedulesigaction.c +++ b/arch/avr/src/avr/avr_schedulesigaction.c @@ -75,120 +75,112 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { uintptr_t reg_ptr = (uintptr_t)avr_sigdeliver; - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the - * interrupted task is the same as the one that - * must receive the signal, then we will have to modify - * the return state as well as the state in the TCB. - * - * Hmmm... there looks like a latent bug here: The following - * logic would fail in the strange case where we are in an - * interrupt handler, the thread is signalling itself, but - * a context switch to another task has occurred so that - * g_current_regs does not refer to the thread of this_task()! - */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } - else - { - /* Save registers that must be protected while the signal - * handler runs. These will be restored by the signal - * trampoline after the signal(s) have been delivered. - */ + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. + * + * Hmmm... there looks like a latent bug here: The following + * logic would fail in the strange case where we are in an + * interrupt handler, the thread is signalling itself, but + * a context switch to another task has occurred so that + * g_current_regs does not refer to the thread of this_task()! + */ - tcb->xcp.saved_pc0 = up_current_regs()[REG_PC0]; - tcb->xcp.saved_pc1 = up_current_regs()[REG_PC1]; + else + { + /* Save registers that must be protected while the signal + * handler runs. These will be restored by the signal + * trampoline after the signal(s) have been delivered. + */ + + tcb->xcp.saved_pc0 = up_current_regs()[REG_PC0]; + tcb->xcp.saved_pc1 = up_current_regs()[REG_PC1]; #if defined(REG_PC2) - tcb->xcp.saved_pc2 = up_current_regs()[REG_PC2]; + tcb->xcp.saved_pc2 = up_current_regs()[REG_PC2]; #endif - tcb->xcp.saved_sreg = up_current_regs()[REG_SREG]; + tcb->xcp.saved_sreg = up_current_regs()[REG_SREG]; - /* Then set up to vector to the trampoline with interrupts - * disabled - */ + /* Then set up to vector to the trampoline with interrupts + * disabled + */ #if !defined(REG_PC2) - up_current_regs()[REG_PC0] = (uint16_t)reg_ptr >> 8; - up_current_regs()[REG_PC1] = (uint16_t)reg_ptr & 0xff; + up_current_regs()[REG_PC0] = (uint16_t)reg_ptr >> 8; + up_current_regs()[REG_PC1] = (uint16_t)reg_ptr & 0xff; #else - up_current_regs()[REG_PC0] = (uint32_t)reg_ptr >> 16; - up_current_regs()[REG_PC1] = (uint32_t)reg_ptr >> 8; - up_current_regs()[REG_PC2] = (uint32_t)reg_ptr & 0xff; + up_current_regs()[REG_PC0] = (uint32_t)reg_ptr >> 16; + up_current_regs()[REG_PC1] = (uint32_t)reg_ptr >> 8; + up_current_regs()[REG_PC2] = (uint32_t)reg_ptr & 0xff; #endif - up_current_regs()[REG_SREG] &= ~(1 << SREG_I); + up_current_regs()[REG_SREG] &= ~(1 << SREG_I); - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ - avr_savestate(tcb->xcp.regs); - } + avr_savestate(tcb->xcp.regs); } + } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. - */ + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ - else - { - /* Save registers that must be protected while the signal handler - * runs. These will be restored by the signal trampoline after - * the signals have been delivered. - */ + else + { + /* Save registers that must be protected while the signal handler + * runs. These will be restored by the signal trampoline after + * the signals have been delivered. + */ - tcb->xcp.saved_pc0 = tcb->xcp.regs[REG_PC0]; - tcb->xcp.saved_pc1 = tcb->xcp.regs[REG_PC1]; + tcb->xcp.saved_pc0 = tcb->xcp.regs[REG_PC0]; + tcb->xcp.saved_pc1 = tcb->xcp.regs[REG_PC1]; #if defined(REG_PC2) - tcb->xcp.saved_pc2 = tcb->xcp.regs[REG_PC2]; + tcb->xcp.saved_pc2 = tcb->xcp.regs[REG_PC2]; #endif - tcb->xcp.saved_sreg = tcb->xcp.regs[REG_SREG]; + tcb->xcp.saved_sreg = tcb->xcp.regs[REG_SREG]; - /* Then set up to vector to the trampoline with interrupts - * disabled - */ + /* Then set up to vector to the trampoline with interrupts + * disabled + */ #if !defined(REG_PC2) - tcb->xcp.regs[REG_PC0] = (uint16_t)reg_ptr >> 8; - tcb->xcp.regs[REG_PC1] = (uint16_t)reg_ptr & 0xff; + tcb->xcp.regs[REG_PC0] = (uint16_t)reg_ptr >> 8; + tcb->xcp.regs[REG_PC1] = (uint16_t)reg_ptr & 0xff; #else - tcb->xcp.regs[REG_PC0] = (uint32_t)reg_ptr >> 16; - tcb->xcp.regs[REG_PC1] = (uint32_t)reg_ptr >> 8; - tcb->xcp.regs[REG_PC2] = (uint32_t)reg_ptr & 0xff; + tcb->xcp.regs[REG_PC0] = (uint32_t)reg_ptr >> 16; + tcb->xcp.regs[REG_PC1] = (uint32_t)reg_ptr >> 8; + tcb->xcp.regs[REG_PC2] = (uint32_t)reg_ptr & 0xff; #endif - tcb->xcp.regs[REG_SREG] &= ~(1 << SREG_I); - } + tcb->xcp.regs[REG_SREG] &= ~(1 << SREG_I); } } diff --git a/arch/avr/src/avr/avr_sigdeliver.c b/arch/avr/src/avr/avr_sigdeliver.c index 24b56fc8ee03e..be1093bcfb30c 100644 --- a/arch/avr/src/avr/avr_sigdeliver.c +++ b/arch/avr/src/avr/avr_sigdeliver.c @@ -59,8 +59,8 @@ void avr_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the return state on the stack. */ @@ -76,7 +76,7 @@ void avr_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -96,13 +96,13 @@ void avr_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_PC0] = rtcb->xcp.saved_pc0; - regs[REG_PC1] = rtcb->xcp.saved_pc1; + regs[REG_PC0] = rtcb->xcp.saved_pc0; + regs[REG_PC1] = rtcb->xcp.saved_pc1; #if defined(REG_PC2) - regs[REG_PC2] = rtcb->xcp.saved_pc2; + regs[REG_PC2] = rtcb->xcp.saved_pc2; #endif - regs[REG_SREG] = rtcb->xcp.saved_sreg; - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + regs[REG_SREG] = rtcb->xcp.saved_sreg; + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. This is an * unusual case that must be handled by up_fullcontextresore. This case is diff --git a/arch/avr/src/avr32/avr_initialstate.c b/arch/avr/src/avr32/avr_initialstate.c index a48315678e49f..14e9886a4c662 100644 --- a/arch/avr/src/avr32/avr_initialstate.c +++ b/arch/avr/src/avr32/avr_initialstate.c @@ -87,7 +87,7 @@ void up_initial_state(struct tcb_s *tcb) #else /* No pending signal delivery */ - xcp->sigdeliver = NULL; + tcb->sigdeliver = NULL; /* Clear the frame pointer and link register since this is the outermost * frame. diff --git a/arch/avr/src/avr32/avr_schedulesigaction.c b/arch/avr/src/avr32/avr_schedulesigaction.c index 0a84063baada1..66ead0617ab21 100644 --- a/arch/avr/src/avr32/avr_schedulesigaction.c +++ b/arch/avr/src/avr32/avr_schedulesigaction.c @@ -75,95 +75,87 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ - - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the - * interrupted task is the same as the one that - * must receive the signal, then we will have to modify - * the return state as well as the state in the TCB. - * - * Hmmm... there looks like a latent bug here: The following - * logic would fail in the strange case where we are in an - * interrupt handler, the thread is signalling itself, but - * a context switch to another task has occurred so that - * g_current_regs does not refer to the thread of this_task()! - */ - - else - { - /* Save registers that must be protected while the signal - * handler runs. These will be restored by the signal - * trampoline after the signal(s) have been delivered. - */ + /* In this case just deliver the signal now. */ - tcb->xcp.saved_pc = up_current_regs()[REG_PC]; - tcb->xcp.saved_sr = up_current_regs()[REG_SR]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_PC] = (uint32_t)avr_sigdeliver; - up_current_regs()[REG_SR] |= AVR32_SR_GM_MASK; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - avr_savestate(tcb->xcp.regs); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. + * + * Hmmm... there looks like a latent bug here: The following + * logic would fail in the strange case where we are in an + * interrupt handler, the thread is signalling itself, but + * a context switch to another task has occurred so that + * g_current_regs does not refer to the thread of this_task()! */ else { - /* Save registers that must be protected while the signal handler - * runs. These will be restored by the signal trampoline after - * the signals have been delivered. + /* Save registers that must be protected while the signal + * handler runs. These will be restored by the signal + * trampoline after the signal(s) have been delivered. */ - tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; - tcb->xcp.saved_sr = tcb->xcp.regs[REG_SR]; + tcb->xcp.saved_pc = up_current_regs()[REG_PC]; + tcb->xcp.saved_sr = up_current_regs()[REG_SR]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_PC] = (uint32_t)avr_sigdeliver; - tcb->xcp.regs[REG_SR] |= AVR32_SR_GM_MASK; + up_current_regs()[REG_PC] = (uint32_t)avr_sigdeliver; + up_current_regs()[REG_SR] |= AVR32_SR_GM_MASK; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + avr_savestate(tcb->xcp.regs); } } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save registers that must be protected while the signal handler + * runs. These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; + tcb->xcp.saved_sr = tcb->xcp.regs[REG_SR]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)avr_sigdeliver; + tcb->xcp.regs[REG_SR] |= AVR32_SR_GM_MASK; + } } diff --git a/arch/avr/src/avr32/avr_sigdeliver.c b/arch/avr/src/avr32/avr_sigdeliver.c index ca81e807ced99..331ac29fd624f 100644 --- a/arch/avr/src/avr32/avr_sigdeliver.c +++ b/arch/avr/src/avr32/avr_sigdeliver.c @@ -63,8 +63,8 @@ void avr_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the return state on the stack. */ @@ -80,7 +80,7 @@ void avr_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -100,9 +100,9 @@ void avr_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_PC] = rtcb->xcp.saved_pc; - regs[REG_SR] = rtcb->xcp.saved_sr; - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + regs[REG_PC] = rtcb->xcp.saved_pc; + regs[REG_SR] = rtcb->xcp.saved_sr; + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. This is an * unusual case that must be handled by up_fullcontextresore. This case is diff --git a/arch/ceva/include/xc5/irq.h b/arch/ceva/include/xc5/irq.h index cf77787e0af16..0d413daccb70f 100644 --- a/arch/ceva/include/xc5/irq.h +++ b/arch/ceva/include/xc5/irq.h @@ -127,12 +127,6 @@ struct xcpt_syscall_s struct xcptcontext { #ifndef CONFIG_DISABLE_SIGNALS - /* The following function pointer is non-zero if there - * are pending signals to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of the context used during * signal processing. */ diff --git a/arch/ceva/include/xm6/irq.h b/arch/ceva/include/xm6/irq.h index 0a735828ec2ef..44732f3d9e4ec 100644 --- a/arch/ceva/include/xm6/irq.h +++ b/arch/ceva/include/xm6/irq.h @@ -130,12 +130,6 @@ struct xcpt_syscall_s struct xcptcontext { #ifndef CONFIG_DISABLE_SIGNALS - /* The following function pointer is non-zero if there - * are pending signals to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of the context used during * signal processing. */ diff --git a/arch/ceva/src/common/ceva_schedulesigaction.c b/arch/ceva/src/common/ceva_schedulesigaction.c index 2eea396b0b994..c96a741141280 100644 --- a/arch/ceva/src/common/ceva_schedulesigaction.c +++ b/arch/ceva/src/common/ceva_schedulesigaction.c @@ -72,138 +72,105 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - DEBUGASSERT(tcb != NULL && sigdeliver != NULL); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to task that is currently executing on any CPU. + */ - if (tcb->xcp.sigdeliver == NULL) + if (tcb->task_state == TSTATE_TASK_RUNNING) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. - */ - - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb->task_state == TSTATE_TASK_RUNNING) - { - uint8_t me = this_cpu(); + uint8_t me = this_cpu(); #ifdef CONFIG_SMP - uint8_t cpu = tcb->cpu; + uint8_t cpu = tcb->cpu; #else - uint8_t cpu = 0; + uint8_t cpu = 0; #endif - /* CASE 1: We are not in an interrupt handler and a task is - * signaling itself for some reason. - */ - - if (cpu == me && !up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: The task that needs to receive the signal is running. - * This could happen if the task is running on another CPU OR if - * we are in an interrupt handler and the task is running on this - * CPU. In the former case, we will have to PAUSE the other CPU - * first. But in either case, we will have to modify the return - * state as well as the state in the TCB. - */ - - else - { -#ifdef CONFIG_SMP - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ + /* CASE 1: We are not in an interrupt handler and a task is + * signaling itself for some reason. + */ - if (cpu != me) - { - /* Pause the CPU */ + if (cpu == me && !up_current_regs()) + { + /* In this case just deliver the signal now. */ - up_cpu_pause(cpu); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } - /* Now tcb on the other CPU can be accessed safely */ -#endif + /* CASE 2: The task that needs to receive the signal is running. + * This could happen if the task is running on another CPU OR if + * we are in an interrupt handler and the task is running on this + * CPU. In the former case, we will have to PAUSE the other CPU + * first. But in either case, we will have to modify the return + * state as well as the state in the TCB. + */ - /* Save the current register context location */ + else + { + /* Save the current register context location */ - tcb->xcp.saved_regs = up_current_regs(); + tcb->xcp.saved_regs = up_current_regs(); - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - up_current_regs() -= XCPTCONTEXT_REGS; - memcpy(up_current_regs(), up_current_regs() + - XCPTCONTEXT_REGS, XCPTCONTEXT_SIZE); + up_current_regs() -= XCPTCONTEXT_REGS; + memcpy(up_current_regs(), up_current_regs() + + XCPTCONTEXT_REGS, XCPTCONTEXT_SIZE); - up_current_regs()[REG_SP] = (uint32_t)up_current_regs(); + up_current_regs()[REG_SP] = (uint32_t)up_current_regs(); - /* Then set up to vector to the trampoline with interrupts - * unchanged. We must already be in privileged thread mode - * to be here. - */ + /* Then set up to vector to the trampoline with interrupts + * unchanged. We must already be in privileged thread mode + * to be here. + */ - up_current_regs()[REG_PC] = (uint32_t)ceva_sigdeliver; + up_current_regs()[REG_PC] = (uint32_t)ceva_sigdeliver; #ifdef REG_OM - up_current_regs()[REG_OM] &= ~REG_OM_MASK; - up_current_regs()[REG_OM] |= REG_OM_KERNEL; -#endif - -#ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } + up_current_regs()[REG_OM] &= ~REG_OM_MASK; + up_current_regs()[REG_OM] |= REG_OM_KERNEL; #endif - } } + } - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signaling some other non-running task. - */ + /* Otherwise, we are (1) signaling a task is not running from an + * interrupt handler or (2) we are not in an interrupt handler and the + * running task is signaling some other non-running task. + */ - else - { - /* Save the current register context location */ + else + { + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + tcb->xcp.saved_regs = tcb->xcp.regs; - /* Duplicate the register context. These will be restored - * by the signal trampoline after the signal has been delivered. - */ + /* Duplicate the register context. These will be restored + * by the signal trampoline after the signal has been delivered. + */ - tcb->xcp.regs -= XCPTCONTEXT_REGS; - memcpy(tcb->xcp.regs, tcb->xcp.regs + - XCPTCONTEXT_REGS, XCPTCONTEXT_SIZE); + tcb->xcp.regs -= XCPTCONTEXT_REGS; + memcpy(tcb->xcp.regs, tcb->xcp.regs + + XCPTCONTEXT_REGS, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs; - /* Then set up to vector to the trampoline with interrupts - * unchanged. We must already be in privileged thread mode to be - * here. - */ + /* Then set up to vector to the trampoline with interrupts + * unchanged. We must already be in privileged thread mode to be + * here. + */ - tcb->xcp.regs[REG_PC] = (uint32_t)ceva_sigdeliver; + tcb->xcp.regs[REG_PC] = (uint32_t)ceva_sigdeliver; #ifdef REG_OM - tcb->xcp.regs[REG_OM] &= ~REG_OM_MASK; - tcb->xcp.regs[REG_OM] |= REG_OM_KERNEL; + tcb->xcp.regs[REG_OM] &= ~REG_OM_MASK; + tcb->xcp.regs[REG_OM] |= REG_OM_KERNEL; #endif - } } } diff --git a/arch/ceva/src/common/ceva_sigdeliver.c b/arch/ceva/src/common/ceva_sigdeliver.c index 3bf25abdffafb..9d0deb4bf380e 100644 --- a/arch/ceva/src/common/ceva_sigdeliver.c +++ b/arch/ceva/src/common/ceva_sigdeliver.c @@ -62,16 +62,16 @@ void ceva_sigdeliver(void) int saved_errno = rtcb->pterrno; sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Get a local copy of the sigdeliver function pointer. We do this so that * we can nullify the sigdeliver function pointer in the TCB and accept * more signal deliveries while processing the current pending signals. */ - sigdeliver = (sig_deliver_t)rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; + sigdeliver = rtcb->sigdeliver; + rtcb->sigdeliver = NULL; /* Deliver the signal */ diff --git a/arch/mips/include/mips32/irq.h b/arch/mips/include/mips32/irq.h index 228f95a56585c..031ba4fe2b233 100644 --- a/arch/mips/include/mips32/irq.h +++ b/arch/mips/include/mips32/irq.h @@ -321,12 +321,6 @@ struct xcpt_syscall_s struct xcptcontext { - /* The following function pointer is non-NULL if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These additional register save locations are used to implement the * signal delivery trampoline. * diff --git a/arch/mips/src/mips32/mips_schedulesigaction.c b/arch/mips/src/mips32/mips_schedulesigaction.c index acbb8318fb586..32501b02eb4ae 100644 --- a/arch/mips/src/mips32/mips_schedulesigaction.c +++ b/arch/mips/src/mips32/mips_schedulesigaction.c @@ -76,88 +76,41 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { uint32_t status; - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ - - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the - * interrupted task is the same as the one that - * must receive the signal, then we will have to modify - * the return state as well as the state in the TCB. - * - * Hmmm... there looks like a latent bug here: The following - * logic would fail in the strange case where we are in an - * interrupt handler, the thread is signalling itself, but - * a context switch to another task has occurred so that - * g_current_regs does not refer to the thread of this_task()! - */ + /* In this case just deliver the signal now. */ - else - { - /* Save the return EPC and STATUS registers. These will be - * restored by the signal trampoline after the signals have - * been delivered. - */ - - tcb->xcp.saved_epc = up_current_regs()[REG_EPC]; - tcb->xcp.saved_status = up_current_regs()[REG_STATUS]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_EPC] = (uint32_t)mips_sigdeliver; - status = up_current_regs()[REG_STATUS]; - status &= ~CP0_STATUS_INT_MASK; - status |= CP0_STATUS_INT_SW0; - up_current_regs()[REG_STATUS] = status; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - mips_savestate(tcb->xcp.regs); - - sinfo("PC/STATUS Saved: %08" PRIx32 "/%08" PRIx32 - " New: %08" PRIx32 "/%08" PRIx32 "\n", - tcb->xcp.saved_epc, tcb->xcp.saved_status, - up_current_regs()[REG_EPC], - up_current_regs()[REG_STATUS]); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. + * + * Hmmm... there looks like a latent bug here: The following + * logic would fail in the strange case where we are in an + * interrupt handler, the thread is signalling itself, but + * a context switch to another task has occurred so that + * g_current_regs does not refer to the thread of this_task()! */ else @@ -167,23 +120,62 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * been delivered. */ - tcb->xcp.saved_epc = tcb->xcp.regs[REG_EPC]; - tcb->xcp.saved_status = tcb->xcp.regs[REG_STATUS]; + tcb->xcp.saved_epc = up_current_regs()[REG_EPC]; + tcb->xcp.saved_status = up_current_regs()[REG_STATUS]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_EPC] = (uint32_t)mips_sigdeliver; - status = tcb->xcp.regs[REG_STATUS]; - status &= ~CP0_STATUS_INT_MASK; - status |= CP0_STATUS_INT_SW0; - tcb->xcp.regs[REG_STATUS] = status; + up_current_regs()[REG_EPC] = (uint32_t)mips_sigdeliver; + status = up_current_regs()[REG_STATUS]; + status &= ~CP0_STATUS_INT_MASK; + status |= CP0_STATUS_INT_SW0; + up_current_regs()[REG_STATUS] = status; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + mips_savestate(tcb->xcp.regs); sinfo("PC/STATUS Saved: %08" PRIx32 "/%08" PRIx32 " New: %08" PRIx32 "/%08" PRIx32 "\n", tcb->xcp.saved_epc, tcb->xcp.saved_status, - tcb->xcp.regs[REG_EPC], tcb->xcp.regs[REG_STATUS]); + up_current_regs()[REG_EPC], + up_current_regs()[REG_STATUS]); } } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save the return EPC and STATUS registers. These will be + * restored by the signal trampoline after the signals have + * been delivered. + */ + + tcb->xcp.saved_epc = tcb->xcp.regs[REG_EPC]; + tcb->xcp.saved_status = tcb->xcp.regs[REG_STATUS]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_EPC] = (uint32_t)mips_sigdeliver; + status = tcb->xcp.regs[REG_STATUS]; + status &= ~CP0_STATUS_INT_MASK; + status |= CP0_STATUS_INT_SW0; + tcb->xcp.regs[REG_STATUS] = status; + + sinfo("PC/STATUS Saved: %08" PRIx32 "/%08" PRIx32 + " New: %08" PRIx32 "/%08" PRIx32 "\n", + tcb->xcp.saved_epc, tcb->xcp.saved_status, + tcb->xcp.regs[REG_EPC], tcb->xcp.regs[REG_STATUS]); + } } diff --git a/arch/mips/src/mips32/mips_sigdeliver.c b/arch/mips/src/mips32/mips_sigdeliver.c index ea810a56386f3..d942689c918c4 100644 --- a/arch/mips/src/mips32/mips_sigdeliver.c +++ b/arch/mips/src/mips32/mips_sigdeliver.c @@ -61,8 +61,8 @@ void mips_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the return state on the stack. */ @@ -78,7 +78,7 @@ void mips_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -100,9 +100,9 @@ void mips_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_EPC] = rtcb->xcp.saved_epc; - regs[REG_STATUS] = rtcb->xcp.saved_status; - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + regs[REG_EPC] = rtcb->xcp.saved_epc; + regs[REG_STATUS] = rtcb->xcp.saved_status; + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of * execution. diff --git a/arch/misoc/include/lm32/irq.h b/arch/misoc/include/lm32/irq.h index 69bdd8a271ff0..799cba3d5da95 100644 --- a/arch/misoc/include/lm32/irq.h +++ b/arch/misoc/include/lm32/irq.h @@ -179,12 +179,6 @@ struct xcptcontext { - /* The following function pointer is non-NULL if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These additional register save locations are used to implement the * signal delivery trampoline. * diff --git a/arch/misoc/include/minerva/irq.h b/arch/misoc/include/minerva/irq.h index 4b81cec28141e..c34c49861ec31 100644 --- a/arch/misoc/include/minerva/irq.h +++ b/arch/misoc/include/minerva/irq.h @@ -261,12 +261,6 @@ struct xcpt_syscall_s struct xcptcontext { - /* The following function pointer is non-NULL if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These additional register save locations are used to implement the * signal delivery trampoline. */ diff --git a/arch/misoc/src/lm32/lm32_schedulesigaction.c b/arch/misoc/src/lm32/lm32_schedulesigaction.c index afc8edafe8d5a..437f180d758de 100644 --- a/arch/misoc/src/lm32/lm32_schedulesigaction.c +++ b/arch/misoc/src/lm32/lm32_schedulesigaction.c @@ -75,81 +75,39 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ - - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the - * interrupted task is the same as the one that - * must receive the signal, then we will have to modify - * the return state as well as the state in the TCB. - * - * Hmmm... there looks like a latent bug here: The following - * logic would fail in the strange case where we are in an - * interrupt handler, the thread is signalling itself, but - * a context switch to another task has occurred so that - * g_current_regs does not refer to the thread of this_task()! - */ - - else - { - /* Save the return EPC and STATUS registers. These will be - * restored by the signal trampoline after the signals have - * been delivered. - */ + /* In this case just deliver the signal now. */ - tcb->xcp.saved_epc = up_current_regs()[REG_EPC]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_EPC] = (uint32_t)lm32_sigdeliver; - up_current_regs()[REG_INT_CTX] = 0; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - misoc_savestate(tcb->xcp.regs); - - sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n", - tcb->xcp.saved_epc, tcb->xcp.saved_status, - up_current_regs()[REG_EPC], - up_current_regs()[REG_STATUS]); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. + * + * Hmmm... there looks like a latent bug here: The following + * logic would fail in the strange case where we are in an + * interrupt handler, the thread is signalling itself, but + * a context switch to another task has occurred so that + * g_current_regs does not refer to the thread of this_task()! */ else @@ -159,19 +117,53 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * been delivered. */ - tcb->xcp.saved_epc = tcb->xcp.regs[REG_EPC]; - tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_INT_CTX]; + tcb->xcp.saved_epc = up_current_regs()[REG_EPC]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_EPC] = (uint32_t)lm32_sigdeliver; - tcb->xcp.regs[REG_INT_CTX] = 0; + up_current_regs()[REG_EPC] = (uint32_t)lm32_sigdeliver; + up_current_regs()[REG_INT_CTX] = 0; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + misoc_savestate(tcb->xcp.regs); sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n", tcb->xcp.saved_epc, tcb->xcp.saved_status, - tcb->xcp.regs[REG_EPC], tcb->xcp.regs[REG_STATUS]); + up_current_regs()[REG_EPC], + up_current_regs()[REG_STATUS]); } } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save the return EPC and STATUS registers. These will be + * restored by the signal trampoline after the signals have + * been delivered. + */ + + tcb->xcp.saved_epc = tcb->xcp.regs[REG_EPC]; + tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_INT_CTX]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_EPC] = (uint32_t)lm32_sigdeliver; + tcb->xcp.regs[REG_INT_CTX] = 0; + + sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n", + tcb->xcp.saved_epc, tcb->xcp.saved_status, + tcb->xcp.regs[REG_EPC], tcb->xcp.regs[REG_STATUS]); + } } diff --git a/arch/misoc/src/lm32/lm32_sigdeliver.c b/arch/misoc/src/lm32/lm32_sigdeliver.c index 4adc84955909f..081f40d6e3739 100644 --- a/arch/misoc/src/lm32/lm32_sigdeliver.c +++ b/arch/misoc/src/lm32/lm32_sigdeliver.c @@ -60,8 +60,8 @@ void lm32_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the return state on the stack. */ @@ -77,7 +77,7 @@ void lm32_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -99,9 +99,9 @@ void lm32_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_EPC] = rtcb->xcp.saved_epc; - regs[REG_INT_CTX] = rtcb->xcp.saved_int_ctx; - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + regs[REG_EPC] = rtcb->xcp.saved_epc; + regs[REG_INT_CTX] = rtcb->xcp.saved_int_ctx; + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of * execution. diff --git a/arch/misoc/src/minerva/minerva_schedulesigaction.c b/arch/misoc/src/minerva/minerva_schedulesigaction.c index e0f2509aff032..9d8487dc689e0 100644 --- a/arch/misoc/src/minerva/minerva_schedulesigaction.c +++ b/arch/misoc/src/minerva/minerva_schedulesigaction.c @@ -76,103 +76,95 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ - - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the interrupted task - * is the same as the one that must receive the signal, then we - * will have to modify the return state as well as the state in - * the TCB. - * - * Hmmm... there looks like a latent bug here: The following logic - * would fail in the strange case where we are in an interrupt - * handler, the thread is signalling itself, but a context switch - * to another task has occurred so that g_current_regs does not - * refer to the thread of this_task()! - */ - - else - { - /* Save the return EPC and STATUS registers. These will be - * restored by the signal trampoline after the signals have - * been delivered. - */ + /* In this case just deliver the signal now. */ - tcb->xcp.saved_epc = up_current_regs()[REG_CSR_MEPC]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_CSR_MEPC] = - (uint32_t)minerva_sigdeliver; - up_current_regs()[REG_CSR_MSTATUS] &= ~CSR_MSTATUS_MIE; - - /* And make sure that the saved context in the TCB is the same - * as the interrupt return context. - */ - - misoc_savestate(tcb->xcp.regs); - - sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n", - tcb->xcp.saved_epc, tcb->xcp.saved_status, - up_current_regs()[REG_CSR_MEPC], - up_current_regs()[REG_CSR_MSTATUS]); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signalling some non-running task. + /* CASE 2: We are in an interrupt handler AND the interrupted task + * is the same as the one that must receive the signal, then we + * will have to modify the return state as well as the state in + * the TCB. + * + * Hmmm... there looks like a latent bug here: The following logic + * would fail in the strange case where we are in an interrupt + * handler, the thread is signalling itself, but a context switch + * to another task has occurred so that g_current_regs does not + * refer to the thread of this_task()! */ else { /* Save the return EPC and STATUS registers. These will be - * restored by the signal trampoline after the signals have been - * delivered. + * restored by the signal trampoline after the signals have + * been delivered. */ - tcb->xcp.saved_epc = tcb->xcp.regs[REG_CSR_MEPC]; - tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_CSR_MSTATUS]; + tcb->xcp.saved_epc = up_current_regs()[REG_CSR_MEPC]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_CSR_MEPC] = (uint32_t) minerva_sigdeliver; + up_current_regs()[REG_CSR_MEPC] = + (uint32_t)minerva_sigdeliver; up_current_regs()[REG_CSR_MSTATUS] &= ~CSR_MSTATUS_MIE; + /* And make sure that the saved context in the TCB is the same + * as the interrupt return context. + */ + + misoc_savestate(tcb->xcp.regs); + sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n", tcb->xcp.saved_epc, tcb->xcp.saved_status, - tcb->xcp.regs[REG_CSR_MEPC], tcb->xcp.regs[REG_CSR_MSTATUS]); + up_current_regs()[REG_CSR_MEPC], + up_current_regs()[REG_CSR_MSTATUS]); } } + + /* Otherwise, we are (1) signaling a task is not running from an + * interrupt handler or (2) we are not in an interrupt handler and the + * running task is signalling some non-running task. + */ + + else + { + /* Save the return EPC and STATUS registers. These will be + * restored by the signal trampoline after the signals have been + * delivered. + */ + + tcb->xcp.saved_epc = tcb->xcp.regs[REG_CSR_MEPC]; + tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_CSR_MSTATUS]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_CSR_MEPC] = (uint32_t) minerva_sigdeliver; + up_current_regs()[REG_CSR_MSTATUS] &= ~CSR_MSTATUS_MIE; + + sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n", + tcb->xcp.saved_epc, tcb->xcp.saved_status, + tcb->xcp.regs[REG_CSR_MEPC], tcb->xcp.regs[REG_CSR_MSTATUS]); + } } diff --git a/arch/misoc/src/minerva/minerva_sigdeliver.c b/arch/misoc/src/minerva/minerva_sigdeliver.c index ac2603f5046e3..306a1a77dfd61 100644 --- a/arch/misoc/src/minerva/minerva_sigdeliver.c +++ b/arch/misoc/src/minerva/minerva_sigdeliver.c @@ -62,8 +62,8 @@ void minerva_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the real return state on the stack. */ @@ -76,8 +76,8 @@ void minerva_sigdeliver(void) * more signal deliveries while processing the current pending signals. */ - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; + sigdeliver = rtcb->sigdeliver; + rtcb->sigdeliver = NULL; # ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always diff --git a/arch/or1k/include/mor1kx/irq.h b/arch/or1k/include/mor1kx/irq.h index ba1e5f736bd68..f45e5949ed287 100644 --- a/arch/or1k/include/mor1kx/irq.h +++ b/arch/or1k/include/mor1kx/irq.h @@ -170,12 +170,6 @@ struct xcptcontext uint32_t regs[XCPTCONTEXT_REGS]; - /* The following function pointer is non-zero if there - * are pending signals to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of LR and CPSR used during * signal processing. * diff --git a/arch/or1k/src/common/or1k_schedulesigaction.c b/arch/or1k/src/common/or1k_schedulesigaction.c index 9ee20473d89af..c7f56ede5b856 100644 --- a/arch/or1k/src/common/or1k_schedulesigaction.c +++ b/arch/or1k/src/common/or1k_schedulesigaction.c @@ -74,80 +74,39 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ - - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the - * interrupted task is the same as the one that - * must receive the signal, then we will have to modify - * the return state as well as the state in the TCB. - * - * Hmmm... there looks like a latent bug here: The following - * logic would fail in the strange case where we are in an - * interrupt handler, the thread is signalling itself, but - * a context switch to another task has occurred so that - * current_regs does not refer to the thread of this_task()! - */ - - else - { - /* Save the return lr and cpsr and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - /* tcb->xcp.saved_pc = up_current_regs()[REG_PC]; - * tcb->xcp.saved_cpsr = up_current_regs()[REG_CPSR]; - */ + /* In this case just deliver the signal now. */ - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - /* up_current_regs()[REG_PC] = (uint32_t)or1k_sigdeliver; - * up_current_regs()[REG_CPSR] = SVC_MODE | PSR_I_BIT | - * PSR_F_BIT; - */ - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - or1k_savestate(tcb->xcp.regs); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. + * + * Hmmm... there looks like a latent bug here: The following + * logic would fail in the strange case where we are in an + * interrupt handler, the thread is signalling itself, but + * a context switch to another task has occurred so that + * current_regs does not refer to the thread of this_task()! */ else @@ -157,17 +116,50 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * the signals have been delivered. */ - tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; - - /* tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR]; */ + /* tcb->xcp.saved_pc = up_current_regs()[REG_PC]; + * tcb->xcp.saved_cpsr = up_current_regs()[REG_CPSR]; + */ /* Then set up to vector to the trampoline with interrupts * disabled */ - /* tcb->xcp.regs[REG_PC] = (uint32_t)or1k_sigdeliver; - * tcb->xcp.regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT; + /* up_current_regs()[REG_PC] = (uint32_t)or1k_sigdeliver; + * up_current_regs()[REG_CPSR] = SVC_MODE | PSR_I_BIT | + * PSR_F_BIT; + */ + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. */ + + or1k_savestate(tcb->xcp.regs); } } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; + + /* tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR]; */ + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + /* tcb->xcp.regs[REG_PC] = (uint32_t)or1k_sigdeliver; + * tcb->xcp.regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT; + */ + } } diff --git a/arch/renesas/include/m16c/irq.h b/arch/renesas/include/m16c/irq.h index 5b66067746ff9..f06aae80d8bb0 100644 --- a/arch/renesas/include/m16c/irq.h +++ b/arch/renesas/include/m16c/irq.h @@ -228,12 +228,6 @@ #ifndef __ASSEMBLY__ struct xcptcontext { - /* The following function pointer is non-zero if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of LR and SR used during signal processing. * * REVISIT: Because there is only one copy of these save areas, diff --git a/arch/renesas/include/rx65n/irq.h b/arch/renesas/include/rx65n/irq.h index 649af4ea4355e..42c5f62dd08c0 100644 --- a/arch/renesas/include/rx65n/irq.h +++ b/arch/renesas/include/rx65n/irq.h @@ -986,12 +986,6 @@ #ifndef __ASSEMBLY__ struct xcptcontext { - /* The following function pointer is non-zero if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of LR and SR used during signal processing. */ uint32_t saved_pc; diff --git a/arch/renesas/include/sh1/irq.h b/arch/renesas/include/sh1/irq.h index 6ce374cf68078..2f45b100bf8c7 100644 --- a/arch/renesas/include/sh1/irq.h +++ b/arch/renesas/include/sh1/irq.h @@ -449,12 +449,6 @@ #ifndef __ASSEMBLY__ struct xcptcontext { - /* The following function pointer is non-zero if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of LR and SR used during signal processing. * * REVISIT: Because there is only one copy of these save areas, diff --git a/arch/renesas/src/m16c/m16c_schedulesigaction.c b/arch/renesas/src/m16c/m16c_schedulesigaction.c index 8217b0e7d466c..58a5fe23e7cb8 100644 --- a/arch/renesas/src/m16c/m16c_schedulesigaction.c +++ b/arch/renesas/src/m16c/m16c_schedulesigaction.c @@ -74,73 +74,33 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ - - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the - * interrupted task is the same as the one that - * must receive the signal, then we will have to modify - * the return state as well as the state in the TCB. - */ - - else - { - /* Save the return PC and SR and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - tcb->xcp.saved_pc[0] = up_current_regs()[REG_PC]; - tcb->xcp.saved_pc[1] = up_current_regs()[REG_PC + 1]; - tcb->xcp.saved_flg = up_current_regs()[REG_FLG]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver >> 8; - up_current_regs()[REG_PC + 1] = (uint32_t)renesas_sigdeliver; - up_current_regs()[REG_FLG] &= ~M16C_FLG_I; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ + /* In this case just deliver the signal now. */ - renesas_copystate(tcb->xcp.regs, up_current_regs()); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. */ else @@ -150,17 +110,49 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * the signals have been delivered. */ - tcb->xcp.saved_pc[0] = tcb->xcp.regs[REG_PC]; - tcb->xcp.saved_pc[1] = tcb->xcp.regs[REG_PC + 1]; - tcb->xcp.saved_flg = tcb->xcp.regs[REG_FLG]; + tcb->xcp.saved_pc[0] = up_current_regs()[REG_PC]; + tcb->xcp.saved_pc[1] = up_current_regs()[REG_PC + 1]; + tcb->xcp.saved_flg = up_current_regs()[REG_FLG]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver >> 8; - tcb->xcp.regs[REG_PC + 1] = (uint32_t)renesas_sigdeliver; - tcb->xcp.regs[REG_FLG] &= ~M16C_FLG_I; + up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver >> 8; + up_current_regs()[REG_PC + 1] = (uint32_t)renesas_sigdeliver; + up_current_regs()[REG_FLG] &= ~M16C_FLG_I; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + renesas_copystate(tcb->xcp.regs, up_current_regs()); } } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save the return PC and SR and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_pc[0] = tcb->xcp.regs[REG_PC]; + tcb->xcp.saved_pc[1] = tcb->xcp.regs[REG_PC + 1]; + tcb->xcp.saved_flg = tcb->xcp.regs[REG_FLG]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver >> 8; + tcb->xcp.regs[REG_PC + 1] = (uint32_t)renesas_sigdeliver; + tcb->xcp.regs[REG_FLG] &= ~M16C_FLG_I; + } } diff --git a/arch/renesas/src/m16c/m16c_sigdeliver.c b/arch/renesas/src/m16c/m16c_sigdeliver.c index 52cd6703af367..9fe660a59e9c7 100644 --- a/arch/renesas/src/m16c/m16c_sigdeliver.c +++ b/arch/renesas/src/m16c/m16c_sigdeliver.c @@ -58,8 +58,8 @@ void renesas_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the return state on the stack. */ @@ -75,7 +75,7 @@ void renesas_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)sig_rtcb->xcp.sigdeliver)(rtcb); + (sig_rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -95,10 +95,10 @@ void renesas_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_PC] = rtcb->xcp.saved_pc[0]; - regs[REG_PC + 1] = rtcb->xcp.saved_pc[1]; - regs[REG_FLG] = rtcb->xcp.saved_flg; - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + regs[REG_PC] = rtcb->xcp.saved_pc[0]; + regs[REG_PC + 1] = rtcb->xcp.saved_pc[1]; + regs[REG_FLG] = rtcb->xcp.saved_flg; + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of * execution. diff --git a/arch/renesas/src/rx65n/rx65n_schedulesigaction.c b/arch/renesas/src/rx65n/rx65n_schedulesigaction.c index 7798d47258d95..bdbe03cb96a17 100644 --- a/arch/renesas/src/rx65n/rx65n_schedulesigaction.c +++ b/arch/renesas/src/rx65n/rx65n_schedulesigaction.c @@ -74,71 +74,33 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ - - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the - * interrupted task is the same as the one that - * must receive the signal, then we will have to modify - * the return state as well as the state in the TCB. - */ - - else - { - /* Save the return PC and SR and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - tcb->xcp.saved_pc = up_current_regs()[REG_PC]; - tcb->xcp.saved_sr = up_current_regs()[REG_PSW]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver; - up_current_regs()[REG_PSW] |= 0x00030000; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ + /* In this case just deliver the signal now. */ - renesas_copystate(tcb->xcp.regs, up_current_regs()); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. */ else @@ -148,15 +110,45 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * the signals have been delivered. */ - tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; - tcb->xcp.saved_sr = tcb->xcp.regs[REG_PSW]; + tcb->xcp.saved_pc = up_current_regs()[REG_PC]; + tcb->xcp.saved_sr = up_current_regs()[REG_PSW]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver; - tcb->xcp.regs[REG_PSW] |= 0x00030000; + up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver; + up_current_regs()[REG_PSW] |= 0x00030000; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + renesas_copystate(tcb->xcp.regs, up_current_regs()); } } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save the return PC and SR and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; + tcb->xcp.saved_sr = tcb->xcp.regs[REG_PSW]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver; + tcb->xcp.regs[REG_PSW] |= 0x00030000; + } } diff --git a/arch/renesas/src/rx65n/rx65n_sigdeliver.c b/arch/renesas/src/rx65n/rx65n_sigdeliver.c index 5c8d50b1092eb..d18f632f461fd 100644 --- a/arch/renesas/src/rx65n/rx65n_sigdeliver.c +++ b/arch/renesas/src/rx65n/rx65n_sigdeliver.c @@ -60,8 +60,8 @@ void renesas_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the real return state on the stack. */ @@ -75,8 +75,8 @@ void renesas_sigdeliver(void) * signals. */ - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; + sigdeliver = rtcb->sigdeliver; + rtcb->sigdeliver = NULL; #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always diff --git a/arch/renesas/src/sh1/sh1_schedulesigaction.c b/arch/renesas/src/sh1/sh1_schedulesigaction.c index 8c020741f3052..c5271a566ed33 100644 --- a/arch/renesas/src/sh1/sh1_schedulesigaction.c +++ b/arch/renesas/src/sh1/sh1_schedulesigaction.c @@ -74,71 +74,33 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ - - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the - * interrupted task is the same as the one that - * must receive the signal, then we will have to modify - * the return state as well as the state in the TCB. - */ - - else - { - /* Save the return PC and SR and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - tcb->xcp.saved_pc = up_current_regs()[REG_PC]; - tcb->xcp.saved_sr = up_current_regs()[REG_SR]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver; - up_current_regs()[REG_SR] |= 0x000000f0; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ + /* In this case just deliver the signal now. */ - renesas_copystate(tcb->xcp.regs, up_current_regs()); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. */ else @@ -148,15 +110,45 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * the signals have been delivered. */ - tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; - tcb->xcp.saved_sr = tcb->xcp.regs[REG_SR]; + tcb->xcp.saved_pc = up_current_regs()[REG_PC]; + tcb->xcp.saved_sr = up_current_regs()[REG_SR]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver; - tcb->xcp.regs[REG_SR] |= 0x000000f0 ; + up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver; + up_current_regs()[REG_SR] |= 0x000000f0; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + renesas_copystate(tcb->xcp.regs, up_current_regs()); } } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save the return PC and SR and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; + tcb->xcp.saved_sr = tcb->xcp.regs[REG_SR]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver; + tcb->xcp.regs[REG_SR] |= 0x000000f0 ; + } } diff --git a/arch/renesas/src/sh1/sh1_sigdeliver.c b/arch/renesas/src/sh1/sh1_sigdeliver.c index d32166906c4be..48b2cc7f5d8ee 100644 --- a/arch/renesas/src/sh1/sh1_sigdeliver.c +++ b/arch/renesas/src/sh1/sh1_sigdeliver.c @@ -58,8 +58,8 @@ void renesas_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the return state on the stack. */ @@ -75,7 +75,7 @@ void renesas_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -95,9 +95,9 @@ void renesas_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_PC] = rtcb->xcp.saved_pc; - regs[REG_SR] = rtcb->xcp.saved_sr; - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + regs[REG_PC] = rtcb->xcp.saved_pc; + regs[REG_SR] = rtcb->xcp.saved_sr; + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/risc-v/include/irq.h b/arch/risc-v/include/irq.h index 40f6275fd91c3..bbae16033e6aa 100644 --- a/arch/risc-v/include/irq.h +++ b/arch/risc-v/include/irq.h @@ -567,12 +567,6 @@ struct xcptcontext { - /* The following function pointer is non-NULL if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These additional register save locations are used to implement the * signal delivery trampoline. * diff --git a/arch/risc-v/src/common/riscv_schedulesigaction.c b/arch/risc-v/src/common/riscv_schedulesigaction.c index d886443d9ee0e..076d11f1fb1ec 100644 --- a/arch/risc-v/src/common/riscv_schedulesigaction.c +++ b/arch/risc-v/src/common/riscv_schedulesigaction.c @@ -76,89 +76,63 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { uintptr_t int_ctx; - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to task that is currently executing on any CPU. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - else - { -#ifdef CONFIG_SMP - int cpu = tcb->cpu; - int me = this_cpu(); - - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - } -#endif - - /* Save the return EPC and STATUS registers. These will be - * by the signal trampoline after the signal has been delivered. - */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + else + { + /* Save the return EPC and STATUS registers. These will be + * by the signal trampoline after the signal has been delivered. + */ - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + tcb->xcp.saved_regs = tcb->xcp.regs; - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (uintreg_t *) - ((uintptr_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); + tcb->xcp.regs = (uintreg_t *) + ((uintptr_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uintptr_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uintptr_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode to be - * here. - */ + /* Then set up to vector to the trampoline with interrupts + * disabled. We must already be in privileged thread mode to be + * here. + */ - tcb->xcp.regs[REG_EPC] = (uintptr_t)riscv_sigdeliver; + tcb->xcp.regs[REG_EPC] = (uintptr_t)riscv_sigdeliver; - int_ctx = tcb->xcp.regs[REG_INT_CTX]; - int_ctx &= ~STATUS_PIE; + int_ctx = tcb->xcp.regs[REG_INT_CTX]; + int_ctx &= ~STATUS_PIE; #ifndef CONFIG_BUILD_FLAT - int_ctx |= STATUS_PPP; + int_ctx |= STATUS_PPP; #endif - tcb->xcp.regs[REG_INT_CTX] = int_ctx; -#ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } -#endif - } + tcb->xcp.regs[REG_INT_CTX] = int_ctx; } } diff --git a/arch/risc-v/src/common/riscv_sigdeliver.c b/arch/risc-v/src/common/riscv_sigdeliver.c index a9d63a66b3cd0..3d8e8f8841531 100644 --- a/arch/risc-v/src/common/riscv_sigdeliver.c +++ b/arch/risc-v/src/common/riscv_sigdeliver.c @@ -69,8 +69,8 @@ void riscv_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); retry: #ifdef CONFIG_SMP @@ -102,7 +102,7 @@ void riscv_sigdeliver(void) /* Deliver the signals */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -147,7 +147,7 @@ void riscv_sigdeliver(void) * could be modified by a hostile program. */ - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of * execution. diff --git a/arch/risc-v/src/esp32c3-legacy/esp32c3_ble_adapter.c b/arch/risc-v/src/esp32c3-legacy/esp32c3_ble_adapter.c index 44f20362f7964..75a7b72fe3930 100644 --- a/arch/risc-v/src/esp32c3-legacy/esp32c3_ble_adapter.c +++ b/arch/risc-v/src/esp32c3-legacy/esp32c3_ble_adapter.c @@ -888,15 +888,10 @@ static int IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw) static void esp_update_time(struct timespec *timespec, uint32_t ticks) { - uint32_t tmp; + struct timespec ts; - tmp = TICK2SEC(ticks); - timespec->tv_sec += tmp; - - ticks -= SEC2TICK(tmp); - tmp = TICK2NSEC(ticks); - - timespec->tv_nsec += tmp; + clock_ticks2time(&ts, ticks); + clock_timespec_add(timespec, &ts, timespec); } /**************************************************************************** diff --git a/arch/risc-v/src/esp32c3-legacy/esp32c3_wifi_adapter.c b/arch/risc-v/src/esp32c3-legacy/esp32c3_wifi_adapter.c index 78193acdaddf7..e946c12131347 100644 --- a/arch/risc-v/src/esp32c3-legacy/esp32c3_wifi_adapter.c +++ b/arch/risc-v/src/esp32c3-legacy/esp32c3_wifi_adapter.c @@ -858,15 +858,10 @@ static void esp_thread_semphr_free(void *semphr) static void esp_update_time(struct timespec *timespec, uint32_t ticks) { - uint32_t tmp; - - tmp = TICK2SEC(ticks); - timespec->tv_sec += tmp; - - ticks -= SEC2TICK(tmp); - tmp = TICK2NSEC(ticks); + struct timespec ts; - timespec->tv_nsec += tmp; + clock_ticks2time(&ts, ticks); + clock_timespec_add(timespec, &ts, timespec); } /**************************************************************************** diff --git a/arch/risc-v/src/esp32c3/esp_wifi_adapter.c b/arch/risc-v/src/esp32c3/esp_wifi_adapter.c index dd453ab82dd84..350bc2e90013c 100644 --- a/arch/risc-v/src/esp32c3/esp_wifi_adapter.c +++ b/arch/risc-v/src/esp32c3/esp_wifi_adapter.c @@ -3144,15 +3144,10 @@ static void esp_nvs_close(uint32_t handle) static void esp_update_time(struct timespec *timespec, uint32_t ticks) { - uint32_t tmp; - - tmp = TICK2SEC(ticks); - timespec->tv_sec += tmp; - - ticks -= SEC2TICK(tmp); - tmp = TICK2NSEC(ticks); + struct timespec ts; - timespec->tv_nsec += tmp; + clock_ticks2time(&ts, ticks); + clock_timespec_add(timespec, &ts, timespec); } #ifdef ESP_WLAN_HAS_STA diff --git a/arch/risc-v/src/esp32c6/esp_wifi_adapter.c b/arch/risc-v/src/esp32c6/esp_wifi_adapter.c index a233634a0421d..b926318a2c31b 100644 --- a/arch/risc-v/src/esp32c6/esp_wifi_adapter.c +++ b/arch/risc-v/src/esp32c6/esp_wifi_adapter.c @@ -3098,15 +3098,10 @@ static void esp_nvs_close(uint32_t handle) static void esp_update_time(struct timespec *timespec, uint32_t ticks) { - uint32_t tmp; - - tmp = TICK2SEC(ticks); - timespec->tv_sec += tmp; - - ticks -= SEC2TICK(tmp); - tmp = TICK2NSEC(ticks); + struct timespec ts; - timespec->tv_nsec += tmp; + clock_ticks2time(&ts, ticks); + clock_timespec_add(timespec, &ts, timespec); } #ifdef ESP_WLAN_HAS_STA diff --git a/arch/sim/include/irq.h b/arch/sim/include/irq.h index 1b2d31b024287..af25d57f5d53a 100644 --- a/arch/sim/include/irq.h +++ b/arch/sim/include/irq.h @@ -51,7 +51,6 @@ struct xcptcontext { - void *sigdeliver; /* Actual type is sig_deliver_t */ jmp_buf regs; }; diff --git a/arch/sim/src/sim/sim_heap.c b/arch/sim/src/sim/sim_heap.c index a3ccb2bb406c3..e95b559ff1213 100644 --- a/arch/sim/src/sim/sim_heap.c +++ b/arch/sim/src/sim/sim_heap.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "sim_internal.h" @@ -185,6 +186,7 @@ static void mm_delayfree(struct mm_heap_s *heap, void *mem, bool delay) int size = host_mallocsize(mem); atomic_fetch_sub(&heap->aordblks, 1); atomic_fetch_sub(&heap->uordblks, size); + sched_note_heap(NOTE_HEAP_FREE, heap, mem, size, 0); host_free(mem); } } @@ -228,9 +230,37 @@ struct mm_heap_s *mm_initialize(const char *name, procfs_register_meminfo(&heap->mm_procfs); #endif + sched_note_heap(NOTE_HEAP_ADD, heap, heap_start, heap_size, 0); return heap; } +/**************************************************************************** + * Name: mm_uninitialize + * + * Description: + * Uninitialize the selected heap data structures + * + * Input Parameters: + * heap - The selected heap + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void mm_uninitialize(struct mm_heap_s *heap) +{ + sched_note_heap(NOTE_HEAP_REMOVE, heap, NULL, 0, 0); + +#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MEMINFO) + procfs_unregister_meminfo(&heap->mm_procfs); +#endif + mm_free_delaylist(heap); + host_free(heap); +} + /**************************************************************************** * Name: mm_addregion * @@ -339,6 +369,7 @@ void *mm_realloc(struct mm_heap_s *heap, void *oldmem, int uordblks; int usmblks; int newsize; + int oldsize; free_delaylist(heap, false); @@ -348,13 +379,23 @@ void *mm_realloc(struct mm_heap_s *heap, void *oldmem, return NULL; } - atomic_fetch_sub(&heap->uordblks, host_mallocsize(oldmem)); + oldsize = host_mallocsize(oldmem); + atomic_fetch_sub(&heap->uordblks, oldsize); mem = host_realloc(oldmem, size); atomic_fetch_add(&heap->aordblks, oldmem == NULL && mem != NULL); newsize = host_mallocsize(mem ? mem : oldmem); atomic_fetch_add(&heap->uordblks, newsize); usmblks = atomic_load(&heap->usmblks); + if (mem != NULL) + { + if (oldmem != NULL) + { + sched_note_heap(NOTE_HEAP_FREE, heap, oldmem, oldsize, 0); + } + + sched_note_heap(NOTE_HEAP_ALLOC, heap, mem, newsize, 0); + } do { @@ -445,6 +486,7 @@ void *mm_memalign(struct mm_heap_s *heap, size_t alignment, size_t size) } size = host_mallocsize(mem); + sched_note_heap(NOTE_HEAP_ALLOC, heap, mem, size, 0); atomic_fetch_add(&heap->aordblks, 1); atomic_fetch_add(&heap->uordblks, size); usmblks = atomic_load(&heap->usmblks); diff --git a/arch/sim/src/sim/sim_schedulesigaction.c b/arch/sim/src/sim/sim_schedulesigaction.c index 4e6ab46831f27..6bc8aa535b81d 100644 --- a/arch/sim/src/sim/sim_schedulesigaction.c +++ b/arch/sim/src/sim/sim_schedulesigaction.c @@ -71,27 +71,15 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - irqstate_t flags; - /* We don't have to anything complex for the simulated target */ - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - - /* Make sure that interrupts are disabled */ + sinfo("tcb=%p\n", tcb); - flags = enter_critical_section(); - - if (tcb->xcp.sigdeliver == NULL) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - if (tcb == this_task()) - { - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - - leave_critical_section(flags); } diff --git a/arch/sim/src/sim/sim_sigdeliver.c b/arch/sim/src/sim/sim_sigdeliver.c index eca8c3bf91045..238599c757066 100644 --- a/arch/sim/src/sim/sim_sigdeliver.c +++ b/arch/sim/src/sim/sim_sigdeliver.c @@ -61,7 +61,7 @@ void sim_sigdeliver(void) int16_t saved_irqcount; irqstate_t flags; #endif - if (NULL == (rtcb->xcp.sigdeliver)) + if (NULL == (rtcb->sigdeliver)) { return; } @@ -75,8 +75,8 @@ void sim_sigdeliver(void) #endif sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* NOTE: we do not save the return state for sim */ @@ -103,7 +103,7 @@ void sim_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -135,7 +135,7 @@ void sim_sigdeliver(void) /* Allows next handler to be scheduled */ - rtcb->xcp.sigdeliver = NULL; + rtcb->sigdeliver = NULL; /* NOTE: we leave a critical section here for sim */ diff --git a/arch/sparc/include/sparc_v8/irq.h b/arch/sparc/include/sparc_v8/irq.h index fa5c77b362ed1..527f756a7c47c 100644 --- a/arch/sparc/include/sparc_v8/irq.h +++ b/arch/sparc/include/sparc_v8/irq.h @@ -427,12 +427,6 @@ struct xcpt_syscall_s struct xcptcontext { - /* The following function pointer is non-NULL if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These additional register save locations are used to implement the * signal delivery trampoline. * diff --git a/arch/sparc/src/sparc_v8/sparc_v8_schedulesigaction.c b/arch/sparc/src/sparc_v8/sparc_v8_schedulesigaction.c index 2f50eb397226f..e54871576aa3a 100644 --- a/arch/sparc/src/sparc_v8/sparc_v8_schedulesigaction.c +++ b/arch/sparc/src/sparc_v8/sparc_v8_schedulesigaction.c @@ -72,249 +72,140 @@ ****************************************************************************/ #ifndef CONFIG_SMP -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - irqstate_t flags; + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - /* Make sure that interrupts are disabled */ - - flags = enter_critical_section(); - - /* Refuse to handle nested signal actions */ - - if (!tcb->xcp.sigdeliver) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ - - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the - * interrupted task is the same as the one that - * must receive the signal, then we will have to modify - * the return state as well as the state in the TCB. - * - * Hmmm... there looks like a latent bug here: The following - * logic would fail in the strange case where we are in an - * interrupt handler, the thread is signalling itself, but - * a context switch to another task has occurred so that - * current_regs does not refer to the thread of this_task()! - */ - - else - { - /* Save registers that must be protected while the signal - * handler runs. These will be restored by the signal - * trampoline after the signal(s) have been delivered. - */ - - tcb->xcp.saved_pc = up_current_regs()[REG_PC]; - tcb->xcp.saved_npc = up_current_regs()[REG_NPC]; - tcb->xcp.saved_status = up_current_regs()[REG_PSR]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_PC] = (uint32_t)sparc_sigdeliver; - up_current_regs()[REG_NPC] = (uint32_t)sparc_sigdeliver + 4; - up_current_regs()[REG_PSR] |= SPARC_PSR_ET_MASK; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ + /* In this case just deliver the signal now. */ - sparc_savestate(tcb->xcp.regs); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. + * + * Hmmm... there looks like a latent bug here: The following + * logic would fail in the strange case where we are in an + * interrupt handler, the thread is signalling itself, but + * a context switch to another task has occurred so that + * current_regs does not refer to the thread of this_task()! */ else { - /* Save registers that must be protected while the signal handler - * runs. These will be restored by the signal trampoline after - * the signals have been delivered. + /* Save registers that must be protected while the signal + * handler runs. These will be restored by the signal + * trampoline after the signal(s) have been delivered. */ - tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; - tcb->xcp.saved_npc = tcb->xcp.regs[REG_NPC]; - tcb->xcp.saved_status = tcb->xcp.regs[REG_PSR]; + tcb->xcp.saved_pc = up_current_regs()[REG_PC]; + tcb->xcp.saved_npc = up_current_regs()[REG_NPC]; + tcb->xcp.saved_status = up_current_regs()[REG_PSR]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_PC] = (uint32_t)sparc_sigdeliver; - tcb->xcp.regs[REG_NPC] = (uint32_t)sparc_sigdeliver + 4; - tcb->xcp.regs[REG_PSR] |= SPARC_PSR_ET_MASK; + up_current_regs()[REG_PC] = (uint32_t)sparc_sigdeliver; + up_current_regs()[REG_NPC] = (uint32_t)sparc_sigdeliver + 4; + up_current_regs()[REG_PSR] |= SPARC_PSR_ET_MASK; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + sparc_savestate(tcb->xcp.regs); } } - leave_critical_section(flags); + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save registers that must be protected while the signal handler + * runs. These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; + tcb->xcp.saved_npc = tcb->xcp.regs[REG_NPC]; + tcb->xcp.saved_status = tcb->xcp.regs[REG_PSR]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)sparc_sigdeliver; + tcb->xcp.regs[REG_NPC] = (uint32_t)sparc_sigdeliver + 4; + tcb->xcp.regs[REG_PSR] |= SPARC_PSR_ET_MASK; + } } #endif /* !CONFIG_SMP */ #ifdef CONFIG_SMP -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - irqstate_t flags; int cpu; int me; - sinfo("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver); - - /* Make sure that interrupts are disabled */ + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - flags = enter_critical_section(); + /* First, handle some special cases when the signal is being delivered + * to task that is currently executing on any CPU. + */ - /* Refuse to handle nested signal actions */ - - if (!tcb->xcp.sigdeliver) + if (tcb->task_state == TSTATE_TASK_RUNNING) { - tcb->xcp.sigdeliver = sigdeliver; + me = this_cpu(); + cpu = tcb->cpu; - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. + /* CASE 1: We are not in an interrupt handler and a task is + * signaling itself for some reason. */ - sinfo("rtcb=0x%p current_regs=0x%p\n", this_task(), up_current_regs()); - - if (tcb->task_state == TSTATE_TASK_RUNNING) + if (cpu == me && !up_current_regs()) { - me = this_cpu(); - cpu = tcb->cpu; - - /* CASE 1: We are not in an interrupt handler and a task is - * signaling itself for some reason. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - if (cpu == me && !up_current_regs()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: The task that needs to receive the signal is running. - * This could happen if the task is running on another CPU OR if - * we are in an interrupt handler and the task is running on this - * CPU. In the former case, we will have to PAUSE the other CPU - * first. But in either case, we will have to modify the return - * state as well as the state in the TCB. - */ - - else - { - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ - - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - - /* Now tcb on the other CPU can be accessed safely */ - - /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; - tcb->xcp.saved_npc = tcb->xcp.regs[REG_NPC]; - tcb->xcp.saved_status = tcb->xcp.regs[REG_PSR]; - - /* Then set up vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode - * to be here. - */ - - tcb->xcp.regs[REG_PC] = (uint32_t)sparc_sigdeliver; - tcb->xcp.regs[REG_NPC] = (uint32_t)sparc_sigdeliver + 4; - tcb->xcp.regs[REG_PSR] |= SPARC_PSR_ET_MASK; - } - else - { - /* tcb is running on the same CPU */ - - /* Save registers that must be protected while the signal - * handler runs. These will be restored by the signal - * trampoline after the signal(s) have been delivered. - */ - - tcb->xcp.saved_pc = up_current_regs()[REG_PC]; - tcb->xcp.saved_npc = up_current_regs()[REG_NPC]; - tcb->xcp.saved_status = up_current_regs()[REG_PSR]; - - /* Then set up vector to the trampoline with interrupts - * disabled. The kernel-space trampoline must run in - * privileged thread mode. - */ - - up_current_regs()[REG_PC] = (uint32_t)sparc_sigdeliver; - up_current_regs()[REG_NPC] = (uint32_t)sparc_sigdeliver - + 4; - up_current_regs()[REG_PSR] |= SPARC_PSR_ET_MASK; - - /* And make sure that the saved context in the TCB is the - * same as the interrupt return context. - */ - - sparc_savestate(tcb->xcp.regs); - } - - /* NOTE: If the task runs on another CPU(cpu), adjusting - * global IRQ controls will be done in the pause handler - * on the CPU(cpu) by taking a critical section. - * If the task is scheduled on this CPU(me), do nothing - * because this CPU already took a critical section - */ - - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signaling some other non-running task. + /* CASE 2: The task that needs to receive the signal is running. + * This could happen if the task is running on another CPU OR if + * we are in an interrupt handler and the task is running on this + * CPU. In the former case, we will have to PAUSE the other CPU + * first. But in either case, we will have to modify the return + * state as well as the state in the TCB. */ else { + /* tcb is running on the same CPU */ + /* Save registers that must be protected while the signal * handler runs. These will be restored by the signal * trampoline after the signal(s) have been delivered. @@ -324,17 +215,48 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) tcb->xcp.saved_npc = up_current_regs()[REG_NPC]; tcb->xcp.saved_status = up_current_regs()[REG_PSR]; - /* Then set up to vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode to be - * here. + /* Then set up vector to the trampoline with interrupts + * disabled. The kernel-space trampoline must run in + * privileged thread mode. + */ + + up_current_regs()[REG_PC] = (uint32_t)sparc_sigdeliver; + up_current_regs()[REG_NPC] = (uint32_t)sparc_sigdeliver + + 4; + up_current_regs()[REG_PSR] |= SPARC_PSR_ET_MASK; + + /* And make sure that the saved context in the TCB is the + * same as the interrupt return context. */ - tcb->xcp.regs[REG_PC] = (uint32_t)sparc_sigdeliver; - tcb->xcp.regs[REG_NPC] = (uint32_t)sparc_sigdeliver + 4; - tcb->xcp.regs[REG_PSR] |= SPARC_PSR_ET_MASK; + sparc_savestate(tcb->xcp.regs); } } - leave_critical_section(flags); + /* Otherwise, we are (1) signaling a task is not running from an + * interrupt handler or (2) we are not in an interrupt handler and the + * running task is signaling some other non-running task. + */ + + else + { + /* Save registers that must be protected while the signal + * handler runs. These will be restored by the signal + * trampoline after the signal(s) have been delivered. + */ + + tcb->xcp.saved_pc = up_current_regs()[REG_PC]; + tcb->xcp.saved_npc = up_current_regs()[REG_NPC]; + tcb->xcp.saved_status = up_current_regs()[REG_PSR]; + + /* Then set up to vector to the trampoline with interrupts + * disabled. We must already be in privileged thread mode to be + * here. + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)sparc_sigdeliver; + tcb->xcp.regs[REG_NPC] = (uint32_t)sparc_sigdeliver + 4; + tcb->xcp.regs[REG_PSR] |= SPARC_PSR_ET_MASK; + } } #endif /* CONFIG_SMP */ diff --git a/arch/sparc/src/sparc_v8/sparc_v8_sigdeliver.c b/arch/sparc/src/sparc_v8/sparc_v8_sigdeliver.c index 06fa3c5b7770f..69caac640ecad 100644 --- a/arch/sparc/src/sparc_v8/sparc_v8_sigdeliver.c +++ b/arch/sparc/src/sparc_v8/sparc_v8_sigdeliver.c @@ -77,8 +77,8 @@ void sparc_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the return state on the stack. */ @@ -114,7 +114,7 @@ void sparc_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -163,10 +163,10 @@ void sparc_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_PC] = rtcb->xcp.saved_pc; - regs[REG_NPC] = rtcb->xcp.saved_npc; - regs[REG_PSR] = rtcb->xcp.saved_status; - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + regs[REG_PC] = rtcb->xcp.saved_pc; + regs[REG_NPC] = rtcb->xcp.saved_npc; + regs[REG_PSR] = rtcb->xcp.saved_status; + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ #ifdef CONFIG_SMP /* Restore the saved 'irqcount' and recover the critical section diff --git a/arch/tricore/include/tc3xx/irq.h b/arch/tricore/include/tc3xx/irq.h index 7b0394fd4e628..39b35ba97ae81 100644 --- a/arch/tricore/include/tc3xx/irq.h +++ b/arch/tricore/include/tc3xx/irq.h @@ -116,12 +116,6 @@ #ifndef __ASSEMBLY__ struct xcptcontext { - /* The following function pointer is non-zero if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of the context used during * signal processing. */ diff --git a/arch/tricore/src/common/tricore_schedulesigaction.c b/arch/tricore/src/common/tricore_schedulesigaction.c index 7b82a95746ccf..bc62436d4b0bb 100644 --- a/arch/tricore/src/common/tricore_schedulesigaction.c +++ b/arch/tricore/src/common/tricore_schedulesigaction.c @@ -76,88 +76,81 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (tcb->xcp.sigdeliver == NULL) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - if (tcb == this_task()) + if (up_current_regs() == NULL) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ - - if (up_current_regs() == NULL) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the - * interrupted task is the same as the one that - * must receive the signal, then we will have to modify - * the return state as well as the state in the TCB. - * - * Hmmm... there looks like a latent bug here: The following - * logic would fail in the strange case where we are in an - * interrupt handler, the thread is signalling itself, but - * a context switch to another task has occurred so that - * g_current_regs does not refer to the thread of this_task()! - */ - - else - { - /* Save the context registers. These will be - * restored by the signal trampoline after the signals have - * been delivered. - */ + /* In this case just deliver the signal now. */ - tricore_savestate(tcb->xcp.saved_regs); - - /* Create a new CSA for signal delivery. The new context - * will borrow the process stack of the current tcb. - */ - - up_set_current_regs(tricore_alloc_csa((uintptr_t) - tricore_sigdeliver, - STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)), - PSW_IO_SUPERVISOR | PSW_CDE, true)); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. + * + * Hmmm... there looks like a latent bug here: The following + * logic would fail in the strange case where we are in an + * interrupt handler, the thread is signalling itself, but + * a context switch to another task has occurred so that + * g_current_regs does not refer to the thread of this_task()! */ else { - /* Save the return EPC and STATUS registers. These will be + /* Save the context registers. These will be * restored by the signal trampoline after the signals have * been delivered. */ - /* Save the current register context location */ - - tcb->xcp.saved_regs = tcb->xcp.regs; + tricore_savestate(tcb->xcp.saved_regs); /* Create a new CSA for signal delivery. The new context * will borrow the process stack of the current tcb. */ - tcb->xcp.regs = tricore_alloc_csa((uintptr_t)tricore_sigdeliver, - STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)), - PSW_IO_SUPERVISOR | PSW_CDE, true); + up_set_current_regs(tricore_alloc_csa((uintptr_t) + tricore_sigdeliver, + STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)), + PSW_IO_SUPERVISOR | PSW_CDE, true)); } } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save the return EPC and STATUS registers. These will be + * restored by the signal trampoline after the signals have + * been delivered. + */ + + /* Save the current register context location */ + + tcb->xcp.saved_regs = tcb->xcp.regs; + + /* Create a new CSA for signal delivery. The new context + * will borrow the process stack of the current tcb. + */ + + tcb->xcp.regs = tricore_alloc_csa((uintptr_t)tricore_sigdeliver, + STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)), + PSW_IO_SUPERVISOR | PSW_CDE, true); + } } diff --git a/arch/tricore/src/common/tricore_sigdeliver.c b/arch/tricore/src/common/tricore_sigdeliver.c index 9888597b9b7c1..e06ac8d046bc8 100644 --- a/arch/tricore/src/common/tricore_sigdeliver.c +++ b/arch/tricore/src/common/tricore_sigdeliver.c @@ -59,8 +59,8 @@ void tricore_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); retry: @@ -74,7 +74,7 @@ void tricore_sigdeliver(void) /* Deliver the signal */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -106,7 +106,7 @@ void tricore_sigdeliver(void) * could be modified by a hostile program. */ - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of * execution. diff --git a/arch/x86/include/i486/irq.h b/arch/x86/include/i486/irq.h index ce6c58bade18b..144618fa4640f 100644 --- a/arch/x86/include/i486/irq.h +++ b/arch/x86/include/i486/irq.h @@ -151,12 +151,6 @@ #ifndef __ASSEMBLY__ struct xcptcontext { - /* The following function pointer is non-zero if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of instruction pointer and EFLAGS used during * signal processing. * diff --git a/arch/x86/src/i486/i486_schedulesigaction.c b/arch/x86/src/i486/i486_schedulesigaction.c index 30770529ecedd..219d3aa9bbd75 100644 --- a/arch/x86/src/i486/i486_schedulesigaction.c +++ b/arch/x86/src/i486/i486_schedulesigaction.c @@ -70,95 +70,87 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ - - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the interrupted task - * is the same as the one that must receive the signal, then we - * will have to modify the return state as well as the state in the - * TCB. - * - * Hmmm... there looks like a latent bug here: The following logic - * would fail in the strange case where we are in an interrupt - * handler, the thread is signalling itself, but a context switch - * to another task has occurred so that g_current_regs does not - * refer to the thread of this_task()! - */ - - else - { - /* Save the return lr and cpsr and one scratch register. These - * will be restored by the signal trampoline after the signals - * have been delivered. - */ + /* In this case just deliver the signal now. */ - tcb->xcp.saved_eip = up_current_regs()[REG_EIP]; - tcb->xcp.saved_eflags = up_current_regs()[REG_EFLAGS]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_EIP] = (uint32_t)x86_sigdeliver; - up_current_regs()[REG_EFLAGS] = 0; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - x86_savestate(tcb->xcp.regs); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. + /* CASE 2: We are in an interrupt handler AND the interrupted task + * is the same as the one that must receive the signal, then we + * will have to modify the return state as well as the state in the + * TCB. + * + * Hmmm... there looks like a latent bug here: The following logic + * would fail in the strange case where we are in an interrupt + * handler, the thread is signalling itself, but a context switch + * to another task has occurred so that g_current_regs does not + * refer to the thread of this_task()! */ else { - /* Save the return lr and cpsr and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. + /* Save the return lr and cpsr and one scratch register. These + * will be restored by the signal trampoline after the signals + * have been delivered. */ - tcb->xcp.saved_eip = tcb->xcp.regs[REG_EIP]; - tcb->xcp.saved_eflags = tcb->xcp.regs[REG_EFLAGS]; + tcb->xcp.saved_eip = up_current_regs()[REG_EIP]; + tcb->xcp.saved_eflags = up_current_regs()[REG_EFLAGS]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_EIP] = (uint32_t)x86_sigdeliver; - tcb->xcp.regs[REG_EFLAGS] = 0; + up_current_regs()[REG_EIP] = (uint32_t)x86_sigdeliver; + up_current_regs()[REG_EFLAGS] = 0; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + x86_savestate(tcb->xcp.regs); } } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_eip = tcb->xcp.regs[REG_EIP]; + tcb->xcp.saved_eflags = tcb->xcp.regs[REG_EFLAGS]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_EIP] = (uint32_t)x86_sigdeliver; + tcb->xcp.regs[REG_EFLAGS] = 0; + } } diff --git a/arch/x86/src/i486/i486_sigdeliver.c b/arch/x86/src/i486/i486_sigdeliver.c index 9ddf0ace415b9..48ef001468091 100644 --- a/arch/x86/src/i486/i486_sigdeliver.c +++ b/arch/x86/src/i486/i486_sigdeliver.c @@ -59,8 +59,8 @@ void x86_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the return state on the stack. */ @@ -76,7 +76,7 @@ void x86_sigdeliver(void) /* Deliver the signals */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -96,9 +96,9 @@ void x86_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_EIP] = rtcb->xcp.saved_eip; - regs[REG_EFLAGS] = rtcb->xcp.saved_eflags; - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + regs[REG_EIP] = rtcb->xcp.saved_eip; + regs[REG_EFLAGS] = rtcb->xcp.saved_eflags; + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/x86_64/include/intel64/irq.h b/arch/x86_64/include/intel64/irq.h index 78ebfa4135acd..f4831c05b9173 100644 --- a/arch/x86_64/include/intel64/irq.h +++ b/arch/x86_64/include/intel64/irq.h @@ -495,12 +495,6 @@ enum ioapic_trigger_mode struct xcptcontext { - /* The following function pointer is non-zero if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of instruction pointer and EFLAGS used during * signal processing. */ diff --git a/arch/x86_64/src/intel64/intel64_schedulesigaction.c b/arch/x86_64/src/intel64/intel64_schedulesigaction.c index d846ed3798a73..d9d01d23efae2 100644 --- a/arch/x86_64/src/intel64/intel64_schedulesigaction.c +++ b/arch/x86_64/src/intel64/intel64_schedulesigaction.c @@ -71,252 +71,188 @@ ****************************************************************************/ #ifndef CONFIG_SMP -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - sinfo("rtcb=%p g_current_regs=%p\n", this_task(), up_current_regs()); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. */ - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ - - if (!up_current_regs()) - { - /* In this case just deliver the signal with a function call - * now. - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the interrupted task - * is the same as the one that must receive the signal, then we - * will have to modify the return state as well as the state in the - * TCB. - * - * Hmmm... there looks like a latent bug here: The following logic - * would fail in the strange case where we are in an interrupt - * handler, the thread is signalling itself, but a context switch - * to another task has occurred so that current_regs does not - * refer to the thread of this_task()! + /* In this case just deliver the signal with a function call + * now. */ - else - { - /* Save the return lr and cpsr and one scratch register. These - * will be restored by the signal trampoline after the signals - * have been delivered. - */ - - tcb->xcp.saved_rip = up_current_regs()[REG_RIP]; - tcb->xcp.saved_rsp = up_current_regs()[REG_RSP]; - tcb->xcp.saved_rflags = up_current_regs()[REG_RFLAGS]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_RIP] = (uint64_t)x86_64_sigdeliver; - up_current_regs()[REG_RSP] = up_current_regs()[REG_RSP] - 8; - up_current_regs()[REG_RFLAGS] = 0; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - x86_64_savestate(tcb->xcp.regs); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. + /* CASE 2: We are in an interrupt handler AND the interrupted task + * is the same as the one that must receive the signal, then we + * will have to modify the return state as well as the state in the + * TCB. + * + * Hmmm... there looks like a latent bug here: The following logic + * would fail in the strange case where we are in an interrupt + * handler, the thread is signalling itself, but a context switch + * to another task has occurred so that current_regs does not + * refer to the thread of this_task()! */ else { - /* Save the return lr and cpsr and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. + /* Save the return lr and cpsr and one scratch register. These + * will be restored by the signal trampoline after the signals + * have been delivered. */ - tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP]; - tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP]; - tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS]; + tcb->xcp.saved_rip = up_current_regs()[REG_RIP]; + tcb->xcp.saved_rsp = up_current_regs()[REG_RSP]; + tcb->xcp.saved_rflags = up_current_regs()[REG_RFLAGS]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver; - tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8; - tcb->xcp.regs[REG_RFLAGS] = 0; + up_current_regs()[REG_RIP] = (uint64_t)x86_64_sigdeliver; + up_current_regs()[REG_RSP] = up_current_regs()[REG_RSP] - 8; + up_current_regs()[REG_RFLAGS] = 0; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + x86_64_savestate(tcb->xcp.regs); } } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP]; + tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP]; + tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver; + tcb->xcp.regs[REG_RIP] = tcb->xcp.regs[REG_RIP] - 8; + tcb->xcp.regs[REG_RFLAGS] = 0; + } } #else /* !CONFIG_SMP */ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { int cpu; int me; - sinfo("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to task that is currently executing on any CPU. + */ - if (tcb->xcp.sigdeliver == NULL) + if (tcb->task_state == TSTATE_TASK_RUNNING) { - tcb->xcp.sigdeliver = sigdeliver; + me = this_cpu(); + cpu = tcb->cpu; - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. + /* CASE 1: We are not in an interrupt handler and a task is + * signaling itself for some reason. */ - sinfo("rtcb=0x%p current_regs=0x%p\n", this_task(), - up_current_regs()); - - if (tcb->task_state == TSTATE_TASK_RUNNING) + if (cpu == me && !up_current_regs()) { - me = this_cpu(); - cpu = tcb->cpu; - - /* CASE 1: We are not in an interrupt handler and a task is - * signaling itself for some reason. - */ - - if (cpu == me && !up_current_regs()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: The task that needs to receive the signal is running. - * This could happen if the task is running on another CPU OR if - * we are in an interrupt handler and the task is running on this - * CPU. In the former case, we will have to PAUSE the other CPU - * first. But in either case, we will have to modify the return - * state as well as the state in the TCB. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - else - { - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ - - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - - /* Now tcb on the other CPU can be accessed safely */ - - /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP]; - tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP]; - tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver; - tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8; - tcb->xcp.regs[REG_RFLAGS] = 0; - } - else - { - /* tcb is running on the same CPU */ - - /* Save the return lr and cpsr and one scratch register. - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - tcb->xcp.saved_rip = up_current_regs()[REG_RIP]; - tcb->xcp.saved_rsp = up_current_regs()[REG_RSP]; - tcb->xcp.saved_rflags = up_current_regs()[REG_RFLAGS]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_RIP] = - (uint64_t)x86_64_sigdeliver; - up_current_regs()[REG_RSP] = - up_current_regs()[REG_RSP] - 8; - up_current_regs()[REG_RFLAGS] = 0; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - x86_64_savestate(tcb->xcp.regs); - } - - /* NOTE: If the task runs on another CPU(cpu), adjusting - * global IRQ controls will be done in the pause handler - * on the CPU(cpu) by taking a critical section. - * If the task is scheduled on this CPU(me), do nothing - * because this CPU already took a critical section - */ - - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signaling some other non-running task. + /* CASE 2: The task that needs to receive the signal is running. + * This could happen if the task is running on another CPU OR if + * we are in an interrupt handler and the task is running on this + * CPU. In the former case, we will have to PAUSE the other CPU + * first. But in either case, we will have to modify the return + * state as well as the state in the TCB. */ else { - /* Save the return lr and cpsr and one scratch register + /* tcb is running on the same CPU */ + + /* Save the return lr and cpsr and one scratch register. * These will be restored by the signal trampoline after * the signals have been delivered. */ - tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP]; - tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP]; - tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS]; + tcb->xcp.saved_rip = up_current_regs()[REG_RIP]; + tcb->xcp.saved_rsp = up_current_regs()[REG_RSP]; + tcb->xcp.saved_rflags = up_current_regs()[REG_RFLAGS]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver; - tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8; - tcb->xcp.regs[REG_RFLAGS] = 0; + up_current_regs()[REG_RIP] = (uint64_t)x86_64_sigdeliver; + up_current_regs()[REG_RIP] = up_current_regs()[REG_RIP] - 8; + up_current_regs()[REG_RFLAGS] = 0; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + x86_64_savestate(tcb->xcp.regs); } } + + /* Otherwise, we are (1) signaling a task is not running from an + * interrupt handler or (2) we are not in an interrupt handler and the + * running task is signaling some other non-running task. + */ + + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP]; + tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP]; + tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver; + tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8; + tcb->xcp.regs[REG_RFLAGS] = 0; + } } #endif /* CONFIG_SMP */ diff --git a/arch/x86_64/src/intel64/intel64_sigdeliver.c b/arch/x86_64/src/intel64/intel64_sigdeliver.c index a7f5763b424e7..5701291820e6a 100644 --- a/arch/x86_64/src/intel64/intel64_sigdeliver.c +++ b/arch/x86_64/src/intel64/intel64_sigdeliver.c @@ -69,8 +69,8 @@ void x86_64_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Align regs to 64 byte boundary for XSAVE */ @@ -113,7 +113,7 @@ void x86_64_sigdeliver(void) /* Deliver the signals */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -138,10 +138,10 @@ void x86_64_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_RIP] = rtcb->xcp.saved_rip; - regs[REG_RSP] = rtcb->xcp.saved_rsp; - regs[REG_RFLAGS] = rtcb->xcp.saved_rflags; - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + regs[REG_RIP] = rtcb->xcp.saved_rip; + regs[REG_RSP] = rtcb->xcp.saved_rsp; + regs[REG_RFLAGS] = rtcb->xcp.saved_rflags; + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ #ifdef CONFIG_SMP /* Restore the saved 'irqcount' and recover the critical section diff --git a/arch/xtensa/include/irq.h b/arch/xtensa/include/irq.h index 1d299f428e99f..ef681ab58129e 100644 --- a/arch/xtensa/include/irq.h +++ b/arch/xtensa/include/irq.h @@ -178,12 +178,6 @@ struct xcpt_syscall_s struct xcptcontext { - /* The following function pointer is non-zero if there are pending signals - * to be processed. - */ - - void *sigdeliver; /* Actual type is sig_deliver_t */ - /* These are saved copies of registers used during signal processing. * * REVISIT: Because there is only one copy of these save areas, diff --git a/arch/xtensa/src/common/xtensa_schedsigaction.c b/arch/xtensa/src/common/xtensa_schedsigaction.c index 2d3a381583d3a..0a37b5bccada0 100644 --- a/arch/xtensa/src/common/xtensa_schedsigaction.c +++ b/arch/xtensa/src/common/xtensa_schedsigaction.c @@ -78,94 +78,67 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to task that is currently executing on any CPU. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->xcp.sigdeliver = sigdeliver; + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! + */ - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + else + { + /* Save the context registers. These will be restored by the + * signal trampoline after the signals have been delivered. + * + * NOTE: that hi-priority interrupts are not disabled. */ - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ + tcb->xcp.saved_regs = tcb->xcp.regs; - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - else + if ((tcb->xcp.saved_regs[REG_PS] & PS_EXCM_MASK) != 0) { -#ifdef CONFIG_SMP - int cpu = tcb->cpu; - int me = this_cpu(); - - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - } -#endif - - /* Save the context registers. These will be restored by the - * signal trampoline after the signals have been delivered. - * - * NOTE: that hi-priority interrupts are not disabled. - */ - - tcb->xcp.saved_regs = tcb->xcp.regs; - - if ((tcb->xcp.saved_regs[REG_PS] & PS_EXCM_MASK) != 0) - { - tcb->xcp.saved_regs[REG_PS] &= ~PS_EXCM_MASK; - } + tcb->xcp.saved_regs[REG_PS] &= ~PS_EXCM_MASK; + } - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_A1] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_A1] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled - */ + /* Then set up to vector to the trampoline with interrupts + * disabled + */ - tcb->xcp.regs[REG_PC] = (uint32_t)xtensa_sig_deliver; + tcb->xcp.regs[REG_PC] = (uint32_t)xtensa_sig_deliver; #ifdef __XTENSA_CALL0_ABI__ - tcb->xcp.regs[REG_PS] = (uint32_t) - (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM); + tcb->xcp.regs[REG_PS] = (uint32_t) + (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM); #else - tcb->xcp.regs[REG_PS] = (uint32_t) - (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | - PS_WOE | PS_CALLINC(1)); + tcb->xcp.regs[REG_PS] = (uint32_t) + (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | + PS_WOE | PS_CALLINC(1)); #endif #ifndef CONFIG_BUILD_FLAT - xtensa_raiseprivilege(tcb->xcp.regs); + xtensa_raiseprivilege(tcb->xcp.regs); #endif - -#ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } -#endif - } } } diff --git a/arch/xtensa/src/common/xtensa_sigdeliver.c b/arch/xtensa/src/common/xtensa_sigdeliver.c index 97c4f3ded9330..3ea04d309918a 100644 --- a/arch/xtensa/src/common/xtensa_sigdeliver.c +++ b/arch/xtensa/src/common/xtensa_sigdeliver.c @@ -68,8 +68,8 @@ void xtensa_sig_deliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); retry: #ifdef CONFIG_SMP @@ -102,7 +102,7 @@ void xtensa_sig_deliver(void) /* Deliver the signals */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -146,7 +146,7 @@ void xtensa_sig_deliver(void) * could be modified by a hostile program. */ - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/xtensa/src/esp32/esp32_ble_adapter.c b/arch/xtensa/src/esp32/esp32_ble_adapter.c index 7296401ce00e5..253a407b4d47f 100644 --- a/arch/xtensa/src/esp32/esp32_ble_adapter.c +++ b/arch/xtensa/src/esp32/esp32_ble_adapter.c @@ -2491,15 +2491,10 @@ static IRAM_ATTR int32_t esp_queue_send_generic(void *queue, void *item, static void esp_update_time(struct timespec *timespec, uint32_t ticks) { - uint32_t tmp; - - tmp = TICK2SEC(ticks); - timespec->tv_sec += tmp; - - ticks -= SEC2TICK(tmp); - tmp = TICK2NSEC(ticks); + struct timespec ts; - timespec->tv_nsec += tmp; + clock_ticks2time(&ts, ticks); + clock_timespec_add(timespec, &ts, timespec); } /**************************************************************************** diff --git a/arch/xtensa/src/esp32/esp32_wifi_adapter.c b/arch/xtensa/src/esp32/esp32_wifi_adapter.c index e267a6970c45a..3bd618f9c75bc 100644 --- a/arch/xtensa/src/esp32/esp32_wifi_adapter.c +++ b/arch/xtensa/src/esp32/esp32_wifi_adapter.c @@ -730,15 +730,10 @@ static void esp_thread_semphr_free(void *semphr) static void esp_update_time(struct timespec *timespec, uint32_t ticks) { - uint32_t tmp; - - tmp = TICK2SEC(ticks); - timespec->tv_sec += tmp; - - ticks -= SEC2TICK(tmp); - tmp = TICK2NSEC(ticks); + struct timespec ts; - timespec->tv_nsec += tmp; + clock_ticks2time(&ts, ticks); + clock_timespec_add(timespec, &ts, timespec); } /**************************************************************************** diff --git a/arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.c b/arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.c index 6852f74026756..3d253e78c304a 100644 --- a/arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.c +++ b/arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.c @@ -679,15 +679,10 @@ static void esp_thread_semphr_free(void *semphr) static void esp_update_time(struct timespec *timespec, uint32_t ticks) { - uint32_t tmp; - - tmp = TICK2SEC(ticks); - timespec->tv_sec += tmp; - - ticks -= SEC2TICK(tmp); - tmp = TICK2NSEC(ticks); + struct timespec ts; - timespec->tv_nsec += tmp; + clock_ticks2time(&ts, ticks); + clock_timespec_add(timespec, &ts, timespec); } /**************************************************************************** diff --git a/arch/xtensa/src/esp32s3/esp32s3_ble_adapter.c b/arch/xtensa/src/esp32s3/esp32s3_ble_adapter.c index 473a9f479e62d..efcefc48d52d7 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_ble_adapter.c +++ b/arch/xtensa/src/esp32s3/esp32s3_ble_adapter.c @@ -2311,15 +2311,10 @@ static IRAM_ATTR int32_t esp_queue_send_generic(void *queue, void *item, static void esp_update_time(struct timespec *timespec, uint32_t ticks) { - uint32_t tmp; + struct timespec ts; - tmp = TICK2SEC(ticks); - timespec->tv_sec += tmp; - - ticks -= SEC2TICK(tmp); - tmp = TICK2NSEC(ticks); - - timespec->tv_nsec += tmp; + clock_ticks2time(&ts, ticks); + clock_timespec_add(timespec, &ts, timespec); } /**************************************************************************** diff --git a/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c b/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c index 4770986842b26..071c251647915 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c +++ b/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c @@ -724,15 +724,10 @@ static void esp_thread_semphr_free(void *semphr) static void esp_update_time(struct timespec *timespec, uint32_t ticks) { - uint32_t tmp; - - tmp = TICK2SEC(ticks); - timespec->tv_sec += tmp; - - ticks -= SEC2TICK(tmp); - tmp = TICK2NSEC(ticks); + struct timespec ts; - timespec->tv_nsec += tmp; + clock_ticks2time(&ts, ticks); + clock_timespec_add(timespec, &ts, timespec); } /**************************************************************************** diff --git a/arch/z16/include/z16f/irq.h b/arch/z16/include/z16f/irq.h index 4a2be42ed43f3..0782cefe3979f 100644 --- a/arch/z16/include/z16f/irq.h +++ b/arch/z16/include/z16f/irq.h @@ -165,12 +165,6 @@ struct xcptcontext uint16_t regs[XCPTCONTEXT_REGS]; - /* The following function pointer is non-zero if there - * are pending signals to be processed. - */ - - CODE void *sigdeliver; /* Actual type is sig_deliver_t */ - /* The following retains that state during signal execution. * * REVISIT: Because there is only one copy of these save areas, diff --git a/arch/z16/src/common/z16_schedulesigaction.c b/arch/z16/src/common/z16_schedulesigaction.c index ca8f6bcb15b15..51cceea436159 100644 --- a/arch/z16/src/common/z16_schedulesigaction.c +++ b/arch/z16/src/common/z16_schedulesigaction.c @@ -74,93 +74,85 @@ * ****************************************************************************/ -void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(FAR struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=0x%06x\n", tcb, (uint32_t)sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->xcp.sigdeliver) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ - - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the interrupted - * task is the same as the one that must receive the signal, then - * we will have to modify the return state as well as the state - * in the TCB. - */ - - else - { - FAR uint32_t *current_pc = - (FAR uint32_t *)&up_current_regs()[REG_PC]; - - /* Save the return address and interrupt state. These will be - * restored by the signal trampoline after the signals have - * been delivered. - */ - - tcb->xcp.saved_pc = *current_pc; - tcb->xcp.saved_i = up_current_regs()[REG_FLAGS]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - *current_pc = (uint32_t)z16_sigdeliver; - up_current_regs()[REG_FLAGS] = 0; - - /* And make sure that the saved context in the TCB is the - * same as the interrupt return context. - */ + /* In this case just deliver the signal now. */ - z16_copystate(tcb->xcp.regs, up_current_regs()); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler - * and the running task is signalling some non-running task. + /* CASE 2: We are in an interrupt handler AND the interrupted + * task is the same as the one that must receive the signal, then + * we will have to modify the return state as well as the state + * in the TCB. */ else { - FAR uint32_t *saved_pc = (FAR uint32_t *)&tcb->xcp.regs[REG_PC]; + FAR uint32_t *current_pc = + (FAR uint32_t *)&up_current_regs()[REG_PC]; - /* Save the return lr and cpsr and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. + /* Save the return address and interrupt state. These will be + * restored by the signal trampoline after the signals have + * been delivered. */ - tcb->xcp.saved_pc = *saved_pc; - tcb->xcp.saved_i = tcb->xcp.regs[REG_FLAGS]; + tcb->xcp.saved_pc = *current_pc; + tcb->xcp.saved_i = up_current_regs()[REG_FLAGS]; /* Then set up to vector to the trampoline with interrupts * disabled */ - *saved_pc = (uint32_t)z16_sigdeliver; - tcb->xcp.regs[REG_FLAGS] = 0; + *current_pc = (uint32_t)z16_sigdeliver; + up_current_regs()[REG_FLAGS] = 0; + + /* And make sure that the saved context in the TCB is the + * same as the interrupt return context. + */ + + z16_copystate(tcb->xcp.regs, up_current_regs()); } } + + /* Otherwise, we are (1) signaling a task is not running from an + * interrupt handler or (2) we are not in an interrupt handler + * and the running task is signalling some non-running task. + */ + + else + { + FAR uint32_t *saved_pc = (FAR uint32_t *)&tcb->xcp.regs[REG_PC]; + + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_pc = *saved_pc; + tcb->xcp.saved_i = tcb->xcp.regs[REG_FLAGS]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + *saved_pc = (uint32_t)z16_sigdeliver; + tcb->xcp.regs[REG_FLAGS] = 0; + } } diff --git a/arch/z16/src/common/z16_sigdeliver.c b/arch/z16/src/common/z16_sigdeliver.c index 68e17b0afdb6a..f0d037c8d777f 100644 --- a/arch/z16/src/common/z16_sigdeliver.c +++ b/arch/z16/src/common/z16_sigdeliver.c @@ -60,8 +60,8 @@ void z16_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the return state on the stack. */ @@ -77,7 +77,7 @@ void z16_sigdeliver(void) /* Deliver the signals */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -97,9 +97,9 @@ void z16_sigdeliver(void) * could be modified by a hostile program. */ - regs32[REG_PC / 2] = rtcb->xcp.saved_pc; - regs[REG_FLAGS] = rtcb->xcp.saved_i; - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + regs32[REG_PC / 2] = rtcb->xcp.saved_pc; + regs[REG_FLAGS] = rtcb->xcp.saved_i; + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/z80/include/ez80/irq.h b/arch/z80/include/ez80/irq.h index 351f6f94c1923..83f3bed2ff5f2 100644 --- a/arch/z80/include/ez80/irq.h +++ b/arch/z80/include/ez80/irq.h @@ -246,12 +246,6 @@ struct xcptcontext chipreg_t regs[XCPTCONTEXT_REGS]; - /* The following function pointer is non-zero if there - * are pending signals to be processed. - */ - - CODE void *sigdeliver; /* Actual type is sig_deliver_t */ - /* The following retains that state during signal execution * * REVISIT: Because there is only one copy of these save areas, diff --git a/arch/z80/include/z180/irq.h b/arch/z80/include/z180/irq.h index 3fb3b25cd032e..125422714a6d5 100644 --- a/arch/z80/include/z180/irq.h +++ b/arch/z80/include/z180/irq.h @@ -173,12 +173,6 @@ struct xcptcontext chipreg_t regs[XCPTCONTEXT_REGS]; - /* The following function pointer is non-zero if there - * are pending signals to be processed. - */ - - CODE void *sigdeliver; /* Actual type is sig_deliver_t */ - /* The following retains that state during signal execution * * REVISIT: Because there is only one copy of these save areas, diff --git a/arch/z80/include/z8/irq.h b/arch/z80/include/z8/irq.h index b50fe0f04cfb6..7faff99d001d7 100644 --- a/arch/z80/include/z8/irq.h +++ b/arch/z80/include/z8/irq.h @@ -304,12 +304,6 @@ struct xcptcontext chipreg_t regs[XCPTCONTEXT_REGS]; - /* The following function pointer is non-zero if there - * are pending signals to be processed. - */ - - CODE void *sigdeliver; /* Actual type is sig_deliver_t */ - /* The following retains that state during signal execution * * REVISIT: Because there is only one copy of these save areas, diff --git a/arch/z80/include/z80/irq.h b/arch/z80/include/z80/irq.h index 861fbb2822545..e0308d9707f1d 100644 --- a/arch/z80/include/z80/irq.h +++ b/arch/z80/include/z80/irq.h @@ -88,12 +88,6 @@ struct xcptcontext chipreg_t regs[XCPTCONTEXT_REGS]; - /* The following function pointer is non-zero if there - * are pending signals to be processed. - */ - - CODE void *sigdeliver; /* Actual type is sig_deliver_t */ - /* The following retains that state during signal execution. * * REVISIT: Because there is only one copy of these save areas, diff --git a/arch/z80/src/ez80/ez80_schedulesigaction.c b/arch/z80/src/ez80/ez80_schedulesigaction.c index d0d0be93b9bb5..e96611102e0a9 100644 --- a/arch/z80/src/ez80/ez80_schedulesigaction.c +++ b/arch/z80/src/ez80/ez80_schedulesigaction.c @@ -43,8 +43,7 @@ * Name: ez80_sigsetup ****************************************************************************/ -static void ez80_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, - FAR chipreg_t *regs) +static void ez80_sigsetup(FAR struct tcb_s *tcb, FAR chipreg_t *regs) { /* Save the return address and interrupt state. These will be restored by * the signal trampoline after the signals have been delivered. @@ -99,66 +98,60 @@ static void ez80_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, * ****************************************************************************/ -void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(FAR struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=0x%06" PRIx32 "\n", tcb, (uint32_t)sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ - if (tcb->xcp.sigdeliver == NULL) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. */ - if (tcb == this_task()) + if (!IN_INTERRUPT()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!IN_INTERRUPT()) - { - /* In this case just deliver the signal now. */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } + /* CASE 2: We are in an interrupt handler AND the interrupted task + * is the same as the one that must receive the signal, then we + * will have to modify the return state as well as the state in + * the TCB. + */ - /* CASE 2: We are in an interrupt handler AND the interrupted task - * is the same as the one that must receive the signal, then we - * will have to modify the return state as well as the state in - * the TCB. + else + { + /* Set up to vector to the trampoline with interrupts + * disabled. */ - else - { - /* Set up to vector to the trampoline with interrupts - * disabled. - */ - - ez80_sigsetup(tcb, sigdeliver, (chipreg_t *)IRQ_STATE()); + ez80_sigsetup(tcb, (chipreg_t *)IRQ_STATE()); - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ - SAVE_IRQCONTEXT(tcb); - } + SAVE_IRQCONTEXT(tcb); } + } - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signaling some non-running task. - */ + /* Otherwise, we are (1) signaling a task is not running from an + * interrupt handler or (2) we are not in an interrupt handler and the + * running task is signaling some non-running task. + */ - else - { - /* Set up to vector to the trampoline with interrupts disabled. */ + else + { + /* Set up to vector to the trampoline with interrupts disabled. */ - ez80_sigsetup(tcb, sigdeliver, tcb->xcp.regs); - } + ez80_sigsetup(tcb, tcb->xcp.regs); } } diff --git a/arch/z80/src/ez80/ez80_sigdeliver.c b/arch/z80/src/ez80/ez80_sigdeliver.c index cff88ad2e3a75..3047267075cf3 100644 --- a/arch/z80/src/ez80/ez80_sigdeliver.c +++ b/arch/z80/src/ez80/ez80_sigdeliver.c @@ -61,8 +61,8 @@ void z80_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the return state on the stack. */ @@ -78,7 +78,7 @@ void z80_sigdeliver(void) /* Deliver the signals */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -98,9 +98,9 @@ void z80_sigdeliver(void) * could be modified by a hostile program. */ - regs[XCPT_PC] = rtcb->xcp.saved_pc; - regs[XCPT_I] = rtcb->xcp.saved_i; - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + regs[XCPT_PC] = rtcb->xcp.saved_pc; + regs[XCPT_I] = rtcb->xcp.saved_i; + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is diff --git a/arch/z80/src/z180/z180_schedulesigaction.c b/arch/z80/src/z180/z180_schedulesigaction.c index 21f40053b5cd0..c577745c3f910 100644 --- a/arch/z80/src/z180/z180_schedulesigaction.c +++ b/arch/z80/src/z180/z180_schedulesigaction.c @@ -46,8 +46,7 @@ * Name: z180_sigsetup ****************************************************************************/ -static void z180_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, - FAR chipreg_t *regs) +static void z180_sigsetup(FAR struct tcb_s *tcb, FAR chipreg_t *regs) { /* Save the return address and interrupt state. These will be restored by * the signal trampoline after the signals have been delivered. @@ -102,67 +101,61 @@ static void z180_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, * ****************************************************************************/ -void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(FAR struct tcb_s *tcb) { - _info("tcb=%p sigdeliver=0x%04x\n", tcb, (uint16_t)sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ - if (tcb->xcp.sigdeliver == NULL) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. */ - if (tcb == this_task()) + if (!IN_INTERRUPT()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!IN_INTERRUPT()) - { - /* In this case just deliver the signal now. */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } + /* CASE 2: We are in an interrupt handler AND the interrupted task + * is the same as the one that must receive the signal, then we + * will have to modify the return state as well as the state in + * the TCB. + */ - /* CASE 2: We are in an interrupt handler AND the interrupted task - * is the same as the one that must receive the signal, then we - * will have to modify the return state as well as the state in - * the TCB. + else + { + /* Set up to vector to the trampoline with interrupts + * disabled. */ - else - { - /* Set up to vector to the trampoline with interrupts - * disabled. - */ - - z180_sigsetup(tcb, sigdeliver, IRQ_STATE()); + z180_sigsetup(tcb, IRQ_STATE()); - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ - SAVE_IRQCONTEXT(tcb); - } + SAVE_IRQCONTEXT(tcb); } + } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. - */ + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ - else - { - /* Set up to vector to the trampoline with interrupts disabled. */ + else + { + /* Set up to vector to the trampoline with interrupts disabled. */ - z180_sigsetup(tcb, sigdeliver, tcb->xcp.regs); - } + z180_sigsetup(tcb, tcb->xcp.regs); } } diff --git a/arch/z80/src/z180/z180_sigdeliver.c b/arch/z80/src/z180/z180_sigdeliver.c index 10979e651543a..7bebc5e4c60a6 100644 --- a/arch/z80/src/z180/z180_sigdeliver.c +++ b/arch/z80/src/z180/z180_sigdeliver.c @@ -58,8 +58,8 @@ void z80_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the return state on the stack. */ @@ -75,7 +75,7 @@ void z80_sigdeliver(void) /* Deliver the signals */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -95,9 +95,9 @@ void z80_sigdeliver(void) * could be modified by a hostile program. */ - regs[XCPT_PC] = rtcb->xcp.saved_pc; - regs[XCPT_I] = rtcb->xcp.saved_i; - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + regs[XCPT_PC] = rtcb->xcp.saved_pc; + regs[XCPT_I] = rtcb->xcp.saved_i; + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/z80/src/z8/z8_schedulesigaction.c b/arch/z80/src/z8/z8_schedulesigaction.c index b018bbe3aac89..cddf5c6af3880 100644 --- a/arch/z80/src/z8/z8_schedulesigaction.c +++ b/arch/z80/src/z8/z8_schedulesigaction.c @@ -43,8 +43,7 @@ * Name: z8_sigsetup ****************************************************************************/ -static void z8_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, - FAR chipreg_t *regs) +static void z8_sigsetup(FAR struct tcb_s *tcb, FAR chipreg_t *regs) { /* Save the return address and interrupt state. These will be restored by * the signal trampoline after the signals have been delivered. @@ -99,60 +98,33 @@ static void z8_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, * ****************************************************************************/ -void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(FAR struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=0x%04x\n", tcb, (uint16_t)sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ - if (tcb->xcp.sigdeliver == NULL) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. */ - if (tcb == this_task()) + if (!IN_INTERRUPT()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ - - if (!IN_INTERRUPT()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the interrupted task - * is the same as the one that must receive the signal, then we - * will have to modify the return state as well as the state in - * the TCB. - */ - - else - { - /* Set up to vector to the trampoline with interrupts - * disabled. - */ - - z8_sigsetup(tcb, sigdeliver, IRQ_STATE()); - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ + /* In this case just deliver the signal now. */ - SAVE_IRQCONTEXT(tcb); - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. + /* CASE 2: We are in an interrupt handler AND the interrupted task + * is the same as the one that must receive the signal, then we + * will have to modify the return state as well as the state in + * the TCB. */ else @@ -161,7 +133,28 @@ void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) * disabled. */ - z8_sigsetup(tcb, sigdeliver, tcb->xcp.regs); + z8_sigsetup(tcb, IRQ_STATE()); + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + SAVE_IRQCONTEXT(tcb); } } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Set up to vector to the trampoline with interrupts + * disabled. + */ + + z8_sigsetup(tcb, tcb->xcp.regs); + } } diff --git a/arch/z80/src/z8/z8_sigdeliver.c b/arch/z80/src/z8/z8_sigdeliver.c index 3c93c08536b44..2c13db2e0c09e 100644 --- a/arch/z80/src/z8/z8_sigdeliver.c +++ b/arch/z80/src/z8/z8_sigdeliver.c @@ -77,8 +77,8 @@ void z80_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the return state on the stack. */ @@ -94,7 +94,7 @@ void z80_sigdeliver(void) /* Deliver the signals */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -114,9 +114,9 @@ void z80_sigdeliver(void) * could be modified by a hostile program. */ - regs[XCPT_PC] = rtcb->xcp.saved_pc; - regs[XCPT_IRQCTL] = rtcb->xcp.saved_irqctl; - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + regs[XCPT_PC] = rtcb->xcp.saved_pc; + regs[XCPT_IRQCTL] = rtcb->xcp.saved_irqctl; + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/z80/src/z80/z80_schedulesigaction.c b/arch/z80/src/z80/z80_schedulesigaction.c index 4bfba686db88b..f03690e784a65 100644 --- a/arch/z80/src/z80/z80_schedulesigaction.c +++ b/arch/z80/src/z80/z80_schedulesigaction.c @@ -44,8 +44,7 @@ * Name: z80_sigsetup ****************************************************************************/ -static void z80_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, - FAR chipreg_t *regs) +static void z80_sigsetup(FAR struct tcb_s *tcb, FAR chipreg_t *regs) { /* Save the return address and interrupt state. These will be restored by * the signal trampoline after the signals have been delivered. @@ -100,67 +99,61 @@ static void z80_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, * ****************************************************************************/ -void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(FAR struct tcb_s *tcb) { - _info("tcb=%p sigdeliver=0x%04x\n", tcb, (uint16_t)sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ - if (tcb->xcp.sigdeliver == NULL) + if (tcb == this_task()) { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. */ - if (tcb == this_task()) + if (!IN_INTERRUPT()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!IN_INTERRUPT()) - { - /* In this case just deliver the signal now. */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } + /* CASE 2: We are in an interrupt handler AND the interrupted task + * is the same as the one that must receive the signal, then we + * will have to modify the return state as well as the state in + * the TCB. + */ - /* CASE 2: We are in an interrupt handler AND the interrupted task - * is the same as the one that must receive the signal, then we - * will have to modify the return state as well as the state in - * the TCB. + else + { + /* Set up to vector to the trampoline with interrupts + * disabled. */ - else - { - /* Set up to vector to the trampoline with interrupts - * disabled. - */ - - z80_sigsetup(tcb, sigdeliver, IRQ_STATE()); + z80_sigsetup(tcb, IRQ_STATE()); - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ - SAVE_IRQCONTEXT(tcb); - } + SAVE_IRQCONTEXT(tcb); } + } - /* Otherwise, we are (1) signaling a task is not running - * from an interrupt handler or (2) we are not in an - * interrupt handler and the running task is signalling - * some non-running task. - */ + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ - else - { - /* Set up to vector to the trampoline with interrupts disabled. */ + else + { + /* Set up to vector to the trampoline with interrupts disabled. */ - z80_sigsetup(tcb, sigdeliver, tcb->xcp.regs); - } + z80_sigsetup(tcb, tcb->xcp.regs); } } diff --git a/arch/z80/src/z80/z80_sigdeliver.c b/arch/z80/src/z80/z80_sigdeliver.c index 3d793cadc7d78..ce2a6d9cbbadc 100644 --- a/arch/z80/src/z80/z80_sigdeliver.c +++ b/arch/z80/src/z80/z80_sigdeliver.c @@ -58,8 +58,8 @@ void z80_sigdeliver(void) board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", - rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); - DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->sigdeliver != NULL); /* Save the return state on the stack. */ @@ -75,7 +75,7 @@ void z80_sigdeliver(void) /* Deliver the signals */ - ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + (rtcb->sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -95,9 +95,9 @@ void z80_sigdeliver(void) * could be modified by a hostile program. */ - regs[XCPT_PC] = rtcb->xcp.saved_pc; - regs[XCPT_I] = rtcb->xcp.saved_i; - rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + regs[XCPT_PC] = rtcb->xcp.saved_pc; + regs[XCPT_I] = rtcb->xcp.saved_i; + rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/boards/arm/qemu/qemu-armv7a/configs/smp/defconfig b/boards/arm/qemu/qemu-armv7a/configs/smp/defconfig index bf7e0fcd36ada..28c219881d64e 100644 --- a/boards/arm/qemu/qemu-armv7a/configs/smp/defconfig +++ b/boards/arm/qemu/qemu-armv7a/configs/smp/defconfig @@ -14,6 +14,7 @@ CONFIG_ARCH_CHIP_QEMU_ARM=y CONFIG_ARCH_CHIP_QEMU_CORTEXA7=y CONFIG_ARCH_INTERRUPTSTACK=2048 CONFIG_ARCH_LOWVECTORS=y +CONFIG_ARM_PSCI=y CONFIG_BUILTIN=y CONFIG_DEBUG_ASSERTIONS=y CONFIG_DEBUG_FEATURES=y diff --git a/boards/arm/sama5/sama5d4-ek/src/sam_audio_null.c b/boards/arm/sama5/sama5d4-ek/src/sam_audio_null.c index c7428f9ad2712..7e289fe0ae9d0 100644 --- a/boards/arm/sama5/sama5d4-ek/src/sam_audio_null.c +++ b/boards/arm/sama5/sama5d4-ek/src/sam_audio_null.c @@ -100,7 +100,7 @@ int sam_audio_null_initialize(int minor) /* Get a null audio interface */ - nullaudio = audio_null_initialize(); + nullaudio = audio_null_initialize(true); if (!nullaudio) { auderr("ERROR: Failed to get the NULL audio interface\n"); diff --git a/boards/arm/stm32/stm32f429i-disco/configs/systemview/defconfig b/boards/arm/stm32/stm32f429i-disco/configs/systemview/defconfig index 075534e939ea8..adb3a67086eec 100644 --- a/boards/arm/stm32/stm32f429i-disco/configs/systemview/defconfig +++ b/boards/arm/stm32/stm32f429i-disco/configs/systemview/defconfig @@ -38,6 +38,7 @@ CONFIG_RAM_START=0x20000000 CONFIG_RAW_BINARY=y CONFIG_RR_INTERVAL=200 CONFIG_SCHED_INSTRUMENTATION=y +CONFIG_SCHED_INSTRUMENTATION_HEAP=y CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER=y CONFIG_SCHED_INSTRUMENTATION_SWITCH=y CONFIG_SEGGER_SYSVIEW=y diff --git a/cmake/menuconfig.cmake b/cmake/menuconfig.cmake index 6a8b0efc4c776..7dfd4a6c9905d 100644 --- a/cmake/menuconfig.cmake +++ b/cmake/menuconfig.cmake @@ -24,16 +24,9 @@ # changes) set(KCONFIG_ENV - "KCONFIG_CONFIG=${CMAKE_BINARY_DIR}/.config" - "EXTERNALDIR=dummy" - "APPSDIR=${NUTTX_APPS_DIR}" - "DRIVERS_PLATFORM_DIR=dummy" - "APPSBINDIR=${NUTTX_APPS_BINDIR}" - "BINDIR=${CMAKE_BINARY_DIR}" - "HOST_LINUX=$,y,n>" - "HOST_MACOS=$,y,n>" - "HOST_WINDOWS=$,y,n>" - "HOST_OTHER=$,y,n>") + "KCONFIG_CONFIG=${CMAKE_BINARY_DIR}/.config" "EXTERNALDIR=dummy" + "APPSDIR=${NUTTX_APPS_DIR}" "DRIVERS_PLATFORM_DIR=dummy" + "APPSBINDIR=${NUTTX_APPS_BINDIR}" "BINDIR=${CMAKE_BINARY_DIR}") # Use qconfig instead of menuconfig since PowerShell not support curses # redirection @@ -66,16 +59,6 @@ add_custom_target( WORKING_DIRECTORY ${NUTTX_DIR} USES_TERMINAL) -add_custom_target( - savedefconfig - COMMAND ${CMAKE_COMMAND} -E env ${KCONFIG_ENV} savedefconfig --out - ${CMAKE_BINARY_DIR}/defconfig.tmp - COMMAND ${CMAKE_COMMAND} -P ${NUTTX_DIR}/cmake/savedefconfig.cmake - ${CMAKE_BINARY_DIR}/.config ${CMAKE_BINARY_DIR}/defconfig.tmp - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/defconfig - ${NUTTX_DEFCONFIG} - WORKING_DIRECTORY ${NUTTX_DIR}) - # utility target to restore .config from board's defconfig add_custom_target( resetconfig @@ -86,3 +69,21 @@ add_custom_target( ${CMAKE_BINARY_DIR}/.config.orig COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_PARENT_LIST_FILE} WORKING_DIRECTORY ${NUTTX_DIR}) + +# utility target to refresh .config from board's defconfig for GITHUB +add_custom_target( + savedefconfig + COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/SAVEconfig + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/.config + ${CMAKE_BINARY_DIR}/SAVEconfig + COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/.config + COMMAND ${CMAKE_COMMAND} -E copy ${NUTTX_DEFCONFIG} + ${CMAKE_BINARY_DIR}/.config + COMMAND ${CMAKE_COMMAND} -E env ${KCONFIG_ENV} olddefconfig + COMMAND ${CMAKE_COMMAND} -E env ${KCONFIG_ENV} savedefconfig --out + ${CMAKE_BINARY_DIR}/defconfig.tmp + COMMAND ${CMAKE_COMMAND} -P ${NUTTX_DIR}/cmake/savedefconfig.cmake + ${CMAKE_BINARY_DIR}/.config ${CMAKE_BINARY_DIR}/defconfig.tmp + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/defconfig + ${NUTTX_DEFCONFIG} + WORKING_DIRECTORY ${NUTTX_DIR}) diff --git a/cmake/nuttx_kconfig.cmake b/cmake/nuttx_kconfig.cmake index 371bf2b08aea2..76b65e3387b35 100644 --- a/cmake/nuttx_kconfig.cmake +++ b/cmake/nuttx_kconfig.cmake @@ -159,9 +159,43 @@ function(nuttx_generate_kconfig) endif() endfunction() +function(nuttx_olddefconfig) + execute_process( + COMMAND olddefconfig + ERROR_VARIABLE KCONFIG_ERROR + OUTPUT_VARIABLE KCONFIG_OUTPUT + RESULT_VARIABLE KCONFIG_STATUS + WORKING_DIRECTORY ${NUTTX_DIR}) + + if(KCONFIG_ERROR) + message(WARNING "Kconfig Configuration Error: ${KCONFIG_ERROR}") + endif() + + if(KCONFIG_STATUS AND NOT KCONFIG_STATUS EQUAL 0) + message( + FATAL_ERROR + "nuttx_olddefconfig: Failed to initialize Kconfig configuration: ${KCONFIG_OUTPUT}" + ) + endif() +endfunction() + function(nuttx_setconfig) + set(ENV{KCONFIG_CONFIG} ${CMAKE_BINARY_DIR}/.config) execute_process( - COMMAND ${CMAKE_COMMAND} -E env ${KCONFIG_ENV} setconfig ${ARGN} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - OUTPUT_QUIET ERROR_QUIET) + COMMAND setconfig ${ARGN} --kconfig ${NUTTX_DIR}/Kconfig + ERROR_VARIABLE KCONFIG_ERROR + OUTPUT_VARIABLE KCONFIG_OUTPUT + RESULT_VARIABLE KCONFIG_STATUS + WORKING_DIRECTORY ${NUTTX_DIR}) + + if(KCONFIG_ERROR) + message(WARNING "Kconfig Configuration Error: ${KCONFIG_ERROR}") + endif() + + if(KCONFIG_STATUS AND NOT KCONFIG_STATUS EQUAL 0) + message( + FATAL_ERROR + "nuttx_setconfig: Failed to initialize Kconfig configuration: ${KCONFIG_OUTPUT}" + ) + endif() endfunction() diff --git a/cmake/nuttx_sethost.cmake b/cmake/nuttx_sethost.cmake index 308b11f41a8ae..e51f832316a22 100644 --- a/cmake/nuttx_sethost.cmake +++ b/cmake/nuttx_sethost.cmake @@ -29,11 +29,11 @@ function(nuttx_sethost) if(DEFINED ENV{PROCESSOR_ARCHITEW6432}) set(CMAKE_HOST_SYSTEM_PROCESSOR "$ENV{PROCESSOR_ARCHITEW6432}") message( - STATUS "ENV{PROCESSOR_ARCHITEW6432} = $ENV{PROCESSOR_ARCHITEW6432}") + STATUS " ENV{PROCESSOR_ARCHITEW6432} = $ENV{PROCESSOR_ARCHITEW6432}") else() set(CMAKE_HOST_SYSTEM_PROCESSOR "$ENV{PROCESSOR_ARCHITECTURE}") message( - STATUS "ENV{PROCESSOR_ARCHITECTURE} = $ENV{PROCESSOR_ARCHITECTURE}") + STATUS " ENV{PROCESSOR_ARCHITECTURE} = $ENV{PROCESSOR_ARCHITECTURE}") endif() else() execute_process( @@ -42,61 +42,66 @@ function(nuttx_sethost) OUTPUT_VARIABLE ARCHITECTURE) endif() + set(NUTTX_SYSTEM_SETHOST) + if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|Darwin|FreeBSD") - nuttx_setconfig(HOST_WINDOWS=n) if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux") - message(" Select HOST_LINUX=y") - nuttx_setconfig(HOST_LINUX=y) + message(" Select HOST_LINUX=y") + list(APPEND NUTTX_SYSTEM_SETHOST "HOST_LINUX=y") elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin") - message(" Select HOST_MACOS=y") - nuttx_setconfig(HOST_MACOS=y) + message(" Select HOST_MACOS=y") + list(APPEND NUTTX_SYSTEM_SETHOST "HOST_MACOS=y") elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "FreeBSD") - message(" Select HOST_BSD=y") - nuttx_setconfig(HOST_BSD=y) + message(" Select HOST_BSD=y") + list(APPEND NUTTX_SYSTEM_SETHOST "HOST_BSD=y") endif() - # Enable the System V ABI - nuttx_setconfig(SIM_X8664_SYSTEMV=y) elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "MSYS|CYGWIN|Windows") - # Enable Windows and the Microsoft ABI - message(" Select HOST_WINDOWS=y") - nuttx_setconfig(HOST_LINUX=n) - nuttx_setconfig(HOST_MACOS=n) - nuttx_setconfig(HOST_BSD=n) - nuttx_setconfig(HOST_WINDOWS=y) - nuttx_setconfig(SIM_X8664_MICROSOFT=y) + message(" Select HOST_WINDOWS=y") + list(APPEND NUTTX_SYSTEM_SETHOST "HOST_WINDOWS=y") if(CMAKE_HOST_SYSTEM_NAME MATCHES "CYGWIN") - message(" Select WINDOWS_CYGWIN=y") - nuttx_setconfig(WINDOWS_CYGWIN=y) + message(" Select WINDOWS_CYGWIN=y") + list(APPEND NUTTX_SYSTEM_SETHOST "WINDOWS_CYGWIN=y") elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "MSYS") - message(" Select WINDOWS_MSYS=y") - nuttx_setconfig(WINDOWS_MSYS=y) + message(" Select WINDOWS_MSYS=y") + list(APPEND NUTTX_SYSTEM_SETHOST "WINDOWS_MSYS=y") elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") - message(" Select WINDOWS_NATIVE=y") - nuttx_setconfig(EXPERIMENTAL=y) - nuttx_setconfig(WINDOWS_NATIVE=y) + message(" Select WINDOWS_NATIVE=y") + if(NOT MSVC) + list(APPEND NUTTX_SYSTEM_SETHOST "EXPERIMENTAL=y") + list(APPEND NUTTX_SYSTEM_SETHOST "WINDOWS_NATIVE=y") + else() + message(" MSVC toolchain") + endif() endif() else() - message(" Select HOST_OTHER=y") - nuttx_setconfig(HOST_LINUX=n) - nuttx_setconfig(HOST_MACOS=n) - nuttx_setconfig(HOST_BSD=n) - nuttx_setconfig(HOST_WINDOWS=n) - nuttx_setconfig(HOST_OTHER=y) - nuttx_setconfig(OTHER_OS=y) + message(" Select HOST_OTHER=y") + list(APPEND NUTTX_SYSTEM_SETHOST "HOST_OTHER=y") + # nuttx_setconfig(OTHER_OS=y) endif() - if(ARCHITECTURE STREQUAL "x86_64") - message(" Select HOST_X86_64=y") - nuttx_setconfig(HOST_X86_64=y) - elseif(ARCHITECTURE STREQUAL "x86") - message(" Select HOST_X86=y") - nuttx_setconfig(HOST_X86=y) - elseif(ARCHITECTURE STREQUAL "arm") - message(" Select HOST_ARM=y") - nuttx_setconfig(HOST_ARM=y) - elseif(ARCHITECTURE STREQUAL "arm64") - message(" Select HOST_ARM64=y") - nuttx_setconfig(HOST_ARM64=y) + if("${NUTTX_BOARD}" STREQUAL "sim") + if(ARCHITECTURE STREQUAL "x86_64") + message(" Select HOST_X86_64=y") + list(APPEND NUTTX_SYSTEM_SETHOST "HOST_X86_64=y") + if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|Darwin|FreeBSD") + # Enable the System V ABI + list(APPEND NUTTX_SYSTEM_SETHOST "SIM_X8664_SYSTEMV=y") + elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "MSYS|CYGWIN|Windows") + # Enable Microsoft ABI and the System V ABI + list(APPEND NUTTX_SYSTEM_SETHOST "SIM_X8664_SYSTEMV=y") + list(APPEND NUTTX_SYSTEM_SETHOST "SIM_X8664_MICROSOFT=y") + endif() + elseif(ARCHITECTURE STREQUAL "x86") + message(" Select HOST_X86=y") + list(APPEND NUTTX_SYSTEM_SETHOST "HOST_X86=y") + elseif(ARCHITECTURE STREQUAL "arm") + message(" Select HOST_ARM=y") + list(APPEND NUTTX_SYSTEM_SETHOST "HOST_ARM=y") + elseif(ARCHITECTURE STREQUAL "arm64") + message(" Select HOST_ARM64=y") + list(APPEND NUTTX_SYSTEM_SETHOST "HOST_ARM64=y") + endif() endif() - + # message(" nuttx_setconfig: ${NUTTX_SYSTEM_SETHOST}") + nuttx_setconfig("${NUTTX_SYSTEM_SETHOST}") endfunction() diff --git a/drivers/audio/audio_null.c b/drivers/audio/audio_null.c index 1954f9c7a8040..f857a122120ec 100644 --- a/drivers/audio/audio_null.c +++ b/drivers/audio/audio_null.c @@ -55,6 +55,7 @@ struct null_dev_s { struct audio_lowerhalf_s dev; /* Audio lower half (this device) */ + bool playback; /* True: playback, False: recording */ uint32_t scaler; /* Data bytes to sec scaler (bytes per sec) */ struct file mq; /* Message queue for receiving messages */ char mqname[16]; /* Our message queue name */ @@ -209,6 +210,8 @@ static int null_sleep(FAR struct audio_lowerhalf_s *dev, static int null_getcaps(FAR struct audio_lowerhalf_s *dev, int type, FAR struct audio_caps_s *caps) { + FAR struct null_dev_s *priv = (struct null_dev_s *)dev; + audinfo("type=%d\n", type); /* Validate the structure */ @@ -241,9 +244,9 @@ static int null_getcaps(FAR struct audio_lowerhalf_s *dev, int type, /* The types of audio units we implement */ - caps->ac_controls.b[0] = AUDIO_TYPE_OUTPUT | - AUDIO_TYPE_FEATURE | - AUDIO_TYPE_PROCESSING; + caps->ac_controls.b[0] = priv->playback ? + AUDIO_TYPE_OUTPUT : AUDIO_TYPE_INPUT; + caps->ac_format.hw = 1 << (AUDIO_FMT_PCM - 1); break; @@ -264,6 +267,7 @@ static int null_getcaps(FAR struct audio_lowerhalf_s *dev, int type, /* Provide capabilities of our OUTPUT unit */ case AUDIO_TYPE_OUTPUT: + case AUDIO_TYPE_INPUT: caps->ac_channels = 2; @@ -273,13 +277,13 @@ static int null_getcaps(FAR struct audio_lowerhalf_s *dev, int type, /* Report the Sample rates we support */ - caps->ac_controls.hw[0] = AUDIO_SAMP_RATE_8K | - AUDIO_SAMP_RATE_11K | - AUDIO_SAMP_RATE_16K | - AUDIO_SAMP_RATE_22K | - AUDIO_SAMP_RATE_32K | - AUDIO_SAMP_RATE_44K | - AUDIO_SAMP_RATE_48K; + caps->ac_controls.hw[0] = AUDIO_SAMP_RATE_8K | + AUDIO_SAMP_RATE_11K | + AUDIO_SAMP_RATE_16K | + AUDIO_SAMP_RATE_22K | + AUDIO_SAMP_RATE_32K | + AUDIO_SAMP_RATE_44K | + AUDIO_SAMP_RATE_48K; break; case AUDIO_FMT_MP3: @@ -391,6 +395,32 @@ static int null_configure(FAR struct audio_lowerhalf_s *dev, FAR struct null_dev_s *priv = (FAR struct null_dev_s *)dev; audinfo("ac_type: %d\n", caps->ac_type); + if (priv->mqname[0] == '\0') + { + struct mq_attr attr; + int ret; + + /* Create a message queue for the worker thread */ + + snprintf(priv->mqname, sizeof(priv->mqname), "/tmp/%" PRIXPTR, + (uintptr_t)priv); + + attr.mq_maxmsg = 16; + attr.mq_msgsize = sizeof(struct audio_msg_s); + attr.mq_curmsgs = 0; + attr.mq_flags = 0; + + ret = file_mq_open(&priv->mq, priv->mqname, + O_RDWR | O_CREAT, 0644, &attr); + if (ret < 0) + { + /* Error creating message queue! */ + + auderr("ERROR: Couldn't allocate message queue\n"); + return ret; + } + } + /* Process the configure operation */ switch (caps->ac_type) @@ -425,10 +455,10 @@ static int null_configure(FAR struct audio_lowerhalf_s *dev, break; case AUDIO_TYPE_OUTPUT: + case AUDIO_TYPE_INPUT: priv->scaler = caps->ac_channels * caps->ac_controls.hw[0] * caps->ac_controls.b[2] / 8; - audinfo(" AUDIO_TYPE_OUTPUT:\n"); audinfo(" Number of channels: %u\n", caps->ac_channels); audinfo(" Sample rate: %u\n", caps->ac_controls.hw[0]); audinfo(" Sample width: %u\n", caps->ac_controls.b[2]); @@ -525,6 +555,7 @@ static void *null_workerthread(pthread_addr_t pvarg) file_mq_close(&priv->mq); file_mq_unlink(priv->mqname); + priv->mqname[0] = '\0'; priv->terminate = false; /* Send an AUDIO_MSG_COMPLETE message to the client */ @@ -555,33 +586,12 @@ static int null_start(FAR struct audio_lowerhalf_s *dev) { FAR struct null_dev_s *priv = (FAR struct null_dev_s *)dev; struct sched_param sparam; - struct mq_attr attr; pthread_attr_t tattr; FAR void *value; int ret; audinfo("Entry\n"); - /* Create a message queue for the worker thread */ - - snprintf(priv->mqname, sizeof(priv->mqname), "/tmp/%" PRIXPTR, - (uintptr_t)priv); - - attr.mq_maxmsg = 16; - attr.mq_msgsize = sizeof(struct audio_msg_s); - attr.mq_curmsgs = 0; - attr.mq_flags = 0; - - ret = file_mq_open(&priv->mq, priv->mqname, - O_RDWR | O_CREAT, 0644, &attr); - if (ret < 0) - { - /* Error creating message queue! */ - - auderr("ERROR: Couldn't allocate message queue\n"); - return ret; - } - /* Join any old worker thread we had created to prevent a memory leak */ if (priv->threadid != 0) @@ -649,6 +659,12 @@ static int null_stop(FAR struct audio_lowerhalf_s *dev) pthread_join(priv->threadid, &value); priv->threadid = 0; +#ifdef CONFIG_AUDIO_MULTI_SESSION + dev->upper(dev->priv, AUDIO_CALLBACK_COMPLETE, NULL, OK, NULL); +#else + dev->upper(dev->priv, AUDIO_CALLBACK_COMPLETE, NULL, OK); +#endif + audinfo("Return OK\n"); return OK; } @@ -850,9 +866,8 @@ static int null_release(FAR struct audio_lowerhalf_s *dev) * Initialize the null audio device. * * Input Parameters: - * i2c - An I2C driver instance - * i2s - An I2S driver instance - * lower - Persistent board configuration data + * playback - True: initialize for playback only + * False: initialize for recording only * * Returned Value: * A new lower half audio interface for the NULL audio device is returned @@ -860,7 +875,7 @@ static int null_release(FAR struct audio_lowerhalf_s *dev) * ****************************************************************************/ -FAR struct audio_lowerhalf_s *audio_null_initialize(void) +FAR struct audio_lowerhalf_s *audio_null_initialize(bool playback) { FAR struct null_dev_s *priv; @@ -878,6 +893,8 @@ FAR struct audio_lowerhalf_s *audio_null_initialize(void) return &priv->dev; } + priv->playback = playback; + auderr("ERROR: Failed to allocate null audio device\n"); return NULL; } diff --git a/drivers/clk/clk_divider.c b/drivers/clk/clk_divider.c index 96fd643141b46..7490e3dd4af4c 100644 --- a/drivers/clk/clk_divider.c +++ b/drivers/clk/clk_divider.c @@ -304,7 +304,7 @@ static int32_t divider_get_val(uint32_t rate, uint32_t parent_rate, div = div_round_up(parent_rate, rate); - if ((flags & CLK_DIVIDER_POWER_OF_TWO) && !is_power_of_2(div)) + if ((flags & CLK_DIVIDER_POWER_OF_TWO) && !IS_POWER_OF_2(div)) { return -EINVAL; } diff --git a/drivers/note/note_driver.c b/drivers/note/note_driver.c index cee07d3b9a79b..74141665420fc 100644 --- a/drivers/note/note_driver.c +++ b/drivers/note/note_driver.c @@ -92,6 +92,8 @@ #define note_irqhandler(drv, irq, handler, enter) \ ((drv)->ops->irqhandler && \ ((drv)->ops->irqhandler(drv, irq, handler, enter), true)) +#define note_heap(drv, event, data, mem, size, used) \ + ((drv)->ops->heap && ((drv)->ops->heap(drv, event, data, mem, size, used), true)) #define note_string(drv, ip, buf) \ ((drv)->ops->string && ((drv)->ops->string(drv, ip, buf), true)) #define note_event(drv, ip, event, buf, len) \ @@ -1352,6 +1354,51 @@ void sched_note_irqhandler(int irq, FAR void *handler, bool enter) } #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP +void sched_note_heap(uint8_t event, FAR void *heap, FAR void *mem, + size_t size, size_t used) +{ + FAR struct note_driver_s **driver; + struct note_heap_s note; + bool formatted = false; + FAR struct tcb_s *tcb = this_task(); + +#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER + if (!note_isenabled()) + { + return; + } +#endif + + for (driver = g_note_drivers; *driver; driver++) + { + if (note_heap(*driver, event, heap, mem, size, used)) + { + continue; + } + + if ((*driver)->ops->add == NULL) + { + continue; + } + + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.nmm_cmn, sizeof(note), event); + note.heap = heap; + note.mem = mem; + note.size = size; + note.used = used; + } + + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(note)); + } +} +#endif + #ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP void sched_note_string_ip(uint32_t tag, uintptr_t ip, FAR const char *buf) { diff --git a/drivers/note/noteram_driver.c b/drivers/note/noteram_driver.c index f095445010cd9..e9b60333ab015 100644 --- a/drivers/note/noteram_driver.c +++ b/drivers/note/noteram_driver.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -419,6 +420,7 @@ static int noteram_open(FAR struct file *filep) int noteram_close(FAR struct file *filep) { FAR struct noteram_dump_context_s *ctx = filep->f_priv; + kmm_free(ctx); return OK; } @@ -621,11 +623,12 @@ static void noteram_dump_init_context(FAR struct noteram_dump_context_s *ctx) } /**************************************************************************** - * Name: get_task_name + * Name: get_taskname ****************************************************************************/ static const char *get_taskname(pid_t pid) { +#if CONFIG_DRIVERS_NOTE_TASKNAME_BUFSIZE > 0 FAR const char *taskname; taskname = note_get_taskname(pid); @@ -633,6 +636,7 @@ static const char *get_taskname(pid_t pid) { return taskname; } +#endif return ""; } @@ -1015,7 +1019,27 @@ static int noteram_dump_one(FAR uint8_t *p, FAR struct lib_outstream_s *s, } break; #endif - +#ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP + case NOTE_HEAP_ADD: + case NOTE_HEAP_REMOVE: + case NOTE_HEAP_ALLOC: + case NOTE_HEAP_FREE: + { + FAR struct note_heap_s *nmm = (FAR struct note_heap_s *)p; + FAR const char *name[] = + { + "add", "remove", "malloc", "free" + }; + + ret += noteram_dump_header(s, &nmm->nmm_cmn, ctx); + ret += lib_sprintf(s, "tracing_mark_write: C|%d|Heap Usage|%d|%s" + ": heap: %p size:%" PRIiPTR ", address: %p\n", + pid, nmm->used, + name[note->nc_type - NOTE_HEAP_ADD], + nmm->heap, nmm->size, nmm->mem); + } + break; +#endif default: break; } diff --git a/drivers/segger/Make.defs b/drivers/segger/Make.defs index 424c0f7206676..162cd4e3958b6 100644 --- a/drivers/segger/Make.defs +++ b/drivers/segger/Make.defs @@ -69,7 +69,7 @@ endif ifneq ($(CONFIG_SEGGER_RTT)$(CONFIG_SEGGER_SYSVIEW),) CFLAGS += ${INCDIR_PREFIX}segger$(DELIM)SystemView$(DELIM)SEGGER - SYSVIEW_VERSION ?= 354 + SYSVIEW_VERSION ?= 356 SYSVIEW_ZIP = SystemView_Src_V$(SYSVIEW_VERSION).zip # Download and unpack tarball if no git repo found diff --git a/drivers/segger/note_sysview.c b/drivers/segger/note_sysview.c index 1b221fff5a19e..95ded2b2ebcb6 100644 --- a/drivers/segger/note_sysview.c +++ b/drivers/segger/note_sysview.c @@ -23,6 +23,7 @@ ****************************************************************************/ #include +#include #include #include @@ -73,6 +74,11 @@ static void note_sysview_syscall_enter(FAR struct note_driver_s *drv, static void note_sysview_syscall_leave(FAR struct note_driver_s *drv, int nr, uintptr_t result); #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP +static void note_sysview_heap(FAR struct note_driver_s *drv, + uint8_t event, FAR void *heap, FAR void *mem, + size_t size, size_t curused); +#endif /**************************************************************************** * Private Data @@ -113,6 +119,9 @@ static const struct note_driver_ops_s g_note_sysview_ops = #ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER note_sysview_irqhandler, /* irqhandler */ #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP + note_sysview_heap, /* heap */ +#endif }; static struct note_sysview_driver_s g_note_sysview_driver = @@ -319,6 +328,64 @@ static void note_sysview_syscall_leave(FAR struct note_driver_s *drv, } #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP +static void note_sysview_heap(FAR struct note_driver_s *drv, + uint8_t event, FAR void *heap, FAR void *mem, + size_t size, size_t curused) +{ + switch (event) + { + case NOTE_HEAP_ALLOC: + case NOTE_HEAP_FREE: + { + U32 value = (U32)curused; + const SEGGER_SYSVIEW_DATA_SAMPLE data = + { + .ID = (U32)(uintptr_t)heap, + .pU32_Value = &value, + }; + + SEGGER_SYSVIEW_SampleData(&data); + if (event == NOTE_HEAP_ALLOC) + { + SEGGER_SYSVIEW_HeapAlloc(heap, mem, size); + } + else + { + SEGGER_SYSVIEW_HeapFree(heap, mem); + } + + break; + } + + case NOTE_HEAP_ADD: + { + char name[32]; + SEGGER_SYSVIEW_DATA_REGISTER data = + { + .ID = (U32)(uintptr_t)heap, + .DataType = SEGGER_SYSVIEW_TYPE_U32, + .Offset = 0, + .RangeMin = 0, + .RangeMax = 0, + .ScalingFactor = 1.f, + .sUnit = "B", + .sName = name, + }; + + snprintf(name, sizeof(name), "Heap%p", heap); + + SEGGER_SYSVIEW_RegisterData(&data); + SEGGER_SYSVIEW_HeapDefine(heap, mem, size, 0); + break; + } + + default: + break; + } +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/drivers/serial/uart_rpmsg.c b/drivers/serial/uart_rpmsg.c index 30b5d0ec7381b..a3e9e7adb8239 100644 --- a/drivers/serial/uart_rpmsg.c +++ b/drivers/serial/uart_rpmsg.c @@ -344,6 +344,9 @@ static void uart_rpmsg_device_destroy(FAR struct rpmsg_device *rdev, { rpmsg_destroy_ept(&priv->ept); } + + dev->dmatx.nbytes = dev->dmatx.length + dev->dmatx.nlength; + uart_xmitchars_done(dev); } static int uart_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, FAR void *data, @@ -381,9 +384,11 @@ static int uart_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, FAR void *data, { /* Get write-cmd, there are some data, we need receive them */ + nxmutex_lock(&dev->recv.lock); priv->recv_data = data; uart_recvchars_dma(dev); priv->recv_data = NULL; + nxmutex_unlock(&dev->recv.lock); header->response = 1; rpmsg_send(ept, msg, sizeof(*msg)); @@ -439,6 +444,7 @@ int uart_rpmsg_init(FAR const char *cpuname, FAR const char *devname, goto fail; } + nxmutex_init(&priv->lock); priv->cpuname = cpuname; priv->devname = devname; @@ -451,10 +457,10 @@ int uart_rpmsg_init(FAR const char *cpuname, FAR const char *devname, NULL); if (ret < 0) { + nxmutex_destroy(&priv->lock); goto fail; } - nxmutex_init(&priv->lock); snprintf(dev_name, sizeof(dev_name), "%s%s", UART_RPMSG_DEV_PREFIX, devname); uart_register(dev_name, dev); diff --git a/drivers/syslog/syslog_rpmsg.c b/drivers/syslog/syslog_rpmsg.c index 6cbce4a0108a3..d7b7ceeba9afa 100644 --- a/drivers/syslog/syslog_rpmsg.c +++ b/drivers/syslog/syslog_rpmsg.c @@ -80,8 +80,8 @@ struct syslog_rpmsg_s ****************************************************************************/ static void syslog_rpmsg_work(FAR void *priv_); -static void syslog_rpmsg_putchar(FAR struct syslog_rpmsg_s *priv, int ch, - bool last); +static void syslog_rpmsg_addbuf(FAR struct syslog_rpmsg_s *priv, + FAR const char *buffer, size_t len); static void syslog_rpmsg_device_created(FAR struct rpmsg_device *rdev, FAR void *priv_); static void syslog_rpmsg_device_destroy(FAR struct rpmsg_device *rdev, @@ -189,10 +189,19 @@ static void syslog_rpmsg_work(FAR void *priv_) } } -static void syslog_rpmsg_putchar(FAR struct syslog_rpmsg_s *priv, int ch, - bool last) +static void syslog_rpmsg_addbuf(FAR struct syslog_rpmsg_s *priv, + FAR const char *buffer, size_t len) { - if (priv->head + 1 - priv->tail >= priv->size) + bool overwritten = false; + size_t offset; + size_t tail; + + if (len <= 0) + { + return; + } + + if (priv->head + len - priv->tail >= priv->size) { bool ret = false; @@ -203,26 +212,41 @@ static void syslog_rpmsg_putchar(FAR struct syslog_rpmsg_s *priv, int ch, if (!ret) { - /* Overwrite */ - - priv->buffer[SYSLOG_RPMSG_TAILOFF(priv)] = 0; - priv->tail++; + overwritten = true; } } - priv->buffer[SYSLOG_RPMSG_HEADOFF(priv)] = ch & 0xff; - priv->head++; + offset = SYSLOG_RPMSG_HEADOFF(priv); + tail = priv->size - offset; + + if (len > tail) + { + memcpy(&priv->buffer[offset], buffer, tail); + memcpy(priv->buffer, buffer + tail, len - tail); + } + else + { + memcpy(&priv->buffer[offset], buffer, len); + } + + priv->head += len; + if (overwritten) + { + priv->tail = priv->head - priv->size; + priv->buffer[SYSLOG_RPMSG_TAILOFF(priv)] = 0; + priv->tail++; + } if (priv->flush) { #if defined(CONFIG_ARCH_LOWPUTC) - up_putc(ch); + up_nputs(buffer, len); #endif - priv->flush++; + priv->flush += len; return; } - if (last && !priv->suspend && is_rpmsg_ept_ready(&priv->ept)) + if (!priv->suspend && is_rpmsg_ept_ready(&priv->ept)) { clock_t delay = SYSLOG_RPMSG_WORK_DELAY; size_t space = SYSLOG_RPMSG_SPACE(priv); @@ -340,11 +364,12 @@ static ssize_t syslog_rpmsg_file_write(FAR struct file *filep, int syslog_rpmsg_putc(FAR syslog_channel_t *channel, int ch) { - FAR struct syslog_rpmsg_s *priv = &g_syslog_rpmsg; irqstate_t flags; + char tmp = ch; + UNUSED(channel); flags = enter_critical_section(); - syslog_rpmsg_putchar(priv, ch, true); + syslog_rpmsg_addbuf(&g_syslog_rpmsg, &tmp, 1); leave_critical_section(flags); return ch; @@ -380,15 +405,8 @@ ssize_t syslog_rpmsg_write(FAR syslog_channel_t *channel, FAR const char *buffer, size_t buflen) { FAR struct syslog_rpmsg_s *priv = &g_syslog_rpmsg; - irqstate_t flags; - size_t nwritten; - - flags = enter_critical_section(); - for (nwritten = 1; nwritten <= buflen; nwritten++) - { - syslog_rpmsg_putchar(priv, *buffer++, nwritten == buflen); - } - + irqstate_t flags = enter_critical_section(); + syslog_rpmsg_addbuf(priv, buffer, buflen); leave_critical_section(flags); return buflen; diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index b358be603b533..015a4befa8f88 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -103,7 +103,6 @@ * Public Types ****************************************************************************/ -typedef CODE void (*sig_deliver_t)(FAR struct tcb_s *tcb); typedef CODE void (*phy_enable_t)(bool enable); typedef CODE void (*initializer_t)(void); typedef CODE void (*debug_callback_t)(int type, FAR void *addr, size_t size, @@ -546,7 +545,7 @@ int up_backtrace(FAR struct tcb_s *tcb, * ****************************************************************************/ -void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver); +void up_schedule_sigaction(FAR struct tcb_s *tcb); /**************************************************************************** * Name: up_task_start diff --git a/include/nuttx/audio/audio_null.h b/include/nuttx/audio/audio_null.h index 2a90fdd8aecd7..80df3b2f52f28 100644 --- a/include/nuttx/audio/audio_null.h +++ b/include/nuttx/audio/audio_null.h @@ -100,9 +100,8 @@ extern "C" * Initialize the null audio device. * * Input Parameters: - * i2c - An I2C driver instance - * i2s - An I2S driver instance - * lower - Persistent board configuration data + * playback - True: initialize for playback only + * False: initialize for recording only * * Returned Value: * A new lower half audio interface for the NULL audio device is returned @@ -112,7 +111,7 @@ extern "C" struct audio_lowerhalf_s; /* Forward reference. Defined in nuttx/audio/audio.h */ -FAR struct audio_lowerhalf_s *audio_null_initialize(void); +FAR struct audio_lowerhalf_s *audio_null_initialize(bool playback); #undef EXTERN #ifdef __cplusplus diff --git a/include/nuttx/lib/math32.h b/include/nuttx/lib/math32.h index e3e7bd165f2ed..593bd868c7278 100644 --- a/include/nuttx/lib/math32.h +++ b/include/nuttx/lib/math32.h @@ -114,7 +114,6 @@ extern "C" * Public Function Prototypes ****************************************************************************/ -#define is_power_of_2(n) IS_POWER_OF_2(n) #define flsx(n) ((sizeof(n) <= sizeof(long)) ? flsl(n) : flsll(n)) /**************************************************************************** @@ -131,7 +130,7 @@ extern "C" * ****************************************************************************/ -#define log2ceil(n) (is_power_of_2(n) ? (flsx(n) - 1) : flsx(n)) +#define log2ceil(n) (IS_POWER_OF_2(n) ? (flsx(n) - 1) : flsx(n)) /**************************************************************************** * Name: log2floor diff --git a/include/nuttx/note/note_driver.h b/include/nuttx/note/note_driver.h index fae9b0685c8e8..7dc67e3dcda6b 100644 --- a/include/nuttx/note/note_driver.h +++ b/include/nuttx/note/note_driver.h @@ -91,6 +91,11 @@ struct note_driver_ops_s CODE void (*irqhandler)(FAR struct note_driver_s *drv, int irq, FAR void *handler, bool enter); #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP + CODE void (*heap)(FAR struct note_driver_s *drv, uint8_t event, + FAR void *heap, FAR void *mem, size_t size, + size_t curused); +#endif #ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP CODE void (*string)(FAR struct note_driver_s *drv, uintptr_t ip, FAR const char *buf); diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 10d7904aefe5a..3103c715f10b3 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -299,6 +299,7 @@ typedef enum tstate_e tstate_t; /* The following is the form of a thread start-up function */ typedef CODE void (*start_t)(void); +typedef CODE void (*sig_deliver_t)(FAR struct tcb_s *tcb); /* This is the entry point into the main thread of the task or into a created * pthread within the task. @@ -716,6 +717,11 @@ struct tcb_s struct xcptcontext xcp; /* Interrupt register save area */ + /* The following function pointer is non-zero if there are pending signals + * to be processed. + */ + + sig_deliver_t sigdeliver; #if CONFIG_TASK_NAME_SIZE > 0 char name[CONFIG_TASK_NAME_SIZE + 1]; /* Task name (with NUL terminator) */ #endif diff --git a/include/nuttx/sched_note.h b/include/nuttx/sched_note.h index 6b0d3c845883a..b87b66369af4f 100644 --- a/include/nuttx/sched_note.h +++ b/include/nuttx/sched_note.h @@ -166,34 +166,41 @@ enum note_type_e { - NOTE_START = 0, - NOTE_STOP = 1, - NOTE_SUSPEND = 2, - NOTE_RESUME = 3, - NOTE_CPU_START = 4, - NOTE_CPU_STARTED = 5, - NOTE_CPU_PAUSE = 6, - NOTE_CPU_PAUSED = 7, - NOTE_CPU_RESUME = 8, - NOTE_CPU_RESUMED = 9, - NOTE_PREEMPT_LOCK = 10, - NOTE_PREEMPT_UNLOCK = 11, - NOTE_CSECTION_ENTER = 12, - NOTE_CSECTION_LEAVE = 13, - NOTE_SPINLOCK_LOCK = 14, - NOTE_SPINLOCK_LOCKED = 15, - NOTE_SPINLOCK_UNLOCK = 16, - NOTE_SPINLOCK_ABORT = 17, - NOTE_SYSCALL_ENTER = 18, - NOTE_SYSCALL_LEAVE = 19, - NOTE_IRQ_ENTER = 20, - NOTE_IRQ_LEAVE = 21, - NOTE_DUMP_STRING = 22, - NOTE_DUMP_BINARY = 23, - NOTE_DUMP_BEGIN = 24, - NOTE_DUMP_END = 25, - NOTE_DUMP_MARK = 28, - NOTE_DUMP_COUNTER = 29, + NOTE_START, + NOTE_STOP, + NOTE_SUSPEND, + NOTE_RESUME, + NOTE_CPU_START, + NOTE_CPU_STARTED, + NOTE_CPU_PAUSE, + NOTE_CPU_PAUSED, + NOTE_CPU_RESUME, + NOTE_CPU_RESUMED, + NOTE_PREEMPT_LOCK, + NOTE_PREEMPT_UNLOCK, + NOTE_CSECTION_ENTER, + NOTE_CSECTION_LEAVE, + NOTE_SPINLOCK_LOCK, + NOTE_SPINLOCK_LOCKED, + NOTE_SPINLOCK_UNLOCK, + NOTE_SPINLOCK_ABORT, + NOTE_SYSCALL_ENTER, + NOTE_SYSCALL_LEAVE, + NOTE_IRQ_ENTER, + NOTE_IRQ_LEAVE, + NOTE_HEAP_ADD, + NOTE_HEAP_REMOVE, + NOTE_HEAP_ALLOC, + NOTE_HEAP_FREE, + NOTE_DUMP_STRING, + NOTE_DUMP_BINARY, + NOTE_DUMP_BEGIN, + NOTE_DUMP_END, + NOTE_DUMP_MARK, + NOTE_DUMP_COUNTER, + + /* Always last */ + NOTE_TYPE_LAST }; @@ -379,6 +386,15 @@ struct note_irqhandler_s uint8_t nih_irq; /* IRQ number */ }; +struct note_heap_s +{ + struct note_common_s nmm_cmn; /* Common note parameters */ + FAR void *heap; + FAR void *mem; + size_t size; + size_t used; +}; + struct note_string_s { struct note_common_s nst_cmn; /* Common note parameters */ @@ -541,6 +557,13 @@ void sched_note_irqhandler(int irq, FAR void *handler, bool enter); # define sched_note_irqhandler(i,h,e) #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP +void sched_note_heap(uint8_t event, FAR void *heap, FAR void *mem, + size_t size, size_t used); +#else +# define sched_note_heap(e,h,m,s,c) +#endif + #ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP void sched_note_string_ip(uint32_t tag, uintptr_t ip, FAR const char *buf); void sched_note_event_ip(uint32_t tag, uintptr_t ip, uint8_t event, diff --git a/mm/mm_heap/mm_free.c b/mm/mm_heap/mm_free.c index ab3cda0eae62f..6848ad3ab8bea 100644 --- a/mm/mm_heap/mm_free.c +++ b/mm/mm_heap/mm_free.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "mm_heap/mm.h" @@ -99,11 +100,12 @@ void mm_delayfree(FAR struct mm_heap_s *heap, FAR void *mem, bool delay) return; } + nodesize = mm_malloc_size(heap, mem); #ifdef CONFIG_MM_FILL_ALLOCATIONS - memset(mem, MM_FREE_MAGIC, mm_malloc_size(heap, mem)); + memset(mem, MM_FREE_MAGIC, nodesize); #endif - kasan_poison(mem, mm_malloc_size(heap, mem)); + kasan_poison(mem, nodesize); if (delay) { @@ -126,6 +128,7 @@ void mm_delayfree(FAR struct mm_heap_s *heap, FAR void *mem, bool delay) /* Update heap statistics */ heap->mm_curused -= nodesize; + sched_note_heap(NOTE_HEAP_FREE, heap, mem, nodesize, heap->mm_curused); /* Check if the following node is free and, if so, merge it */ diff --git a/mm/mm_heap/mm_initialize.c b/mm/mm_heap/mm_initialize.c index 0ae00b04e0120..6dd2f3dbf5902 100644 --- a/mm/mm_heap/mm_initialize.c +++ b/mm/mm_heap/mm_initialize.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -202,6 +203,9 @@ void mm_addregion(FAR struct mm_heap_s *heap, FAR void *heapstart, mm_addfreechunk(heap, node); heap->mm_curused += 2 * MM_SIZEOF_ALLOCNODE; mm_unlock(heap); + + sched_note_heap(NOTE_HEAP_ADD, heap, heapstart, heapsize, + heap->mm_curused); } /**************************************************************************** @@ -367,6 +371,9 @@ void mm_uninitialize(FAR struct mm_heap_s *heap) for (i = 0; i < CONFIG_MM_REGIONS; i++) { kasan_unregister(heap->mm_heapstart[i]); + sched_note_heap(NOTE_HEAP_REMOVE, heap, heap->mm_heapstart[i], + (uintptr_t)heap->mm_heapend[i] - + (uintptr_t)heap->mm_heapstart[i], heap->mm_curused); } #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MEMINFO) diff --git a/mm/mm_heap/mm_malloc.c b/mm/mm_heap/mm_malloc.c index 96adef1a48501..3d15c326ac354 100644 --- a/mm/mm_heap/mm_malloc.c +++ b/mm/mm_heap/mm_malloc.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "mm_heap/mm.h" @@ -306,7 +307,8 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size) /* Update heap statistics */ - heap->mm_curused += MM_SIZEOF_NODE(node); + nodesize = MM_SIZEOF_NODE(node); + heap->mm_curused += nodesize; if (heap->mm_curused > heap->mm_maxused) { heap->mm_maxused = heap->mm_curused; @@ -324,7 +326,9 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size) if (ret) { MM_ADD_BACKTRACE(heap, node); - ret = kasan_unpoison(ret, mm_malloc_size(heap, ret)); + ret = kasan_unpoison(ret, nodesize - MM_ALLOCNODE_OVERHEAD); + sched_note_heap(NOTE_HEAP_ALLOC, heap, ret, nodesize, + heap->mm_curused); #ifdef CONFIG_MM_FILL_ALLOCATIONS memset(ret, MM_ALLOC_MAGIC, alignsize - MM_ALLOCNODE_OVERHEAD); #endif diff --git a/mm/mm_heap/mm_memalign.c b/mm/mm_heap/mm_memalign.c index 0aa449f29605f..aa0621889fece 100644 --- a/mm/mm_heap/mm_memalign.c +++ b/mm/mm_heap/mm_memalign.c @@ -30,6 +30,7 @@ #include #include +#include #include "mm_heap/mm.h" @@ -267,7 +268,8 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment, /* Update heap statistics */ - heap->mm_curused += MM_SIZEOF_NODE(node); + size = MM_SIZEOF_NODE(node); + heap->mm_curused += size; if (heap->mm_curused > heap->mm_maxused) { heap->mm_maxused = heap->mm_curused; @@ -277,10 +279,10 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment, MM_ADD_BACKTRACE(heap, node); - alignedchunk = (uintptr_t)kasan_unpoison - ((FAR const void *)alignedchunk, - mm_malloc_size(heap, - (FAR void *)alignedchunk)); + alignedchunk = (uintptr_t)kasan_unpoison((FAR const void *)alignedchunk, + size - MM_ALLOCNODE_OVERHEAD); + sched_note_heap(NOTE_HEAP_ALLOC, heap, (FAR void *)alignedchunk, size, + heap->mm_curused); DEBUGASSERT(alignedchunk % alignment == 0); return (FAR void *)alignedchunk; diff --git a/mm/mm_heap/mm_realloc.c b/mm/mm_heap/mm_realloc.c index 7125a71f04cea..13fc849541866 100644 --- a/mm/mm_heap/mm_realloc.c +++ b/mm/mm_heap/mm_realloc.c @@ -34,6 +34,7 @@ #include #include +#include #include "mm_heap/mm.h" @@ -382,10 +383,15 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, heap->mm_maxused = heap->mm_curused; } + sched_note_heap(NOTE_HEAP_FREE, heap, oldmem, oldsize, + heap->mm_curused - newsize); + sched_note_heap(NOTE_HEAP_ALLOC, heap, newmem, newsize, + heap->mm_curused); mm_unlock(heap); MM_ADD_BACKTRACE(heap, (FAR char *)newmem - MM_SIZEOF_ALLOCNODE); - newmem = kasan_unpoison(newmem, mm_malloc_size(heap, newmem)); + newmem = kasan_unpoison(newmem, MM_SIZEOF_NODE(oldnode) - + MM_ALLOCNODE_OVERHEAD); if (kasan_reset_tag(newmem) != kasan_reset_tag(oldmem)) { /* Now we have to move the user contents 'down' in memory. memcpy diff --git a/mm/tlsf/mm_tlsf.c b/mm/tlsf/mm_tlsf.c index 4c60f419bf507..ff32de3726250 100644 --- a/mm/tlsf/mm_tlsf.c +++ b/mm/tlsf/mm_tlsf.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "tlsf/tlsf.h" @@ -492,15 +493,12 @@ static void mm_delayfree(FAR struct mm_heap_s *heap, FAR void *mem, { if (mm_lock(heap) == 0) { + size_t size = mm_malloc_size(heap, mem); #ifdef CONFIG_MM_FILL_ALLOCATIONS - memset(mem, MM_FREE_MAGIC, mm_malloc_size(heap, mem)); + memset(mem, MM_FREE_MAGIC, size); #endif - kasan_poison(mem, mm_malloc_size(heap, mem)); - - /* Update heap statistics */ - - heap->mm_curused -= mm_malloc_size(heap, mem); + kasan_poison(mem, size); /* Pass, return to the tlsf pool */ @@ -510,6 +508,10 @@ static void mm_delayfree(FAR struct mm_heap_s *heap, FAR void *mem, } else { + /* Update heap statistics */ + + heap->mm_curused -= size; + sched_note_heap(NOTE_HEAP_FREE, heap, mem, size, heap->mm_curused); tlsf_free(heap->mm_tlsf, mem); } @@ -598,6 +600,9 @@ void mm_addregion(FAR struct mm_heap_s *heap, FAR void *heapstart, tlsf_add_pool(heap->mm_tlsf, heapstart, heapsize); mm_unlock(heap); + + sched_note_heap(NOTE_HEAP_ADD, heap, heapstart, heapsize, + heap->mm_curused); } /**************************************************************************** @@ -1134,6 +1139,7 @@ size_t mm_malloc_size(FAR struct mm_heap_s *heap, FAR void *mem) FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size) { + size_t nodesize; FAR void *ret; /* In case of zero-length allocations allocate the minimum size object */ @@ -1168,7 +1174,8 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size) ret = tlsf_malloc(heap->mm_tlsf, size); #endif - heap->mm_curused += mm_malloc_size(heap, ret); + nodesize = mm_malloc_size(heap, ret); + heap->mm_curused += nodesize; if (heap->mm_curused > heap->mm_maxused) { heap->mm_maxused = heap->mm_curused; @@ -1179,11 +1186,14 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size) if (ret) { #if CONFIG_MM_BACKTRACE >= 0 - FAR struct memdump_backtrace_s *buf = ret + mm_malloc_size(heap, ret); + FAR struct memdump_backtrace_s *buf = ret + nodesize; memdump_backtrace(heap, buf); #endif - ret = kasan_unpoison(ret, mm_malloc_size(heap, ret)); + + ret = kasan_unpoison(ret, nodesize); + sched_note_heap(NOTE_HEAP_ALLOC, heap, ret, nodesize, + heap->mm_curused); #ifdef CONFIG_MM_FILL_ALLOCATIONS memset(ret, 0xaa, nodesize); @@ -1218,6 +1228,7 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size) FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment, size_t size) { + size_t nodesize; FAR void *ret; #ifdef CONFIG_MM_HEAP_MEMPOOL @@ -1245,7 +1256,8 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment, ret = tlsf_memalign(heap->mm_tlsf, alignment, size); #endif - heap->mm_curused += mm_malloc_size(heap, ret); + nodesize = mm_malloc_size(heap, ret); + heap->mm_curused += nodesize; if (heap->mm_curused > heap->mm_maxused) { heap->mm_maxused = heap->mm_curused; @@ -1256,11 +1268,13 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment, if (ret) { #if CONFIG_MM_BACKTRACE >= 0 - FAR struct memdump_backtrace_s *buf = ret + mm_malloc_size(heap, ret); + FAR struct memdump_backtrace_s *buf = ret + nodesize; memdump_backtrace(heap, buf); #endif - ret = kasan_unpoison(ret, mm_malloc_size(heap, ret)); + ret = kasan_unpoison(ret, nodesize); + sched_note_heap(NOTE_HEAP_ALLOC, heap, ret, nodesize, + heap->mm_curused); } #if CONFIG_MM_FREE_DELAYCOUNT_MAX > 0 @@ -1302,6 +1316,8 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, size_t size) { FAR void *newmem; + size_t oldsize; + size_t newsize; /* If oldmem is NULL, then realloc is equivalent to malloc */ @@ -1361,7 +1377,8 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, /* Allocate from the tlsf pool */ DEBUGVERIFY(mm_lock(heap)); - heap->mm_curused -= mm_malloc_size(heap, oldmem); + oldsize = mm_malloc_size(heap, oldmem); + heap->mm_curused -= oldsize; #if CONFIG_MM_BACKTRACE >= 0 newmem = tlsf_realloc(heap->mm_tlsf, oldmem, size + sizeof(struct memdump_backtrace_s)); @@ -1369,7 +1386,8 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, newmem = tlsf_realloc(heap->mm_tlsf, oldmem, size); #endif - heap->mm_curused += mm_malloc_size(heap, newmem ? newmem : oldmem); + newsize = mm_malloc_size(heap, newmem); + heap->mm_curused += newmem ? newsize : oldsize; if (heap->mm_curused > heap->mm_maxused) { heap->mm_maxused = heap->mm_curused; @@ -1377,20 +1395,23 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, mm_unlock(heap); -#if CONFIG_MM_BACKTRACE >= 0 if (newmem) { - FAR struct memdump_backtrace_s *buf = - newmem + mm_malloc_size(heap, newmem); - +#if CONFIG_MM_BACKTRACE >= 0 + FAR struct memdump_backtrace_s *buf = newmem + newsize; memdump_backtrace(heap, buf); - } #endif + sched_note_heap(NOTE_HEAP_FREE, heap, oldmem, oldsize, + heap->mm_curused - newsize); + sched_note_heap(NOTE_HEAP_ALLOC, heap, newmem, newsize, + heap->mm_curused); + } + #if CONFIG_MM_FREE_DELAYCOUNT_MAX > 0 /* Try again after free delay list */ - if (newmem == NULL && free_delaylist(heap, true)) + else if (free_delaylist(heap, true)) { return mm_realloc(heap, oldmem, size); } @@ -1425,6 +1446,9 @@ void mm_uninitialize(FAR struct mm_heap_s *heap) for (i = 0; i < CONFIG_MM_REGIONS; i++) { kasan_unregister(heap->mm_heapstart[i]); + sched_note_heap(NOTE_HEAP_REMOVE, heap, heap->mm_heapstart[i], + (uintptr_t)heap->mm_heapend[i] - + (uintptr_t)heap->mm_heapstart[i], heap->mm_curused); } #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MEMINFO) diff --git a/sched/Kconfig b/sched/Kconfig index f7a10612fdbcc..a4c5110c6f7ee 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -1284,6 +1284,14 @@ config SCHED_INSTRUMENTATION_IRQHANDLER void sched_note_irqhandler(int irq, FAR void *handler, bool enter); +config SCHED_INSTRUMENTATION_HEAP + bool "Heap monitor hooks" + default n + ---help--- + Enables additional hooks for heap allocation. + + void sched_note_heap(uint8_t event, FAR void* heap, FAR void *mem, size_t size, size_t curused); + config SCHED_INSTRUMENTATION_DUMP bool "Use note dump for instrumentation" default n diff --git a/sched/mqueue/mq_initialize.c b/sched/mqueue/mq_initialize.c index 2ed75b88070a9..28691a15ab416 100644 --- a/sched/mqueue/mq_initialize.c +++ b/sched/mqueue/mq_initialize.c @@ -28,11 +28,21 @@ #include #include +#include #include #include "mqueue/mqueue.h" #include "mqueue/msg.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_MQUEUE +# define MQ_BLOCK_SIZE \ + ALIGN_UP(MQ_MSG_SIZE(MQ_MAX_BYTES), sizeof(void *)) +#endif + /**************************************************************************** * Private Type Definitions ****************************************************************************/ @@ -40,8 +50,9 @@ struct msgpool_s { #ifndef CONFIG_DISABLE_MQUEUE - struct mqueue_msg_s mqueue[CONFIG_PREALLOC_MQ_MSGS + - CONFIG_PREALLOC_MQ_IRQ_MSGS]; + uint8_t mqueue[MQ_BLOCK_SIZE * + (CONFIG_PREALLOC_MQ_MSGS + + CONFIG_PREALLOC_MQ_IRQ_MSGS)]; #endif #ifndef CONFIG_DISABLE_MQUEUE_SYSV struct msgbuf_s msgbuf[CONFIG_PREALLOC_MQ_MSGS]; @@ -94,18 +105,22 @@ static struct msgpool_s g_msgpool; #ifndef CONFIG_DISABLE_MQUEUE static FAR void * mq_msgblockinit(FAR struct list_node *list, - FAR struct mqueue_msg_s *mqmsgblock, + FAR uint8_t *block, uint16_t nmsgs, uint8_t alloc_type) { + FAR struct mqueue_msg_s *mqmsgblock; int i; + for (i = 0; i < nmsgs; i++) { + mqmsgblock = (FAR struct mqueue_msg_s *)block; + mqmsgblock->type = alloc_type; list_add_tail(list, &mqmsgblock->node); - mqmsgblock++; + block += MQ_BLOCK_SIZE; } - return mqmsgblock; + return block; } #endif diff --git a/sched/mqueue/mq_send.c b/sched/mqueue/mq_send.c index ba32f0fd46525..3c86f12208627 100644 --- a/sched/mqueue/mq_send.c +++ b/sched/mqueue/mq_send.c @@ -132,7 +132,7 @@ static int nxmq_verify_send(FAR FAR struct file *mq, FAR const char *msg, * ****************************************************************************/ -static FAR struct mqueue_msg_s *nxmq_alloc_msg(uint16_t maxmsgsize) +static FAR struct mqueue_msg_s *nxmq_alloc_msg(uint16_t msgsize) { FAR struct mqueue_msg_s *mqmsg; irqstate_t flags; @@ -166,7 +166,7 @@ static FAR struct mqueue_msg_s *nxmq_alloc_msg(uint16_t maxmsgsize) * allocate one. */ - mqmsg = kmm_malloc((sizeof (struct mqueue_msg_s))); + mqmsg = kmm_malloc(MQ_MSG_SIZE(msgsize)); /* Check if we allocated the message */ @@ -308,7 +308,7 @@ int file_mq_timedsend_internal(FAR struct file *mq, FAR const char *msg, /* Pre-allocate a message structure */ - mqmsg = nxmq_alloc_msg(msgq->maxmsgsize); + mqmsg = nxmq_alloc_msg(msglen); if (!mqmsg) { return -ENOMEM; diff --git a/sched/mqueue/mqueue.h b/sched/mqueue/mqueue.h index 80b500db2c7b1..f47ea8e06dd5d 100644 --- a/sched/mqueue/mqueue.h +++ b/sched/mqueue/mqueue.h @@ -49,6 +49,8 @@ #define MQ_MAX_MSGS 16 #define MQ_PRIO_MAX _POSIX_MQ_PRIO_MAX +#define MQ_MSG_SIZE(n) (sizeof(struct mqueue_msg_s) + (n) - 1) + /**************************************************************************** * Public Type Definitions ****************************************************************************/ @@ -72,7 +74,7 @@ struct mqueue_msg_s #else uint16_t msglen; /* Message data length */ #endif - char mail[MQ_MAX_BYTES]; /* Message data */ + char mail[1]; /* Message data */ }; /**************************************************************************** diff --git a/sched/signal/sig_dispatch.c b/sched/signal/sig_dispatch.c index 7e238b8e95f7d..d726d5c3ae486 100644 --- a/sched/signal/sig_dispatch.c +++ b/sched/signal/sig_dispatch.c @@ -46,10 +46,57 @@ #include "signal/signal.h" #include "mqueue/mqueue.h" +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct sig_arg_s +{ + pid_t pid; + cpu_set_t saved_affinity; + uint16_t saved_flags; + bool need_restore; +}; + /**************************************************************************** * Private Functions ****************************************************************************/ +#ifdef CONFIG_SMP +static int sig_handler(FAR void *cookie) +{ + FAR struct sig_arg_s *arg = cookie; + FAR struct tcb_s *tcb; + irqstate_t flags; + + flags = enter_critical_section(); + tcb = nxsched_get_tcb(arg->pid); + + if (!tcb || tcb->task_state == TSTATE_TASK_INVALID || + (tcb->flags & TCB_FLAG_EXIT_PROCESSING) != 0) + { + /* There is no TCB with this pid or, if there is, it is not a task. */ + + leave_critical_section(flags); + return -ESRCH; + } + + if (arg->need_restore) + { + tcb->affinity = arg->saved_affinity; + tcb->flags = arg->saved_flags; + } + + if (tcb->sigdeliver) + { + up_schedule_sigaction(tcb); + } + + leave_critical_section(flags); + return OK; +} +#endif + /**************************************************************************** * Name: nxsig_queue_action * @@ -115,7 +162,43 @@ static int nxsig_queue_action(FAR struct tcb_s *stcb, siginfo_t *info) * up_schedule_sigaction() */ - up_schedule_sigaction(stcb, nxsig_deliver); + if (!stcb->sigdeliver) + { +#ifdef CONFIG_SMP + int cpu = stcb->cpu; + int me = this_cpu(); + + stcb->sigdeliver = nxsig_deliver; + if (cpu != me && stcb->task_state == TSTATE_TASK_RUNNING) + { + struct sig_arg_s arg; + + if ((stcb->flags & TCB_FLAG_CPU_LOCKED) != 0) + { + arg.need_restore = false; + } + else + { + arg.saved_flags = stcb->flags; + arg.saved_affinity = stcb->affinity; + arg.need_restore = true; + + stcb->flags |= TCB_FLAG_CPU_LOCKED; + CPU_SET(stcb->cpu, &stcb->affinity); + } + + arg.pid = stcb->pid; + nxsched_smp_call_single(stcb->cpu, sig_handler, &arg, + true); + } + else +#endif + { + stcb->sigdeliver = nxsig_deliver; + up_schedule_sigaction(stcb); + } + } + leave_critical_section(flags); } } diff --git a/sched/task/task.h b/sched/task/task.h index aa656861e28a6..6ce8a3afcddde 100644 --- a/sched/task/task.h +++ b/sched/task/task.h @@ -44,10 +44,16 @@ struct tcb_s; /* Forward reference */ /* Task start-up */ void nxtask_start(void); -int nxtask_setup_scheduler(FAR struct task_tcb_s *tcb, int priority, - start_t start, main_t main, uint8_t ttype); -int nxtask_setup_arguments(FAR struct task_tcb_s *tcb, - FAR const char *name, FAR char * const argv[]); +int nxtask_setup_stackargs(FAR struct task_tcb_s *tcb, + FAR const char *name, + FAR char * const argv[]); +int nxtask_setup_scheduler(FAR struct task_tcb_s *tcb, int priority, + start_t start, main_t main, uint8_t ttype); +#if CONFIG_TASK_NAME_SIZE > 0 +void nxtask_setup_name(FAR struct task_tcb_s *tcb, FAR const char *name); +#else +# define nxtask_setup_name(tcb, name) +#endif /* Task exit */ diff --git a/sched/task/task_fork.c b/sched/task/task_fork.c index 0cf22599cab0b..fca28ab8022e0 100644 --- a/sched/task/task_fork.c +++ b/sched/task/task_fork.c @@ -188,6 +188,11 @@ FAR struct task_tcb_s *nxtask_setup_fork(start_t retaddr) goto errout_with_tcb; } + /* Set the task name */ + + argv = nxsched_get_stackargs(parent); + nxtask_setup_name(child, argv[0]); + /* Allocate the stack for the TCB */ stack_size = (uintptr_t)ptcb->stack_base_ptr - @@ -240,8 +245,7 @@ FAR struct task_tcb_s *nxtask_setup_fork(start_t retaddr) /* Setup to pass parameters to the new task */ - argv = nxsched_get_stackargs(parent); - ret = nxtask_setup_arguments(child, argv[0], &argv[1]); + ret = nxtask_setup_stackargs(child, argv[0], &argv[1]); if (ret < OK) { goto errout_with_tcb; diff --git a/sched/task/task_init.c b/sched/task/task_init.c index e4f71480dfe93..bcf8b30811a1e 100644 --- a/sched/task/task_init.c +++ b/sched/task/task_init.c @@ -142,6 +142,10 @@ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority, goto errout_with_group; } + /* Set the task name */ + + nxtask_setup_name(tcb, name); + if (stack) { /* Use pre-allocated stack */ @@ -179,7 +183,7 @@ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority, /* Setup to pass parameters to the new task */ - ret = nxtask_setup_arguments(tcb, name, argv); + ret = nxtask_setup_stackargs(tcb, name, argv); if (ret < OK) { goto errout_with_group; diff --git a/sched/task/task_setup.c b/sched/task/task_setup.c index c1e14681d2c4e..fc4a38d41f3e5 100644 --- a/sched/task/task_setup.c +++ b/sched/task/task_setup.c @@ -491,53 +491,14 @@ static int nxthread_setup_scheduler(FAR struct tcb_s *tcb, int priority, } /**************************************************************************** - * Name: nxtask_setup_name - * - * Description: - * Assign the task name. - * - * Input Parameters: - * tcb - Address of the new task's TCB - * name - Name of the new task - * - * Returned Value: - * None - * + * Public Functions ****************************************************************************/ -#if CONFIG_TASK_NAME_SIZE > 0 -static void nxtask_setup_name(FAR struct task_tcb_s *tcb, - FAR const char *name) -{ - FAR char *dst = tcb->cmn.name; - int i; - - /* Copy the name into the TCB */ - - for (i = 0; i < CONFIG_TASK_NAME_SIZE; i++) - { - char c = *name++; - - if (c == '\0') - { - break; - } - - *dst++ = isspace(c) ? '_' : c; - } - - *dst = '\0'; -} -#else -# define nxtask_setup_name(t,n) -#endif /* CONFIG_TASK_NAME_SIZE */ - /**************************************************************************** * Name: nxtask_setup_stackargs * * Description: - * This functions is called only from nxtask_setup_arguments() It will - * allocate space on the new task's stack and will copy the argv[] array + * Allocate space on the new task's stack and will copy the argv[] array * and all strings to the task's stack where it is readily accessible to * the task. Data on the stack, on the other hand, is guaranteed to be * accessible no matter what privilege mode the task runs in. @@ -554,9 +515,9 @@ static void nxtask_setup_name(FAR struct task_tcb_s *tcb, * ****************************************************************************/ -static int nxtask_setup_stackargs(FAR struct task_tcb_s *tcb, - FAR const char *name, - FAR char * const argv[]) +int nxtask_setup_stackargs(FAR struct task_tcb_s *tcb, + FAR const char *name, + FAR char * const argv[]) { FAR char **stackargv; FAR char *str; @@ -566,6 +527,13 @@ static int nxtask_setup_stackargs(FAR struct task_tcb_s *tcb, int argc; int i; + /* Give a name to the unnamed tasks */ + + if (!name) + { + name = (FAR char *)g_noname; + } + /* Get the size of the task name (including the NUL terminator) */ strtablen = (strlen(name) + 1); @@ -664,10 +632,6 @@ static int nxtask_setup_stackargs(FAR struct task_tcb_s *tcb, return OK; } -/**************************************************************************** - * Public Functions - ****************************************************************************/ - /**************************************************************************** * Name: nxtask_setup_scheduler * @@ -739,37 +703,26 @@ int pthread_setup_scheduler(FAR struct pthread_tcb_s *tcb, int priority, #endif /**************************************************************************** - * Name: nxtask_setup_arguments + * Name: nxtask_setup_name * * Description: - * This functions sets up parameters in the Task Control Block (TCB) in - * preparation for starting a new thread. - * - * nxtask_setup_arguments() is called only from nxtask_init() and - * nxtask_start() to create a new task. In the "normal" case, the argv[] - * array is a structure in the TCB, the arguments are cloned via strdup. - * - * In the kernel build case, the argv[] array and all strings are copied - * to the task's stack. This is done because the TCB (and kernel allocated - * strings) are only accessible in kernel-mode. Data on the stack, on the - * other hand, is guaranteed to be accessible no matter what mode the - * task runs in. + * Assign the task name. * * Input Parameters: * tcb - Address of the new task's TCB - * name - Name of the new task (not used) - * argv - A pointer to an array of input parameters. The array should be - * terminated with a NULL argv[] value. If no parameters are - * required, argv may be NULL. + * name - Name of the new task * * Returned Value: - * OK + * None * ****************************************************************************/ -int nxtask_setup_arguments(FAR struct task_tcb_s *tcb, - FAR const char *name, FAR char * const argv[]) +#if CONFIG_TASK_NAME_SIZE > 0 +void nxtask_setup_name(FAR struct task_tcb_s *tcb, FAR const char *name) { + FAR char *dst = tcb->cmn.name; + int i; + /* Give a name to the unnamed tasks */ if (!name) @@ -777,14 +730,20 @@ int nxtask_setup_arguments(FAR struct task_tcb_s *tcb, name = (FAR char *)g_noname; } - /* Setup the task name */ + /* Copy the name into the TCB */ - nxtask_setup_name(tcb, name); + for (i = 0; i < CONFIG_TASK_NAME_SIZE; i++) + { + char c = *name++; - /* Copy the argv[] array and all strings are to the task's stack. Data on - * the stack is guaranteed to be accessible by the ask no matter what - * privilege mode the task runs in. - */ + if (c == '\0') + { + break; + } - return nxtask_setup_stackargs(tcb, name, argv); + *dst++ = isspace(c) ? '_' : c; + } + + *dst = '\0'; } +#endif /* CONFIG_TASK_NAME_SIZE */ diff --git a/tools/nxstyle.c b/tools/nxstyle.c index f886497360aac..4e27d179996c7 100644 --- a/tools/nxstyle.c +++ b/tools/nxstyle.c @@ -304,12 +304,19 @@ static const char *g_white_content_list[] = * drivers/segger/note_sysview.c */ + "DataType", + "Offset", + "Prio", + "pU32_Value", + "RangeMax", + "RangeMin", "SEGGER_SYSVIEW", - "TaskID", + "ScalingFactor", "sName", - "Prio", + "sUnit", "StackBase", "StackSize", + "TaskID", /* Ref: * drivers/segger/syslog_rtt.c