Skip to content

RTOS threads test: Handle out of memory cases #7744

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

Merged
merged 1 commit into from
Aug 23, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 93 additions & 3 deletions TESTS/mbedmicro-rtos-mbed/threads/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,16 @@ void increment_with_wait(counter_t *counter)

void increment_with_child(counter_t *counter)
{
Thread *child = new Thread(osPriorityNormal, CHILD_THREAD_STACK_SIZE);
Thread *child = new (std::nothrow) Thread(osPriorityNormal, CHILD_THREAD_STACK_SIZE);
char *dummy = new (std::nothrow) char[CHILD_THREAD_STACK_SIZE];
delete[] dummy;

// Don't fail test due to lack of memory. Call function directly instead
if (!child || !dummy) {
increment(counter);
Copy link
Contributor

Choose a reason for hiding this comment

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

If this isn't actually getting called on a new thread doesn't this defeat the purpose of this test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This continues our discussion from below, under the assumption we want to allow low memory boards to still pass the test. If we don't have enough memory to launch a new thread, but still need this test to pass under these conditions (which is what this condition checks), then the only way to make this test pass is to manually call the increment function.

delete child;
return;
}
child->start(callback(increment, counter));
child->join();
delete child;
Expand All @@ -83,12 +92,21 @@ void increment_with_murder(counter_t *counter)
// take ownership of the counter mutex so it prevent the child to
// modify counter.
LockGuard lock(counter->internal_mutex());
Thread *child = new Thread(osPriorityNormal, CHILD_THREAD_STACK_SIZE);
Thread *child = new (std::nothrow) Thread(osPriorityNormal, CHILD_THREAD_STACK_SIZE);
char *dummy = new (std::nothrow) char[CHILD_THREAD_STACK_SIZE];
delete[] dummy;

// Don't fail test due to lack of memory.
if (!child || !dummy) {
delete child;
goto end;
}
child->start(callback(increment, counter));
child->terminate();
delete child;
}

end:
(*counter)++;
}

Expand Down Expand Up @@ -134,6 +152,10 @@ void self_terminate(Thread *self)
template <void (*F)(counter_t *)>
void test_single_thread()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

counter_t counter(0);
Thread thread(osPriorityNormal, THREAD_STACK_SIZE);
thread.start(callback(F, &counter));
Expand Down Expand Up @@ -174,6 +196,10 @@ void test_single_thread()
template <int N, void (*F)(counter_t *)>
void test_parallel_threads()
{
char *dummy = new (std::nothrow) char[PARALLEL_THREAD_STACK_SIZE * N];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");
Copy link
Contributor

Choose a reason for hiding this comment

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

@davidsaada This doesnt seem right. We are trying to allocate the space and then deleting it right away, and then comparing it using the macro. It will always skip the test. Unless I am missing something here. Can you please check?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The delete[] command has no effect on the value of dummy variable. The test will be skipped only if memory allocation fails. I could switch these two lines, but it won't change anything.


counter_t counter(0);
ParallelThread<osPriorityNormal, PARALLEL_THREAD_STACK_SIZE> threads[N];

Expand Down Expand Up @@ -222,6 +248,9 @@ template <int N, void (*F)(counter_t *)>
void test_serial_threads()
{
counter_t counter(0);
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

for (int i = 0; i < N; i++) {
Thread thread(osPriorityNormal, THREAD_STACK_SIZE);
Expand All @@ -240,9 +269,18 @@ void test_serial_threads()
*/
void test_self_terminate()
{
Thread *thread = new Thread(osPriorityNormal, THREAD_STACK_SIZE);
Thread *thread = new (std::nothrow) Thread(osPriorityNormal, THREAD_STACK_SIZE);
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;

// Don't fail test due to lack of memory.
if (!thread || !dummy) {
goto end;
}
thread->start(callback(self_terminate, thread));
thread->join();

end:
delete thread;
}

Expand Down Expand Up @@ -300,6 +338,10 @@ void signal_wait_multibit_tout()
template <int S, void (*F)()>
void test_thread_signal()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

Thread t_wait(osPriorityNormal, THREAD_STACK_SIZE);

t_wait.start(callback(F));
Expand Down Expand Up @@ -336,6 +378,10 @@ void signal_clr()
*/
void test_thread_signal_clr()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

Thread t_wait(osPriorityNormal, THREAD_STACK_SIZE);

t_wait.start(callback(signal_clr));
Expand Down Expand Up @@ -374,6 +420,10 @@ void stack_info()
*/
void test_thread_stack_info()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

Thread t(osPriorityNormal, THREAD_STACK_SIZE);
t.start(callback(stack_info));

Expand Down Expand Up @@ -425,6 +475,10 @@ void test_thread_wait()
*/
void test_thread_name()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

const char tname[] = "Amazing thread";
Thread t(osPriorityNormal, THREAD_STACK_SIZE, NULL, tname);
t.start(callback(thread_wait_signal));
Expand All @@ -446,6 +500,10 @@ void test_deleted_thread()
*/
void test_deleted()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

Thread t(osPriorityNormal, THREAD_STACK_SIZE);

TEST_ASSERT_EQUAL(Thread::Deleted, t.get_state());
Expand All @@ -469,6 +527,10 @@ void test_delay_thread()
*/
void test_delay()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

Thread t(osPriorityNormal, THREAD_STACK_SIZE);

t.start(callback(test_delay_thread));
Expand All @@ -494,6 +556,10 @@ void test_signal_thread()
*/
void test_signal()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

Thread t(osPriorityNormal, THREAD_STACK_SIZE);

t.start(callback(test_signal_thread));
Expand All @@ -518,6 +584,10 @@ void test_evt_flag_thread(osEventFlagsId_t evtflg)
*/
void test_evt_flag()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

Thread t(osPriorityNormal, THREAD_STACK_SIZE);
mbed_rtos_storage_event_flags_t evtflg_mem;
osEventFlagsAttr_t evtflg_attr;
Expand Down Expand Up @@ -550,6 +620,10 @@ void test_mutex_thread(Mutex *mutex)
*/
void test_mutex()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

Thread t(osPriorityNormal, THREAD_STACK_SIZE);
Mutex mutex;

Expand Down Expand Up @@ -577,6 +651,10 @@ void test_semaphore_thread(Semaphore *sem)
*/
void test_semaphore()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

Thread t(osPriorityNormal, THREAD_STACK_SIZE);
Semaphore sem;

Expand All @@ -602,6 +680,10 @@ void test_msg_get_thread(Queue<int32_t, 1> *queue)
*/
void test_msg_get()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

Thread t(osPriorityNormal, THREAD_STACK_SIZE);
Queue<int32_t, 1> queue;

Expand All @@ -628,6 +710,10 @@ void test_msg_put_thread(Queue<int32_t, 1> *queue)
*/
void test_msg_put()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

Thread t(osPriorityNormal, THREAD_STACK_SIZE);
Queue<int32_t, 1> queue;

Expand Down Expand Up @@ -680,6 +766,10 @@ void test_thread_ext_stack()
*/
void test_thread_prio()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");

Thread t(osPriorityNormal, THREAD_STACK_SIZE);
t.start(callback(thread_wait_signal));

Expand Down