Skip to content

Commit

Permalink
Merge pull request #11342 from maciejbocianski/event_queue_static_alloc
Browse files Browse the repository at this point in the history
add queue static allocation support
  • Loading branch information
0xc0170 authored Aug 30, 2019
2 parents 979e1f0 + b637da3 commit bdd6cb8
Show file tree
Hide file tree
Showing 12 changed files with 1,079 additions and 42 deletions.
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

0 comments on commit bdd6cb8

Please sign in to comment.