Skip to content

Commit bdd6cb8

Browse files
authored
Merge pull request #11342 from maciejbocianski/event_queue_static_alloc
add queue static allocation support
2 parents 979e1f0 + b637da3 commit bdd6cb8

File tree

12 files changed

+1079
-42
lines changed

12 files changed

+1079
-42
lines changed

TESTS/events/equeue/main.cpp

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ static void pass_func(void *eh)
3939

4040
static void simple_func(void *p)
4141
{
42-
(*(reinterpret_cast<uint8_t *>(p)))++;
42+
uint8_t *d = reinterpret_cast<uint8_t *>(p);
43+
if (*d < 255) {
44+
(*d)++;
45+
}
4346
}
4447

4548
static void sloth_func(void *p)
@@ -977,6 +980,65 @@ static void test_equeue_sibling()
977980
equeue_destroy(&q);
978981
}
979982

983+
struct user_allocated_event {
984+
struct equeue_event e;
985+
uint8_t touched;
986+
};
987+
988+
/** Test that equeue executes user allocated events passed by equeue_post.
989+
*
990+
* Given queue is initialized and its size is set to store one event at max in its internal memory.
991+
* When post events allocated in queues internal memory (what is done by calling equeue_call).
992+
* Then only one event can be posted due to queue memory size.
993+
* When post user allocated events.
994+
* Then number of posted events is not limited by queue memory size.
995+
* When both queue allocaded and user allocated events are posted and equeue_dispatch is called.
996+
* Then both types of events are executed properly.
997+
*/
998+
static void test_equeue_user_allocated_event_post()
999+
{
1000+
equeue_t q;
1001+
int err = equeue_create(&q, EQUEUE_EVENT_SIZE);
1002+
TEST_ASSERT_EQUAL_INT(0, err);
1003+
1004+
uint8_t touched = 0;
1005+
user_allocated_event e1 = { { 0, 0, 0, NULL, NULL, NULL, 0, -1, NULL, NULL }, 0 };
1006+
user_allocated_event e2 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
1007+
user_allocated_event e3 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
1008+
user_allocated_event e4 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
1009+
user_allocated_event e5 = { { 0, 0, 0, NULL, NULL, NULL, 0, -1, NULL, NULL }, 0 };
1010+
1011+
TEST_ASSERT_NOT_EQUAL(0, equeue_call(&q, simple_func, &touched));
1012+
TEST_ASSERT_EQUAL_INT(0, equeue_call(&q, simple_func, &touched));
1013+
TEST_ASSERT_EQUAL_INT(0, equeue_call(&q, simple_func, &touched));
1014+
1015+
equeue_post_user_allocated(&q, simple_func, &e1.e);
1016+
equeue_post_user_allocated(&q, simple_func, &e2.e);
1017+
equeue_post_user_allocated(&q, simple_func, &e3.e);
1018+
equeue_post_user_allocated(&q, simple_func, &e4.e);
1019+
equeue_post_user_allocated(&q, simple_func, &e5.e);
1020+
equeue_cancel_user_allocated(&q, &e3.e);
1021+
1022+
equeue_dispatch(&q, 1);
1023+
1024+
TEST_ASSERT_EQUAL_UINT8(1, touched);
1025+
TEST_ASSERT_EQUAL_UINT8(1, e1.touched);
1026+
TEST_ASSERT_EQUAL_UINT8(1, e2.touched);
1027+
TEST_ASSERT_EQUAL_UINT8(0, e3.touched);
1028+
TEST_ASSERT_EQUAL_UINT8(1, e4.touched);
1029+
TEST_ASSERT_EQUAL_UINT8(1, e5.touched);
1030+
1031+
equeue_dispatch(&q, 10);
1032+
1033+
TEST_ASSERT_EQUAL_UINT8(1, touched);
1034+
TEST_ASSERT_EQUAL_UINT8(1, e1.touched);
1035+
TEST_ASSERT_EQUAL_UINT8(1, e2.touched);
1036+
TEST_ASSERT_EQUAL_UINT8(0, e3.touched);
1037+
TEST_ASSERT_EQUAL_UINT8(1, e4.touched);
1038+
TEST_ASSERT_EQUAL_UINT8(1, e5.touched);
1039+
1040+
equeue_destroy(&q);
1041+
}
9801042

