Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Thread::start() and general_block_device test's thread allocation/deallocation #15059

Merged
merged 2 commits into from
Sep 8, 2021

Conversation

LDong-Arm
Copy link
Contributor

@LDong-Arm LDong-Arm commented Sep 7, 2021

Summary of changes

This issues were identified while working on QSPI flash support for CYW9P62S1_43012EVB_01 (#14989).

  • In the rtos::Thread class: If a thread's stack memory is not preallocated, Thread::start() allocates its stack from the heap. Allocation is asserted to succeed and not runtime-catchable, and this assertion doesn't even work due to missing std::nothrow. The system crashes in this case.
  • In the general_block_device test: The test case for multithreaded erase/program/read allocates a few Thread objects from the heap and starts them. It has two problems:
    • To check that there will be enough heap to start a new thread, the test case tries to allocate a dummy buffer of the thread's heap size and then frees it, before starting the thread. Then the thread will allocate its own stack. Such check is not reliable, because threads that are already running also perform additional allocation (when running test_thread_job()) and may take away the memory we just checked.
    • When deleting all threads in a loop, the loop boundary misses the last thread if the last thread object was allocated but not started (i.e. due to failed thread stack allocation check).

To fix the issues above

  • In rtos::Thread: Add missing std::nothrow to stack allocation. If allocation returns nullptr, make start() return osErrorNoMemory
  • In the general_block_device test:
    • Start a thread without any allocation test. Handle osErrorNoMemory return value from Thread::start().
    • Store pointers to threads and thread stacks in two zero-initialized arrays, and free all elements at the end of the test.

Impact of changes

Migration actions required

Documentation

None


Pull request type

[x] Patch update (Bug fix / Target update / Docs update / Test update / Refactor)
[] Feature update (New feature / Functionality change / New API)
[] Major update (Breaking change E.g. Return code change / API behaviour change)

Test results

[] No Tests required for this change (E.g docs only update)
[x] Covered by existing mbed-os tests (Greentea or Unittest)
[] Tests / results supplied as part of this PR

Reviewers


@LDong-Arm LDong-Arm requested a review from a team September 7, 2021 16:12
@LDong-Arm LDong-Arm added this to In progress (8) in Mbed Core via automation Sep 7, 2021
@LDong-Arm LDong-Arm moved this from In progress (8) to Awaiting review (3) in Mbed Core Sep 7, 2021
@ciarmcom ciarmcom added the release-type: patch Indentifies a PR as containing just a patch label Sep 7, 2021
@ciarmcom
Copy link
Member

ciarmcom commented Sep 7, 2021

@LDong-Arm, thank you for your changes.
@ARMmbed/mbed-os-maintainers please review.

@ciarmcom ciarmcom requested a review from a team September 7, 2021 16:30
@LDong-Arm LDong-Arm marked this pull request as draft September 8, 2021 09:33
@LDong-Arm LDong-Arm force-pushed the bd_greentea_fixes branch 2 times, most recently from c16cc35 to bde716d Compare September 8, 2021 10:19
@LDong-Arm LDong-Arm marked this pull request as ready for review September 8, 2021 10:26
@LDong-Arm LDong-Arm force-pushed the bd_greentea_fixes branch 2 times, most recently from 6dabc7f to 25dd1c4 Compare September 8, 2021 10:32
@LDong-Arm LDong-Arm changed the title General block device test: Fix thread stack allocation Fix Thread::start() and general_block_device test's thread allocation/deallocation Sep 8, 2021
Patater
Patater previously requested changes Sep 8, 2021
rtos/include/rtos/Thread.h Show resolved Hide resolved
rtos/source/Thread.cpp Show resolved Hide resolved
Mbed Core automation moved this from Awaiting review (3) to Review in progress (4) Sep 8, 2021
Copy link
Contributor Author

@LDong-Arm LDong-Arm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Patater Thanks, good catches. Now fixed.

@mergify mergify bot dismissed Patater’s stale review September 8, 2021 12:46

Pull request has been modified.

When a Thread object's stack memory is not provided, its `start()`
member function dynamically allocates its stack from the heap. If
allocation fails, there is no way to catch it because
* `std::nothrow` is missing after the `new` keyword. As Mbed OS
is built with `-fno-exceptions` (C++ exceptions disabled), failed
allocation results in an unrecoverable fault.
* The attempted `nullptr` check, which doesn't work anyway due to
the first point, is an assertion instead of error returning.
Assertions should be used as a development tool to ensure code
behaves correctly. But out-of-memory is a completely valid runtime
situation.

This commit adds the missing `std::nothrow`, and makes `Thread::start()`
return `osErrorNoMemory` if allocation fails so the caller can handle
it.

Note: A case when a thread should never fail due to lack of memory
is the main thread. But the main thread's stack is a pre-allocated
array in the static memory, passed to the `Thread()` constructor
during thread creation, so it's not impacted by this change.
The test case for multithreaded erase/program/read allocates a few
Thread objects from the heap and starts them. It has a few problems:

* To check that there will be enough heap to start a new thread, the
test case tries to allocate a dummy buffer of the thread's heap size
and then frees it, before starting the thread. Then the thread will
allocate its own stack. Such check is not reliable, because threads
that are already running also perform additional allocation (when
running `test_thread_job()`) and may take away the memory we just
checked.
* When deleting all threads in a loop, the loop boundary misses the
last thread if the last thread object was allocated but not started
(i.e. due to failed thread stack allocation check).

To fix the issues
* Start a thread without any allocation test. Following the preceding
commit "rtos: Thread: Make stack allocation failure runtime catchable",
`Thread::start()` now returns `osErrorNoMemory` if stack allocation
fails which we can handle.
* Store pointers to all threads in a zero-initialized array, and
free all elements at the end of the test.
Copy link
Contributor

@Patater Patater left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Mbed Core automation moved this from Review in progress (4) to Reviewer approved & awaiting CI & merge (3) Sep 8, 2021
@mergify mergify bot added needs: CI and removed needs: work labels Sep 8, 2021
@Patater
Copy link
Contributor

Patater commented Sep 8, 2021

CI started

@mbed-ci
Copy link

mbed-ci commented Sep 8, 2021

Jenkins CI Test : ✔️ SUCCESS

Build Number: 1 | 🔒 Jenkins CI Job | 🌐 Logs & Artifacts

CLICK for Detailed Summary

jobs Status
jenkins-ci/mbed-os-ci_unittests ✔️
jenkins-ci/mbed-os-ci_cmake-cloud-example-ARM ✔️
jenkins-ci/mbed-os-ci_cmake-cloud-example-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_build-cloud-example-ARM ✔️
jenkins-ci/mbed-os-ci_build-cloud-example-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_build-greentea-ARM ✔️
jenkins-ci/mbed-os-ci_build-greentea-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_cmake-example-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_cmake-example-ARM ✔️
jenkins-ci/mbed-os-ci_build-example-ARM ✔️
jenkins-ci/mbed-os-ci_build-example-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_greentea-test ✔️

@Patater Patater merged commit 988d165 into ARMmbed:master Sep 8, 2021
Mbed Core automation moved this from Reviewer approved & awaiting CI & merge (3) to Done Sep 8, 2021
@mergify mergify bot removed the ready for merge label Sep 8, 2021
@Patater Patater moved this from Done to Reported in Mbed Core Sep 10, 2021
@mbedmain mbedmain added release-version: 6.15.0 Release-pending and removed release-type: patch Indentifies a PR as containing just a patch Release-pending labels Sep 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Mbed Core
  
Reported
Development

Successfully merging this pull request may close these issues.

None yet

6 participants