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

add queue static allocation support #11342

Merged
merged 8 commits into from
Aug 30, 2019
Merged
67 changes: 65 additions & 2 deletions TESTS/events/equeue/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ static void pass_func(void *eh)

static void simple_func(void *p)
{
(*(reinterpret_cast<uint8_t *>(p)))++;
uint8_t *d = reinterpret_cast<uint8_t *>(p);
if (*d < 255) {
(*d)++;
}
}

static void sloth_func(void *p)
Expand Down Expand Up @@ -977,6 +980,65 @@ static void test_equeue_sibling()
equeue_destroy(&q);
}

struct user_allocated_event {
struct equeue_event e;
uint8_t touched;
};

/** Test that equeue executes user allocated events passed by equeue_post.
*
* Given queue is initialized and its size is set to store one event at max in its internal memory.
* When post events allocated in queues internal memory (what is done by calling equeue_call).
* Then only one event can be posted due to queue memory size.
* When post user allocated events.
* Then number of posted events is not limited by queue memory size.
* When both queue allocaded and user allocated events are posted and equeue_dispatch is called.
* Then both types of events are executed properly.
*/
static void test_equeue_user_allocated_event_post()
{
equeue_t q;
int err = equeue_create(&q, EQUEUE_EVENT_SIZE);
TEST_ASSERT_EQUAL_INT(0, err);

uint8_t touched = 0;
user_allocated_event e1 = { { 0, 0, 0, NULL, NULL, NULL, 0, -1, NULL, NULL }, 0 };
user_allocated_event e2 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
user_allocated_event e3 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
user_allocated_event e4 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
user_allocated_event e5 = { { 0, 0, 0, NULL, NULL, NULL, 0, -1, NULL, NULL }, 0 };

TEST_ASSERT_NOT_EQUAL(0, equeue_call(&q, simple_func, &touched));
TEST_ASSERT_EQUAL_INT(0, equeue_call(&q, simple_func, &touched));
TEST_ASSERT_EQUAL_INT(0, equeue_call(&q, simple_func, &touched));

equeue_post_user_allocated(&q, simple_func, &e1.e);
equeue_post_user_allocated(&q, simple_func, &e2.e);
equeue_post_user_allocated(&q, simple_func, &e3.e);
equeue_post_user_allocated(&q, simple_func, &e4.e);
equeue_post_user_allocated(&q, simple_func, &e5.e);
equeue_cancel_user_allocated(&q, &e3.e);

equeue_dispatch(&q, 1);

TEST_ASSERT_EQUAL_UINT8(1, touched);
TEST_ASSERT_EQUAL_UINT8(1, e1.touched);
TEST_ASSERT_EQUAL_UINT8(1, e2.touched);
TEST_ASSERT_EQUAL_UINT8(0, e3.touched);
TEST_ASSERT_EQUAL_UINT8(1, e4.touched);
TEST_ASSERT_EQUAL_UINT8(1, e5.touched);

equeue_dispatch(&q, 10);

TEST_ASSERT_EQUAL_UINT8(1, touched);
TEST_ASSERT_EQUAL_UINT8(1, e1.touched);
TEST_ASSERT_EQUAL_UINT8(1, e2.touched);
TEST_ASSERT_EQUAL_UINT8(0, e3.touched);
TEST_ASSERT_EQUAL_UINT8(1, e4.touched);
TEST_ASSERT_EQUAL_UINT8(1, e5.touched);

equeue_destroy(&q);
}

Case cases[] = {
Case("simple call test", test_equeue_simple_call),
Expand Down Expand Up @@ -1006,7 +1068,8 @@ Case cases[] = {
Case("fragmenting barrage test", test_equeue_fragmenting_barrage<10>),
Case("multithreaded barrage test", test_equeue_multithreaded_barrage<10>),
Case("break request cleared on timeout test", test_equeue_break_request_cleared_on_timeout),
Case("sibling test", test_equeue_sibling)
Case("sibling test", test_equeue_sibling),
Case("user allocated event test", test_equeue_user_allocated_event_post)

};

Expand Down
144 changes: 143 additions & 1 deletion TESTS/events/queue/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
* Copyright (c) 2017-2019 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -322,6 +322,145 @@ void time_left_test()
TEST_ASSERT_EQUAL(-1, queue.time_left(0));
}

void f5(int a1, int a2, int a3, int a4, int a5)
{
touched = true;
}