9811043
Case cases[] = {
9821044
Case("simple call test", test_equeue_simple_call),
@@ -1006,7 +1068,8 @@ Case cases[] = {
10061068
Case("fragmenting barrage test", test_equeue_fragmenting_barrage<10>),
10071069
Case("multithreaded barrage test", test_equeue_multithreaded_barrage<10>),
10081070
Case("break request cleared on timeout test", test_equeue_break_request_cleared_on_timeout),
1009-
Case("sibling test", test_equeue_sibling)
1071+
Case("sibling test", test_equeue_sibling),
1072+
Case("user allocated event test", test_equeue_user_allocated_event_post)
10101073

10111074
};
10121075

TESTS/events/queue/main.cpp

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* mbed Microcontroller Library
2-
* Copyright (c) 2017 ARM Limited
2+
* Copyright (c) 2017-2019 ARM Limited
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -322,6 +322,145 @@ void time_left_test()
322322
TEST_ASSERT_EQUAL(-1, queue.time_left(0));
323323
}
324324

325+
void f5(int a1, int a2, int a3, int a4, int a5)
326+
{
327+
touched = true;
328+
}
329+
330+
class EventTest {
331+
public:
332+
EventTest() : counter() {}
333+
void f0()
334+
{
335+
counter++;
336+
}
337+
void f1(int a)
338+
{
339+
counter += a;
340+
}
341+
void f5(int a, int b, int c, int d, int e)
342+
{
343+
counter += a + b + c + d + e;
344+
}
345+
uint32_t counter;
346+
};
347+
348+
/** Test that queue executes both dynamic and user allocated events.
349+
*
350+
* Given queue is initialized and its size is set to store three Event at max in its internal memory.
351+
* When post queue allocated event.
352+
* Then only three event can be posted due to queue memory size.
353+
* When post user allocated evens.
354+
* Then number of posted events is not limited by queue memory size.
355+
* When both Event and UserAllocatedEvent are posted and queue dispatch is called.
356+
* Then both types of events are executed properly.
357+
*
358+
*/
359+
void mixed_dynamic_static_events_queue_test()
360+
{
361+
{
362+
EventQueue queue(9 * EVENTS_EVENT_SIZE);
363+
364+
EventTest e1_test;
365+
Event<void()> e1 = queue.event(&e1_test, &EventTest::f0);
366+
int id1 = e1.post();
367+
TEST_ASSERT_NOT_EQUAL(0, id1);
368+
EventTest e2_test;
369+
Event<void()> e2 = queue.event(&e2_test, &EventTest::f1, 3);
370+
int id2 = e2.post();
371+
TEST_ASSERT_NOT_EQUAL(0, id2);
372+
EventTest e3_test;
373+
Event<void()> e3 = queue.event(&e3_test, &EventTest::f5, 1, 2, 3, 4, 5);
374+
int id3 = e3.post();
375+
TEST_ASSERT_NOT_EQUAL(0, id3);
376+
377+
378+
auto ue0 = make_user_allocated_event(func0);
379+
EventTest ue1_test;
380+
auto ue1 = make_user_allocated_event(&ue1_test, &EventTest::f0);
381+
EventTest ue2_test;
382+
auto ue2 = make_user_allocated_event(&ue2_test, &EventTest::f1, 3);
383+
EventTest ue3_test;
384+
auto ue3 = make_user_allocated_event(&ue3_test, &EventTest::f5, 1, 2, 3, 4, 5);
385+
EventTest ue4_test;
386+
auto ue4 = make_user_allocated_event(&ue4_test, &EventTest::f5, 1, 2, 3, 4, 5);
387+
388+
touched = false;
389+
390+
ue0.call_on(&queue);
391+
TEST_ASSERT_EQUAL(false, ue0.try_call());
392+
ue1.call_on(&queue);
393+
TEST_ASSERT_EQUAL(false, ue1.try_call());
394+
ue2.call_on(&queue);
395+
TEST_ASSERT_EQUAL(false, ue2.try_call());
396+
ue3.call_on(&queue);
397+
TEST_ASSERT_EQUAL(false, ue3.try_call());
398+
ue4.call_on(&queue);
399+
ue4.cancel();
400+
TEST_ASSERT_EQUAL(true, ue4.try_call());
401+
ue4.cancel();
402+
e2.cancel();
403+
404+
queue.dispatch(1);
405+
406+
TEST_ASSERT_EQUAL(true, touched);
407+
TEST_ASSERT_EQUAL(1, ue1_test.counter);
408+
TEST_ASSERT_EQUAL(3, ue2_test.counter);
409+
TEST_ASSERT_EQUAL(15, ue3_test.counter);
410+
TEST_ASSERT_EQUAL(0, ue4_test.counter);
411+
TEST_ASSERT_EQUAL(1, e1_test.counter);
412+
TEST_ASSERT_EQUAL(0, e2_test.counter);
413+
TEST_ASSERT_EQUAL(15, e3_test.counter);
414+
}
415+
}
416+
417+
418+
static EventQueue g_queue(0);
419+
420+
/** Test that static queue executes user allocated events.
421+
*
422+
* Given static queue is initialized
423+
* When post user allocated evens.
424+
* Then UserAllocatedEvent are posted and dispatched without any error.
425+
*/
426+
void static_events_queue_test()
427+
{
428+
// check that no dynamic event can be posted
429+
Event<void()> e0 = g_queue.event(func0);
430+
TEST_ASSERT_EQUAL(0, e0.post());
431+
432+
auto ue0 = g_queue.make_user_allocated_event(func0);
433+
EventTest test1;
434+
auto ue1 = make_user_allocated_event(&test1, &EventTest::f0);
435+
EventTest test2;
436+
auto ue2 = g_queue.make_user_allocated_event(&test2, &EventTest::f1, 3);
437+
EventTest test3;
438+
auto ue3 = make_user_allocated_event(&test3, &EventTest::f5, 1, 2, 3, 4, 5);
439+
EventTest test4;
440+
auto ue4 = g_queue.make_user_allocated_event(&test4, &EventTest::f5, 1, 2, 3, 4, 5);
441+
442+
ue0.call();
443+
TEST_ASSERT_EQUAL(false, ue0.try_call());
444+
ue1.call_on(&g_queue);
445+
TEST_ASSERT_EQUAL(false, ue1.try_call());
446+
ue2();
447+
TEST_ASSERT_EQUAL(false, ue2.try_call());
448+
ue3.call_on(&g_queue);
449+
TEST_ASSERT_EQUAL(false, ue3.try_call());
450+
ue4.call();
451+
ue4.cancel();
452+
TEST_ASSERT_EQUAL(true, ue4.try_call());
453+
g_queue.cancel(&ue4);
454+
455+
g_queue.dispatch(1);
456+
457+
TEST_ASSERT_EQUAL(1, test1.counter);
458+
TEST_ASSERT_EQUAL(3, test2.counter);
459+
TEST_ASSERT_EQUAL(15, test3.counter);
460+
TEST_ASSERT_EQUAL(0, test4.counter);
461+
462+
}
463+
325464
// Test setup
326465
utest::v1::status_t test_setup(const size_t number_of_cases)
327466
{
@@ -348,6 +487,9 @@ const Case cases[] = {
348487
Case("Testing the event inference", event_inference_test),
349488

350489
Case("Testing time_left", time_left_test),
490+
Case("Testing mixed dynamic & static events queue", mixed_dynamic_static_events_queue_test),
491+
Case("Testing static events queue", static_events_queue_test)
492+
351493
};
352494

353495
Specification specification(test_setup, cases);

UNITTESTS/events/equeue/test_equeue.cpp

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ static void pass_func(void *eh)
4545

4646
static void simple_func(void *p)
4747
{
48-
(*(reinterpret_cast<uint8_t *>(p)))++;
48+
uint8_t *d = reinterpret_cast<uint8_t *>(p);
49+
if (*d < 255) {
50+
(*d)++;
51+
}
4952
}
5053

5154
static void sloth_func(void *p)
@@ -994,4 +997,63 @@ TEST_F(TestEqueue, test_equeue_sibling)
994997
equeue_cancel(&q, id1);
995998
equeue_cancel(&q, id2);
996999
equeue_destroy(&q);
997-
}
1000+
}
1001+
1002+
/** Test that equeue executes user allocated events passed by equeue_post.
1003+
*
1004+
* Given queue is initialized and its size is set to store one event at max in its internal memory.
1005+
* When post events allocated in queues internal memory (what is done by calling equeue_call).
1006+
* Then only one event can be posted due to queue memory size.
1007+
* When post user allocated events.
1008+
* Then number of posted events is not limited by queue memory size.
1009+
* When both queue allocaded and user allocated events are posted and equeue_dispatch is called.
1010+
* Then both types of events are executed properly.
1011+
*/
1012+
TEST_F(TestEqueue, test_equeue_user_allocated_event_post)
1013+
{
1014+
struct user_allocated_event {
1015+
struct equeue_event e;
1016+
uint8_t touched;
1017+
};
1018+
equeue_t q;
1019+
int err = equeue_create(&q, EQUEUE_EVENT_SIZE);
1020+
ASSERT_EQ(0, err);
1021+
1022+
uint8_t touched = 0;
1023+
user_allocated_event e1 = { { 0, 0, 0, NULL, NULL, NULL, 0, -1, NULL, NULL }, 0 };
1024+
user_allocated_event e2 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
1025+
user_allocated_event e3 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
1026+
user_allocated_event e4 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
1027+
user_allocated_event e5 = { { 0, 0, 0, NULL, NULL, NULL, 0, -1, NULL, NULL }, 0 };
1028+
1029+
EXPECT_NE(0, equeue_call(&q, simple_func, &touched));
1030+
EXPECT_EQ(0, equeue_call(&q, simple_func, &touched));
1031+
EXPECT_EQ(0, equeue_call(&q, simple_func, &touched));
1032+
1033+
equeue_post_user_allocated(&q, simple_func, &e1.e);
1034+
equeue_post_user_allocated(&q, simple_func, &e2.e);
1035+
equeue_post_user_allocated(&q, simple_func, &e3.e);
1036+
equeue_post_user_allocated(&q, simple_func, &e4.e);
1037+
equeue_post_user_allocated(&q, simple_func, &e5.e);
1038+
equeue_cancel_user_allocated(&q, &e3.e);
1039+
1040+
equeue_dispatch(&q, 1);
1041+
1042+
EXPECT_EQ(1, touched);
1043+
EXPECT_EQ(1, e1.touched);
1044+
EXPECT_EQ(1, e2.touched);
1045+
EXPECT_EQ(0, e3.touched);
1046+
EXPECT_EQ(1, e4.touched);
1047+
EXPECT_EQ(1, e5.touched);
1048+
1049+
equeue_dispatch(&q, 10);
1050+
1051+
EXPECT_EQ(1, touched);
1052+
EXPECT_EQ(1, e1.touched);
1053+
EXPECT_EQ(1, e2.touched);
1054+
EXPECT_EQ(0, e3.touched);
1055+
EXPECT_EQ(1, e4.touched);
1056+
EXPECT_EQ(1, e5.touched);
1057+
1058+
equeue_destroy(&q);
1059+
}

UNITTESTS/stubs/EqueuePosix_stub.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ unsigned equeue_tick(void)
4040
// Mutex operations
4141
int equeue_mutex_create(equeue_mutex_t *m)
4242
{
43-
return pthread_mutex_init(m, 0);
43+
pthread_mutexattr_t attr;
44+
pthread_mutexattr_init(&attr);
45+
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
46+
return pthread_mutex_init(m, &attr);
4447
}
4548

4649
void equeue_mutex_destroy(equeue_mutex_t *m)

0 commit comments

Comments
 (0)