class EventTest {
public:
EventTest() : counter() {}
void f0()
{
counter++;
}
void f1(int a)
{
counter += a;
}
void f5(int a, int b, int c, int d, int e)
{
counter += a + b + c + d + e;
}
uint32_t counter;
};

/** Test that queue executes both dynamic and user allocated events.
*
* Given queue is initialized and its size is set to store three Event at max in its internal memory.
* When post queue allocated event.
* Then only three event can be posted due to queue memory size.
* When post user allocated evens.
* Then number of posted events is not limited by queue memory size.
* When both Event and UserAllocatedEvent are posted and queue dispatch is called.
* Then both types of events are executed properly.
*
*/
void mixed_dynamic_static_events_queue_test()
{
{
EventQueue queue(9 * EVENTS_EVENT_SIZE);

EventTest e1_test;
Event<void()> e1 = queue.event(&e1_test, &EventTest::f0);
int id1 = e1.post();
TEST_ASSERT_NOT_EQUAL(0, id1);
EventTest e2_test;
Event<void()> e2 = queue.event(&e2_test, &EventTest::f1, 3);
int id2 = e2.post();
TEST_ASSERT_NOT_EQUAL(0, id2);
EventTest e3_test;
Event<void()> e3 = queue.event(&e3_test, &EventTest::f5, 1, 2, 3, 4, 5);
int id3 = e3.post();
TEST_ASSERT_NOT_EQUAL(0, id3);


auto ue0 = make_user_allocated_event(func0);
EventTest ue1_test;
auto ue1 = make_user_allocated_event(&ue1_test, &EventTest::f0);
EventTest ue2_test;
auto ue2 = make_user_allocated_event(&ue2_test, &EventTest::f1, 3);
EventTest ue3_test;
auto ue3 = make_user_allocated_event(&ue3_test, &EventTest::f5, 1, 2, 3, 4, 5);
EventTest ue4_test;
auto ue4 = make_user_allocated_event(&ue4_test, &EventTest::f5, 1, 2, 3, 4, 5);

touched = false;

ue0.call_on(&queue);
TEST_ASSERT_EQUAL(false, ue0.try_call());
ue1.call_on(&queue);
TEST_ASSERT_EQUAL(false, ue1.try_call());
ue2.call_on(&queue);
TEST_ASSERT_EQUAL(false, ue2.try_call());
ue3.call_on(&queue);
TEST_ASSERT_EQUAL(false, ue3.try_call());
ue4.call_on(&queue);
ue4.cancel();
TEST_ASSERT_EQUAL(true, ue4.try_call());
ue4.cancel();
e2.cancel();

queue.dispatch(1);

TEST_ASSERT_EQUAL(true, touched);
TEST_ASSERT_EQUAL(1, ue1_test.counter);
TEST_ASSERT_EQUAL(3, ue2_test.counter);
TEST_ASSERT_EQUAL(15, ue3_test.counter);
TEST_ASSERT_EQUAL(0, ue4_test.counter);
TEST_ASSERT_EQUAL(1, e1_test.counter);
TEST_ASSERT_EQUAL(0, e2_test.counter);
TEST_ASSERT_EQUAL(15, e3_test.counter);
}
}


static EventQueue g_queue(0);

/** Test that static queue executes user allocated events.
*
* Given static queue is initialized
* When post user allocated evens.
* Then UserAllocatedEvent are posted and dispatched without any error.
*/
void static_events_queue_test()
{
// check that no dynamic event can be posted
Event<void()> e0 = g_queue.event(func0);
TEST_ASSERT_EQUAL(0, e0.post());

auto ue0 = g_queue.make_user_allocated_event(func0);
EventTest test1;
auto ue1 = make_user_allocated_event(&test1, &EventTest::f0);
EventTest test2;
auto ue2 = g_queue.make_user_allocated_event(&test2, &EventTest::f1, 3);
EventTest test3;
auto ue3 = make_user_allocated_event(&test3, &EventTest::f5, 1, 2, 3, 4, 5);
EventTest test4;
auto ue4 = g_queue.make_user_allocated_event(&test4, &EventTest::f5, 1, 2, 3, 4, 5);

ue0.call();
TEST_ASSERT_EQUAL(false, ue0.try_call());
ue1.call_on(&g_queue);
TEST_ASSERT_EQUAL(false, ue1.try_call());
ue2();
TEST_ASSERT_EQUAL(false, ue2.try_call());
ue3.call_on(&g_queue);
TEST_ASSERT_EQUAL(false, ue3.try_call());
ue4.call();
ue4.cancel();
TEST_ASSERT_EQUAL(true, ue4.try_call());
g_queue.cancel(&ue4);

g_queue.dispatch(1);

TEST_ASSERT_EQUAL(1, test1.counter);
TEST_ASSERT_EQUAL(3, test2.counter);
TEST_ASSERT_EQUAL(15, test3.counter);
TEST_ASSERT_EQUAL(0, test4.counter);

}

// Test setup
utest::v1::status_t test_setup(const size_t number_of_cases)
{
Expand All @@ -348,6 +487,9 @@ const Case cases[] = {
Case("Testing the event inference", event_inference_test),

Case("Testing time_left", time_left_test),
Case("Testing mixed dynamic & static events queue", mixed_dynamic_static_events_queue_test),
Case("Testing static events queue", static_events_queue_test)

};

Specification specification(test_setup, cases);
Expand Down
66 changes: 64 additions & 2 deletions UNITTESTS/events/equeue/test_equeue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ static void pass_func(void *eh)

static void simple_func(void *p)
{
(*(reinterpret_cast<uint8_t *>(p)))++;
uint8_t *d = reinterpret_cast<uint8_t *>(p);
if (*d < 255) {
(*d)++;
}
}

static void sloth_func(void *p)
Expand Down Expand Up @@ -994,4 +997,63 @@ TEST_F(TestEqueue, test_equeue_sibling)
equeue_cancel(&q, id1);
equeue_cancel(&q, id2);
equeue_destroy(&q);
}
}

/** Test that equeue executes user allocated events passed by equeue_post.
*
* Given queue is initialized and its size is set to store one event at max in its internal memory.
* When post events allocated in queues internal memory (what is done by calling equeue_call).
* Then only one event can be posted due to queue memory size.
* When post user allocated events.
* Then number of posted events is not limited by queue memory size.
* When both queue allocaded and user allocated events are posted and equeue_dispatch is called.
* Then both types of events are executed properly.
*/
TEST_F(TestEqueue, test_equeue_user_allocated_event_post)
{
struct user_allocated_event {
struct equeue_event e;
uint8_t touched;
};
equeue_t q;
int err = equeue_create(&q, EQUEUE_EVENT_SIZE);
ASSERT_EQ(0, err);

uint8_t touched = 0;
user_allocated_event e1 = { { 0, 0, 0, NULL, NULL, NULL, 0, -1, NULL, NULL }, 0 };
user_allocated_event e2 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
user_allocated_event e3 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
user_allocated_event e4 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
user_allocated_event e5 = { { 0, 0, 0, NULL, NULL, NULL, 0, -1, NULL, NULL }, 0 };

EXPECT_NE(0, equeue_call(&q, simple_func, &touched));
EXPECT_EQ(0, equeue_call(&q, simple_func, &touched));
EXPECT_EQ(0, equeue_call(&q, simple_func, &touched));

equeue_post_user_allocated(&q, simple_func, &e1.e);
equeue_post_user_allocated(&q, simple_func, &e2.e);
equeue_post_user_allocated(&q, simple_func, &e3.e);
equeue_post_user_allocated(&q, simple_func, &e4.e);
equeue_post_user_allocated(&q, simple_func, &e5.e);
equeue_cancel_user_allocated(&q, &e3.e);

equeue_dispatch(&q, 1);

EXPECT_EQ(1, touched);
EXPECT_EQ(1, e1.touched);
EXPECT_EQ(1, e2.touched);
EXPECT_EQ(0, e3.touched);
EXPECT_EQ(1, e4.touched);
EXPECT_EQ(1, e5.touched);

equeue_dispatch(&q, 10);

EXPECT_EQ(1, touched);
EXPECT_EQ(1, e1.touched);
EXPECT_EQ(1, e2.touched);
EXPECT_EQ(0, e3.touched);
EXPECT_EQ(1, e4.touched);
EXPECT_EQ(1, e5.touched);

equeue_destroy(&q);
}
5 changes: 4 additions & 1 deletion UNITTESTS/stubs/EqueuePosix_stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ unsigned equeue_tick(void)
// Mutex operations
int equeue_mutex_create(equeue_mutex_t *m)
{
return pthread_mutex_init(m, 0);
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
return pthread_mutex_init(m, &attr);
}

void equeue_mutex_destroy(equeue_mutex_t *m)
Expand Down
Loading