Import Mbed OS hard-float snapshot
This commit is contained in:
2
events/tests/.mbedignore
Normal file
2
events/tests/.mbedignore
Normal file
@@ -0,0 +1,2 @@
|
||||
UNITTESTS/*
|
||||
unit/
|
||||
1093
events/tests/TESTS/events/equeue/main.cpp
Normal file
1093
events/tests/TESTS/events/equeue/main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
549
events/tests/TESTS/events/queue/main.cpp
Normal file
549
events/tests/TESTS/events/queue/main.cpp
Normal file
@@ -0,0 +1,549 @@
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "mbed_events.h"
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity.h"
|
||||
#include "utest.h"
|
||||
|
||||
#if !DEVICE_USTICKER
|
||||
#error [NOT_SUPPORTED] test not supported
|
||||
#else
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
// Assume that tolerance is 5% of measured time.
|
||||
#define DELTA(ms) (ms / 20)
|
||||
|
||||
// TEST_EQUEUE_SIZE was reduced below 1024B to fit this test to devices with small RAM (RAM <= 16kB)
|
||||
// additionally TEST_EQUEUE_SIZE was expressed in EVENTS_EVENT_SIZE to increase readability
|
||||
// (for more details about EVENTS_EVENT_SIZE see EventQueue constructor)
|
||||
#define TEST_EQUEUE_SIZE (18*EVENTS_EVENT_SIZE)
|
||||
|
||||
// By empirical, we take 80MHz CPU/2ms delay as base tolerance for time left test.
|
||||
// For higher CPU frequency, tolerance is fixed to 2ms.
|
||||
// For lower CPU frequency, tolerance is inversely proportional to CPU frequency.
|
||||
// E.g.:
|
||||
// 100MHz: 2ms
|
||||
// 80MHz: 2ms
|
||||
// 64MHz: 3ms
|
||||
// 48MHz: 4ms
|
||||
#define ALLOWED_TIME_LEFT_TOLERANCE_MS ((SystemCoreClock >= 80000000) ? 2 : ((80000000 * 2 + SystemCoreClock - 1) / SystemCoreClock))
|
||||
|
||||
// flag for called
|
||||
volatile bool touched = false;
|
||||
|
||||
// static functions
|
||||
void func5(int a0, int a1, int a2, int a3, int a4)
|
||||
{
|
||||
touched = true;
|
||||
TEST_ASSERT_EQUAL(a0 | a1 | a2 | a3 | a4, 0x1f);
|
||||
}
|
||||
|
||||
void func4(int a0, int a1, int a2, int a3)
|
||||
{
|
||||
touched = true;
|
||||
TEST_ASSERT_EQUAL(a0 | a1 | a2 | a3, 0xf);
|
||||
}
|
||||
|
||||
void func3(int a0, int a1, int a2)
|
||||
{
|
||||
touched = true;
|
||||
TEST_ASSERT_EQUAL(a0 | a1 | a2, 0x7);
|
||||
}
|
||||
|
||||
void func2(int a0, int a1)
|
||||
{
|
||||
touched = true;
|
||||
TEST_ASSERT_EQUAL(a0 | a1, 0x3);
|
||||
}
|
||||
|
||||
void func1(int a0)
|
||||
{
|
||||
touched = true;
|
||||
TEST_ASSERT_EQUAL(a0, 0x1);
|
||||
}
|
||||
|
||||
void func0()
|
||||
{
|
||||
touched = true;
|
||||
}
|
||||
|
||||
#define SIMPLE_POSTS_TEST(i, ...) \
|
||||
void simple_posts_test##i() { \
|
||||
EventQueue queue(TEST_EQUEUE_SIZE); \
|
||||
\
|
||||
touched = false; \
|
||||
queue.call(func##i,##__VA_ARGS__); \
|
||||
queue.dispatch(0); \
|
||||
TEST_ASSERT(touched); \
|
||||
\
|
||||
touched = false; \
|
||||
queue.call_in(1, func##i,##__VA_ARGS__); \
|
||||
queue.dispatch(2); \
|
||||
TEST_ASSERT(touched); \
|
||||
\
|
||||
touched = false; \
|
||||
queue.call_every(1, func##i,##__VA_ARGS__); \
|
||||
queue.dispatch(2); \
|
||||
TEST_ASSERT(touched); \
|
||||
}
|
||||
|
||||
SIMPLE_POSTS_TEST(5, 0x01, 0x02, 0x04, 0x08, 0x010)
|
||||
SIMPLE_POSTS_TEST(4, 0x01, 0x02, 0x04, 0x08)
|
||||
SIMPLE_POSTS_TEST(3, 0x01, 0x02, 0x04)
|
||||
SIMPLE_POSTS_TEST(2, 0x01, 0x02)
|
||||
SIMPLE_POSTS_TEST(1, 0x01)
|
||||
SIMPLE_POSTS_TEST(0)
|
||||
|
||||
|
||||
void time_func(Timer *t, int ms)
|
||||
{
|
||||
TEST_ASSERT_INT_WITHIN(DELTA(ms), ms, t->read_ms());
|
||||
t->reset();
|
||||
}
|
||||
|
||||
template <int N>
|
||||
void call_in_test()
|
||||
{
|
||||
Timer tickers[N];
|
||||
|
||||
EventQueue queue(TEST_EQUEUE_SIZE);
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
tickers[i].start();
|
||||
queue.call_in((i + 1) * 100, time_func, &tickers[i], (i + 1) * 100);
|
||||
}
|
||||
|
||||
queue.dispatch(N * 100);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
void call_every_test()
|
||||
{
|
||||
Timer tickers[N];
|
||||
|
||||
EventQueue queue(TEST_EQUEUE_SIZE);
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
tickers[i].start();
|
||||
queue.call_every((i + 1) * 100, time_func, &tickers[i], (i + 1) * 100);
|
||||
}
|
||||
|
||||
queue.dispatch(N * 100);
|
||||
}
|
||||
|
||||
void allocate_failure_test()
|
||||
{
|
||||
EventQueue queue(TEST_EQUEUE_SIZE);
|
||||
int id;
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
id = queue.call((void (*)())0);
|
||||
}
|
||||
|
||||
TEST_ASSERT(!id);
|
||||
}
|
||||
|
||||
void no()
|
||||
{
|
||||
TEST_ASSERT(false);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
void cancel_test1()
|
||||
{
|
||||
EventQueue queue(TEST_EQUEUE_SIZE);
|
||||
|
||||
int ids[N];
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
ids[i] = queue.call_in(1000, no);
|
||||
}
|
||||
|
||||
for (int i = N - 1; i >= 0; i--) {
|
||||
queue.cancel(ids[i]);
|
||||
}
|
||||
|
||||
queue.dispatch(0);
|
||||
}
|
||||
|
||||
|
||||
// Testing the dynamic arguments to the event class
|
||||
unsigned counter = 0;
|
||||
|
||||
void count5(unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a5)
|
||||
{
|
||||
counter += a0 + a1 + a2 + a3 + a5;
|
||||
}
|
||||
|
||||
void count4(unsigned a0, unsigned a1, unsigned a2, unsigned a3)
|
||||
{
|
||||
counter += a0 + a1 + a2 + a3;
|
||||
}
|
||||
|
||||
void count3(unsigned a0, unsigned a1, unsigned a2)
|
||||
{
|
||||
counter += a0 + a1 + a2;
|
||||
}
|
||||
|
||||
void count2(unsigned a0, unsigned a1)
|
||||
{
|
||||
counter += a0 + a1;
|
||||
}
|
||||
|
||||
void count1(unsigned a0)
|
||||
{
|
||||
counter += a0;
|
||||
}
|
||||
|
||||
void count0()
|
||||
{
|
||||
counter += 0;
|
||||
}
|
||||
|
||||
void event_class_test()
|
||||
{
|
||||
counter = 0;
|
||||
EventQueue queue(TEST_EQUEUE_SIZE);
|
||||
|
||||
Event<void(int, int, int, int, int)> e5(&queue, count5);
|
||||
Event<void(int, int, int, int)> e4(&queue, count5, 1);
|
||||
Event<void(int, int, int)> e3(&queue, count5, 1, 1);
|
||||
Event<void(int, int)> e2(&queue, count5, 1, 1, 1);
|
||||
Event<void(int)> e1(&queue, count5, 1, 1, 1, 1);
|
||||
Event<void()> e0(&queue, count5, 1, 1, 1, 1, 1);
|
||||
|
||||
e5.post(1, 1, 1, 1, 1);
|
||||
e4.post(1, 1, 1, 1);
|
||||
e3.post(1, 1, 1);
|
||||
e2.post(1, 1);
|
||||
e1.post(1);
|
||||
e0.post();
|
||||
|
||||
queue.dispatch(0);
|
||||
|
||||
TEST_ASSERT_EQUAL(counter, 30);
|
||||
}
|
||||
|
||||
void event_class_helper_test()
|
||||
{
|
||||
counter = 0;
|
||||
EventQueue queue(TEST_EQUEUE_SIZE);
|
||||
|
||||
Event<void()> e5 = queue.event(count5, 1, 1, 1, 1, 1);
|
||||
Event<void()> e4 = queue.event(count4, 1, 1, 1, 1);
|
||||
Event<void()> e3 = queue.event(count3, 1, 1, 1);
|
||||
Event<void()> e2 = queue.event(count2, 1, 1);
|
||||
Event<void()> e1 = queue.event(count1, 1);
|
||||
Event<void()> e0 = queue.event(count0);
|
||||
|
||||
e5.post();
|
||||
e4.post();
|
||||
e3.post();
|
||||
e2.post();
|
||||
e1.post();
|
||||
e0.post();
|
||||
|
||||
queue.dispatch(0);
|
||||
|
||||
TEST_ASSERT_EQUAL(counter, 15);
|
||||
}
|
||||
|
||||
void event_inference_test()
|
||||
{
|
||||
counter = 0;
|
||||
EventQueue queue(TEST_EQUEUE_SIZE);
|
||||
|
||||
queue.event(count5, 1, 1, 1, 1, 1).post();
|
||||
queue.event(count5, 1, 1, 1, 1).post(1);
|
||||
queue.event(count5, 1, 1, 1).post(1, 1);
|
||||
queue.event(count5, 1, 1).post(1, 1, 1);
|
||||
queue.event(count5, 1).post(1, 1, 1, 1);
|
||||
queue.event(count5).post(1, 1, 1, 1, 1);
|
||||
|
||||
queue.event(callback(count5), 1, 1, 1, 1, 1).post();
|
||||
queue.event(callback(count5), 1, 1, 1, 1).post(1);
|
||||
queue.event(callback(count5), 1, 1, 1).post(1, 1);
|
||||
queue.event(callback(count5), 1, 1).post(1, 1, 1);
|
||||
queue.event(callback(count5), 1).post(1, 1, 1, 1);
|
||||
queue.event(callback(count5)).post(1, 1, 1, 1, 1);
|
||||
|
||||
queue.dispatch(0);
|
||||
|
||||
TEST_ASSERT_EQUAL(counter, 60);
|
||||
}
|
||||
|
||||
int timeleft_events[2];
|
||||
|
||||
void check_time_left(EventQueue *queue, int index, int expected)
|
||||
{
|
||||
const int event_id = timeleft_events[index];
|
||||
TEST_ASSERT_INT_WITHIN(ALLOWED_TIME_LEFT_TOLERANCE_MS, expected, queue->time_left(event_id));
|
||||
touched = true;
|
||||
}
|
||||
|
||||
void time_left(EventQueue *queue, int index)
|
||||
{
|
||||
const int event_id = timeleft_events[index];
|
||||
TEST_ASSERT_EQUAL(0, queue->time_left(event_id));
|
||||
}
|
||||
|
||||
void time_left_test()
|
||||
{
|
||||
EventQueue queue(TEST_EQUEUE_SIZE);
|
||||
|
||||
// Enque check events
|
||||
TEST_ASSERT(queue.call_in(50, check_time_left, &queue, 0, 100 - 50));
|
||||
TEST_ASSERT(queue.call_in(200, check_time_left, &queue, 1, 200 - 200));
|
||||
|
||||
// Enque events to be checked
|
||||
timeleft_events[0] = queue.call_in(100, time_left, &queue, 0);
|
||||
timeleft_events[1] = queue.call_in(200, time_left, &queue, 1);
|
||||
TEST_ASSERT(timeleft_events[0]);
|
||||
TEST_ASSERT(timeleft_events[1]);
|
||||
|
||||
queue.dispatch(300);
|
||||
|
||||
// Ensure check was called
|
||||
TEST_ASSERT(touched);
|
||||
touched = false;
|
||||
|
||||
int id = queue.call(func0);
|
||||
TEST_ASSERT(id);
|
||||
TEST_ASSERT_EQUAL(0, queue.time_left(id));
|
||||
queue.dispatch(10);
|
||||
|
||||
// Test invalid event id
|
||||
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);
|
||||
e1.delay(10);
|
||||
e1.period(10);
|
||||
int id1 = e1.post();
|
||||
TEST_ASSERT_NOT_EQUAL(0, id1);
|
||||
EventTest e2_test;
|
||||
Event<void()> e2 = queue.event(&e2_test, &EventTest::f1, 3);
|
||||
e2.period(10);
|
||||
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);
|
||||
e3.period(10);
|
||||
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.period(10);
|
||||
ue2.call_on(&queue);
|
||||
TEST_ASSERT_EQUAL(false, ue2.try_call());
|
||||
ue3.period(10);
|
||||
ue3.delay(50);
|
||||
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(101);
|
||||
|
||||
TEST_ASSERT_EQUAL(true, touched);
|
||||
TEST_ASSERT_EQUAL(1, ue1_test.counter);
|
||||
TEST_ASSERT_EQUAL(33, ue2_test.counter);
|
||||
TEST_ASSERT_EQUAL(90, ue3_test.counter);
|
||||
TEST_ASSERT_EQUAL(0, ue4_test.counter);
|
||||
TEST_ASSERT_EQUAL(10, e1_test.counter);
|
||||
TEST_ASSERT_EQUAL(0, e2_test.counter);
|
||||
TEST_ASSERT_EQUAL(165, e3_test.counter);
|
||||
|
||||
// user allocated event have to be canceled(removed from the queue) before destruction
|
||||
// cancel all periodic user events
|
||||
ue2.cancel();
|
||||
ue3.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static EventQueue g_queue(0);
|
||||
static auto ue0 = g_queue.make_user_allocated_event(func0);
|
||||
static EventTest test1;
|
||||
static auto ue1 = make_user_allocated_event(&test1, &EventTest::f0);
|
||||
static EventTest test2;
|
||||
static auto ue2 = g_queue.make_user_allocated_event(&test2, &EventTest::f1, 3);
|
||||
static EventTest test3;
|
||||
static auto ue3 = make_user_allocated_event(&test3, &EventTest::f5, 1, 2, 3, 4, 5);
|
||||
static EventTest test4;
|
||||
static auto ue4 = g_queue.make_user_allocated_event(&test4, &EventTest::f5, 1, 2, 3, 4, 5);
|
||||
|
||||
|
||||
/** 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());
|
||||
|
||||
ue0.delay(100);
|
||||
ue0.period(200);
|
||||
|
||||
ue1.delay(100);
|
||||
ue1.period(200);
|
||||
|
||||
ue2.delay(100);
|
||||
ue2.period(200);
|
||||
|
||||
ue3.delay(100);
|
||||
ue3.period(200);
|
||||
|
||||
ue4.delay(100);
|
||||
ue4.period(200);
|
||||
|
||||
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();
|
||||
ue4.cancel();
|
||||
TEST_ASSERT_EQUAL(true, ue4.try_call());
|
||||
g_queue.cancel(&ue4);
|
||||
g_queue.cancel(&ue4);
|
||||
|
||||
g_queue.dispatch(400);
|
||||
|
||||
TEST_ASSERT_EQUAL(2, test1.counter);
|
||||
TEST_ASSERT_EQUAL(6, test2.counter);
|
||||
TEST_ASSERT_EQUAL(30, test3.counter);
|
||||
TEST_ASSERT_EQUAL(0, test4.counter);
|
||||
|
||||
ue4.delay(1);
|
||||
TEST_ASSERT_EQUAL(true, ue4.try_call());
|
||||
g_queue.dispatch(1);
|
||||
|
||||
TEST_ASSERT_EQUAL(2, test1.counter);
|
||||
TEST_ASSERT_EQUAL(6, test2.counter);
|
||||
TEST_ASSERT_EQUAL(30, test3.counter);
|
||||
TEST_ASSERT_EQUAL(15, test4.counter);
|
||||
}
|
||||
|
||||
// Test setup
|
||||
utest::v1::status_t test_setup(const size_t number_of_cases)
|
||||
{
|
||||
GREENTEA_SETUP(20, "default_auto");
|
||||
return verbose_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
const Case cases[] = {
|
||||
Case("Testing calls with 5 args", simple_posts_test5),
|
||||
Case("Testing calls with 4 args", simple_posts_test4),
|
||||
Case("Testing calls with 3 args", simple_posts_test3),
|
||||
Case("Testing calls with 2 args", simple_posts_test2),
|
||||
Case("Testing calls with 1 args", simple_posts_test1),
|
||||
Case("Testing calls with 0 args", simple_posts_test0),
|
||||
|
||||
Case("Testing call_in", call_in_test<20>),
|
||||
Case("Testing call_every", call_every_test<20>),
|
||||
|
||||
Case("Testing allocate failure", allocate_failure_test),
|
||||
|
||||
Case("Testing event cancel 1", cancel_test1<20>),
|
||||
Case("Testing the event class", event_class_test),
|
||||
Case("Testing the event class helpers", event_class_helper_test),
|
||||
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);
|
||||
|
||||
int main()
|
||||
{
|
||||
return !Harness::run(specification);
|
||||
}
|
||||
|
||||
#endif // !DEVICE_USTICKER
|
||||
151
events/tests/TESTS/events/timing/main.cpp
Normal file
151
events/tests/TESTS/events/timing/main.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "mbed_events.h"
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity.h"
|
||||
#include "utest.h"
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
#if !DEVICE_USTICKER
|
||||
#error [NOT_SUPPORTED] test not supported
|
||||
#else
|
||||
|
||||
// Test delay
|
||||
#ifndef TEST_EVENTS_TIMING_TIME
|
||||
#define TEST_EVENTS_TIMING_TIME 20000
|
||||
#endif
|
||||
|
||||
#ifndef TEST_EVENTS_TIMING_MEAN
|
||||
#define TEST_EVENTS_TIMING_MEAN 25
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846264338327950288
|
||||
#endif
|
||||
|
||||
// Random number generation to skew timing values
|
||||
float gauss(float mu, float sigma)
|
||||
{
|
||||
float x = (float)rand() / ((float)RAND_MAX + 1);
|
||||
float y = (float)rand() / ((float)RAND_MAX + 1);
|
||||
float x2pi = x * 2.0 * M_PI;
|
||||
float g2rad = sqrt(-2.0 * log(1.0 - y));
|
||||
float z = cos(x2pi) * g2rad;
|
||||
return mu + z * sigma;
|
||||
}
|
||||
|
||||
float chisq(float sigma)
|
||||
{
|
||||
return pow(gauss(0, sqrt(sigma)), 2);
|
||||
}
|
||||
|
||||
|
||||
Timer timer;
|
||||
DigitalOut led(LED1);
|
||||
|
||||
equeue_sema_t sema;
|
||||
|
||||
// Timer timing test
|
||||
void timer_timing_test()
|
||||
{
|
||||
timer.reset();
|
||||
timer.start();
|
||||
int prev = timer.read_us();
|
||||
|
||||
while (prev < TEST_EVENTS_TIMING_TIME * 1000) {
|
||||
int next = timer.read_us();
|
||||
if (next < prev) {
|
||||
printf("backwards drift %d -> %d (%08x -> %08x)\r\n",
|
||||
prev, next, prev, next);
|
||||
}
|
||||
TEST_ASSERT(next >= prev);
|
||||
prev = next;
|
||||
}
|
||||
}
|
||||
|
||||
// equeue tick timing test
|
||||
void tick_timing_test()
|
||||
{
|
||||
unsigned start = equeue_tick();
|
||||
int prev = 0;
|
||||
|
||||
while (prev < TEST_EVENTS_TIMING_TIME) {
|
||||
int next = equeue_tick() - start;
|
||||
if (next < prev) {
|
||||
printf("backwards drift %d -> %d (%08x -> %08x)\r\n",
|
||||
prev, next, prev, next);
|
||||
}
|
||||
TEST_ASSERT(next >= prev);
|
||||
prev = next;
|
||||
}
|
||||
}
|
||||
|
||||
// equeue semaphore timing test
|
||||
void semaphore_timing_test()
|
||||
{
|
||||
srand(0);
|
||||
timer.reset();
|
||||
timer.start();
|
||||
|
||||
int err = equeue_sema_create(&sema);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
while (timer.read_ms() < TEST_EVENTS_TIMING_TIME) {
|
||||
int delay = chisq(TEST_EVENTS_TIMING_MEAN);
|
||||
|
||||
int start = timer.read_us();
|
||||
equeue_sema_wait(&sema, delay);
|
||||
int taken = timer.read_us() - start;
|
||||
|
||||
if (taken < (delay * 1000 - 5000) || taken > (delay * 1000 + 5000)) {
|
||||
printf("delay %dms => error %dus\r\n", delay, abs(1000 * delay - taken));
|
||||
}
|
||||
|
||||
TEST_ASSERT_INT_WITHIN(5000, taken, delay * 1000);
|
||||
|
||||
led = !led;
|
||||
}
|
||||
|
||||
equeue_sema_destroy(&sema);
|
||||
}
|
||||
|
||||
|
||||
// Test setup
|
||||
utest::v1::status_t test_setup(const size_t number_of_cases)
|
||||
{
|
||||
GREENTEA_SETUP((number_of_cases + 1)*TEST_EVENTS_TIMING_TIME / 1000, "default_auto");
|
||||
return verbose_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
const Case cases[] = {
|
||||
Case("Testing accuracy of timer", timer_timing_test),
|
||||
Case("Testing accuracy of equeue tick", tick_timing_test),
|
||||
Case("Testing accuracy of equeue semaphore", semaphore_timing_test),
|
||||
};
|
||||
|
||||
Specification specification(test_setup, cases);
|
||||
|
||||
int main()
|
||||
{
|
||||
return !Harness::run(specification);
|
||||
}
|
||||
|
||||
#endif // !DEVICE_USTICKER
|
||||
1114
events/tests/UNITTESTS/equeue/test_equeue.cpp
Normal file
1114
events/tests/UNITTESTS/equeue/test_equeue.cpp
Normal file
File diff suppressed because it is too large
Load Diff
27
events/tests/UNITTESTS/equeue/unittest.cmake
Normal file
27
events/tests/UNITTESTS/equeue/unittest.cmake
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
####################
|
||||
# UNIT TESTS
|
||||
####################
|
||||
|
||||
list(REMOVE_ITEM unittest-includes ${PROJECT_SOURCE_DIR}/../events/tests/UNITTESTS/target_h ${PROJECT_SOURCE_DIR}/../events/test/UNITTESTS/target_h/equeue)
|
||||
|
||||
set(unittest-includes ${unittest-includes}
|
||||
../events/source
|
||||
../events/include/events
|
||||
../events/include/events/internal
|
||||
)
|
||||
|
||||
set(unittest-sources
|
||||
../events/source/equeue.c
|
||||
)
|
||||
|
||||
set(unittest-test-sources
|
||||
../events/tests/UNITTESTS/equeue/test_equeue.cpp
|
||||
../events/tests/UNITTESTS/stubs/EqueuePosix_stub.c
|
||||
)
|
||||
|
||||
set(unittest-test-flags
|
||||
-pthread
|
||||
-DEQUEUE_PLATFORM_POSIX
|
||||
)
|
||||
|
||||
120
events/tests/UNITTESTS/stubs/EqueuePosix_stub.c
Normal file
120
events/tests/UNITTESTS/stubs/EqueuePosix_stub.c
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "internal/equeue_platform.h"
|
||||
|
||||
#if defined(EQUEUE_PLATFORM_POSIX)
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* Using global variable as a simulation of passing time. Use of sleep functions may cause problems with thread preempting, which can lead to bad timings.
|
||||
* This problem does not occur on targets.
|
||||
* This variable is only increased in equeue_sema_wait function and in functions that simulate pass of time.
|
||||
*/
|
||||
unsigned int equeue_global_time = 0;
|
||||
|
||||
// Tick operations
|
||||
void equeue_tick_init(void) {}
|
||||
|
||||
unsigned equeue_tick(void)
|
||||
{
|
||||
return equeue_global_time;
|
||||
}
|
||||
|
||||
|
||||
// Mutex operations
|
||||
int equeue_mutex_create(equeue_mutex_t *m)
|
||||
{
|
||||
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)
|
||||
{
|
||||
pthread_mutex_destroy(m);
|
||||
}
|
||||
|
||||
void equeue_mutex_lock(equeue_mutex_t *m)
|
||||
{
|
||||
pthread_mutex_lock(m);
|
||||
}
|
||||
|
||||
void equeue_mutex_unlock(equeue_mutex_t *m)
|
||||
{
|
||||
pthread_mutex_unlock(m);
|
||||
}
|
||||
|
||||
|
||||
// Semaphore operations
|
||||
int equeue_sema_create(equeue_sema_t *s)
|
||||
{
|
||||
int err = pthread_mutex_init(&s->mutex, 0);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = pthread_cond_init(&s->cond, 0);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
s->signal = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void equeue_sema_destroy(equeue_sema_t *s)
|
||||
{
|
||||
pthread_cond_destroy(&s->cond);
|
||||
pthread_mutex_destroy(&s->mutex);
|
||||
}
|
||||
|
||||
void equeue_sema_signal(equeue_sema_t *s)
|
||||
{
|
||||
pthread_mutex_lock(&s->mutex);
|
||||
s->signal = true;
|
||||
pthread_cond_signal(&s->cond);
|
||||
pthread_mutex_unlock(&s->mutex);
|
||||
}
|
||||
|
||||
bool equeue_sema_wait(equeue_sema_t *s, int ms)
|
||||
{
|
||||
pthread_mutex_lock(&s->mutex);
|
||||
if (!s->signal) {
|
||||
if (ms < 0) {
|
||||
pthread_cond_wait(&s->cond, &s->mutex);
|
||||
} else {
|
||||
for (int i = 0; i < ms; i++) {
|
||||
equeue_global_time++;
|
||||
}
|
||||
// If ms == 0 increase time so functions don't get stuck in infinite loops.
|
||||
if (ms == 0) {
|
||||
equeue_global_time++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool signal = s->signal;
|
||||
s->signal = false;
|
||||
pthread_mutex_unlock(&s->mutex);
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
#endif
|
||||
36
events/tests/UNITTESTS/target_h/equeue/equeue_platform.h
Normal file
36
events/tests/UNITTESTS/target_h/equeue/equeue_platform.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef EQUEUE_PLATFORM_H
|
||||
#define EQUEUE_PLATFORM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef unsigned equeue_mutex_t;
|
||||
|
||||
typedef struct equeue_sema {
|
||||
} equeue_sema_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //EQUEUE_PLATFORM_H
|
||||
25
events/tests/UNITTESTS/target_h/mbed_events.h
Normal file
25
events/tests/UNITTESTS/target_h/mbed_events.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_EVENTS_H
|
||||
#define MBED_EVENTS_H
|
||||
|
||||
#include "events/EventQueue.h"
|
||||
|
||||
#include "events/mbed_shared_queues.h"
|
||||
|
||||
#endif
|
||||
55
events/tests/unit/Makefile
Normal file
55
events/tests/unit/Makefile
Normal file
@@ -0,0 +1,55 @@
|
||||
TARGET = libequeue.a
|
||||
|
||||
CC = gcc
|
||||
AR = ar
|
||||
SIZE = size
|
||||
|
||||
SRC += $(wildcard ../../source/*.c)
|
||||
OBJ := $(SRC:.c=.o)
|
||||
DEP := $(SRC:.c=.d)
|
||||
ASM := $(SRC:.c=.s)
|
||||
|
||||
ifdef DEBUG
|
||||
CFLAGS += -O0 -g3
|
||||
else
|
||||
CFLAGS += -O2
|
||||
endif
|
||||
ifdef WORD
|
||||
CFLAGS += -m$(WORD)
|
||||
endif
|
||||
CFLAGS += -I. -I../../include
|
||||
CFLAGS += -std=c99
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -D_XOPEN_SOURCE=600
|
||||
|
||||
LFLAGS += -pthread
|
||||
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
prof: prof.o $(OBJ)
|
||||
$(CC) $(CFLAGS) $^ $(LFLAGS) -o prof
|
||||
./prof
|
||||
|
||||
asm: $(ASM)
|
||||
|
||||
size: $(OBJ)
|
||||
$(SIZE) -t $^
|
||||
|
||||
-include $(DEP)
|
||||
|
||||
%.a: $(OBJ)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c -MMD $(CFLAGS) $< -o $@
|
||||
|
||||
%.s: %.c
|
||||
$(CC) -S $(CFLAGS) $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET)
|
||||
rm -f prof prof.o prof.d
|
||||
rm -f $(OBJ)
|
||||
rm -f $(DEP)
|
||||
rm -f $(ASM)
|
||||
424
events/tests/unit/prof.c
Normal file
424
events/tests/unit/prof.c
Normal file
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
* Profiling framework for the events library
|
||||
*
|
||||
* Copyright (c) 2016 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "events/equeue.h"
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
||||
// Performance measurement utils
|
||||
#define PROF_RUNS 5
|
||||
#define PROF_INTERVAL 100000000
|
||||
|
||||
#define prof_volatile(t) __attribute__((unused)) volatile t
|
||||
|
||||
typedef uint64_t prof_cycle_t;
|
||||
|
||||
static volatile prof_cycle_t prof_start_cycle;
|
||||
static volatile prof_cycle_t prof_stop_cycle;
|
||||
static prof_cycle_t prof_accum_cycle;
|
||||
static prof_cycle_t prof_baseline_cycle;
|
||||
static prof_cycle_t prof_iterations;
|
||||
static const char *prof_units;
|
||||
|
||||
#define prof_cycle() ({ \
|
||||
uint32_t a, b; \
|
||||
__asm__ volatile ("rdtsc" : "=a" (a), "=d" (b)); \
|
||||
((uint64_t)b << 32) | (uint64_t)a; \
|
||||
})
|
||||
|
||||
#define prof_loop() \
|
||||
for (prof_iterations = 0; \
|
||||
prof_accum_cycle < PROF_INTERVAL; \
|
||||
prof_iterations++)
|
||||
|
||||
#define prof_start() ({ \
|
||||
prof_start_cycle = prof_cycle(); \
|
||||
})
|
||||
|
||||
#define prof_stop() ({ \
|
||||
prof_stop_cycle = prof_cycle(); \
|
||||
prof_accum_cycle += prof_stop_cycle - prof_start_cycle; \
|
||||
})
|
||||
|
||||
#define prof_result(value, units) ({ \
|
||||
prof_accum_cycle = value+prof_baseline_cycle; \
|
||||
prof_iterations = 1; \
|
||||
prof_units = units; \
|
||||
})
|
||||
|
||||
#define prof_measure(func, ...) ({ \
|
||||
printf("%s: ...", #func); \
|
||||
fflush(stdout); \
|
||||
\
|
||||
prof_units = "cycles"; \
|
||||
prof_cycle_t runs[PROF_RUNS]; \
|
||||
for (int i = 0; i < PROF_RUNS; i++) { \
|
||||
prof_accum_cycle = 0; \
|
||||
prof_iterations = 0; \
|
||||
func(__VA_ARGS__); \
|
||||
runs[i] = prof_accum_cycle / prof_iterations; \
|
||||
} \
|
||||
\
|
||||
prof_cycle_t res = runs[0]; \
|
||||
for (int i = 0; i < PROF_RUNS; i++) { \
|
||||
if (runs[i] < res) { \
|
||||
res = runs[i]; \
|
||||
} \
|
||||
} \
|
||||
res -= prof_baseline_cycle; \
|
||||
printf("\r%s: %"PRIu64" %s", #func, res, prof_units); \
|
||||
\
|
||||
if (!isatty(0)) { \
|
||||
prof_cycle_t prev; \
|
||||
while (scanf("%*[^0-9]%"PRIu64, &prev) == 0); \
|
||||
int64_t perc = 100*((int64_t)prev - (int64_t)res) / (int64_t)prev; \
|
||||
\
|
||||
if (perc > 10) { \
|
||||
printf(" (\e[32m%+"PRId64"%%\e[0m)", perc); \
|
||||
} else if (perc < -10) { \
|
||||
printf(" (\e[31m%+"PRId64"%%\e[0m)", perc); \
|
||||
} else { \
|
||||
printf(" (%+"PRId64"%%)", perc); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
printf("\n"); \
|
||||
res; \
|
||||
})
|
||||
|
||||
#define prof_baseline(func, ...) ({ \
|
||||
prof_baseline_cycle = 0; \
|
||||
prof_baseline_cycle = prof_measure(func, __VA_ARGS__); \
|
||||
})
|
||||
|
||||
|
||||
// Various test functions
|
||||
void no_func(void *eh)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// Actual performance tests
|
||||
void baseline_prof(void)
|
||||
{
|
||||
prof_loop() {
|
||||
prof_start();
|
||||
__asm__ volatile("");
|
||||
prof_stop();
|
||||
}
|
||||
}
|
||||
|
||||
void equeue_tick_prof(void)
|
||||
{
|
||||
prof_volatile(unsigned) res;
|
||||
prof_loop() {
|
||||
prof_start();
|
||||
res = equeue_tick();
|
||||
prof_stop();
|
||||
}
|
||||
}
|
||||
|
||||
void equeue_alloc_prof(void)
|
||||
{
|
||||
struct equeue q;
|
||||
equeue_create(&q, 32 * EQUEUE_EVENT_SIZE);
|
||||
|
||||
prof_loop() {
|
||||
prof_start();
|
||||
void *e = equeue_alloc(&q, 8 * sizeof(int));
|
||||
prof_stop();
|
||||
|
||||
equeue_dealloc(&q, e);
|
||||
}
|
||||
|
||||
equeue_destroy(&q);
|
||||
}
|
||||
|
||||
void equeue_alloc_many_prof(int count)
|
||||
{
|
||||
struct equeue q;
|
||||
equeue_create(&q, count * EQUEUE_EVENT_SIZE);
|
||||
|
||||
void *es[count];
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
es[i] = equeue_alloc(&q, (i % 4) * sizeof(int));
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
equeue_dealloc(&q, es[i]);
|
||||
}
|
||||
|
||||
prof_loop() {
|
||||
prof_start();
|
||||
void *e = equeue_alloc(&q, 8 * sizeof(int));
|
||||
prof_stop();
|
||||
|
||||
equeue_dealloc(&q, e);
|
||||
}
|
||||
|
||||
equeue_destroy(&q);
|
||||
}
|
||||
|
||||
void equeue_post_prof(void)
|
||||
{
|
||||
struct equeue q;
|
||||
equeue_create(&q, EQUEUE_EVENT_SIZE);
|
||||
|
||||
prof_loop() {
|
||||
void *e = equeue_alloc(&q, 0);
|
||||
|
||||
prof_start();
|
||||
int id = equeue_post(&q, no_func, e);
|
||||
prof_stop();
|
||||
|
||||
equeue_cancel(&q, id);
|
||||
}
|
||||
|
||||
equeue_destroy(&q);
|
||||
}
|
||||
|
||||
void equeue_post_many_prof(int count)
|
||||
{
|
||||
struct equeue q;
|
||||
equeue_create(&q, count * EQUEUE_EVENT_SIZE);
|
||||
|
||||
for (int i = 0; i < count - 1; i++) {
|
||||
equeue_call(&q, no_func, 0);
|
||||
}
|
||||
|
||||
prof_loop() {
|
||||
void *e = equeue_alloc(&q, 0);
|
||||
|
||||
prof_start();
|
||||
int id = equeue_post(&q, no_func, e);
|
||||
prof_stop();
|
||||
|
||||
equeue_cancel(&q, id);
|
||||
}
|
||||
|
||||
equeue_destroy(&q);
|
||||
}
|
||||
|
||||
void equeue_post_future_prof(void)
|
||||
{
|
||||
struct equeue q;
|
||||
equeue_create(&q, EQUEUE_EVENT_SIZE);
|
||||
|
||||
prof_loop() {
|
||||
void *e = equeue_alloc(&q, 0);
|
||||
equeue_event_delay(e, 1000);
|
||||
|
||||
prof_start();
|
||||
int id = equeue_post(&q, no_func, e);
|
||||
prof_stop();
|
||||
|
||||
equeue_cancel(&q, id);
|
||||
}
|
||||
|
||||
equeue_destroy(&q);
|
||||
}
|
||||
|
||||
void equeue_post_future_many_prof(int count)
|
||||
{
|
||||
struct equeue q;
|
||||
equeue_create(&q, count * EQUEUE_EVENT_SIZE);
|
||||
|
||||
for (int i = 0; i < count - 1; i++) {
|
||||
equeue_call(&q, no_func, 0);
|
||||
}
|
||||
|
||||
prof_loop() {
|
||||
void *e = equeue_alloc(&q, 0);
|
||||
equeue_event_delay(e, 1000);
|
||||
|
||||
prof_start();
|
||||
int id = equeue_post(&q, no_func, e);
|
||||
prof_stop();
|
||||
|
||||
equeue_cancel(&q, id);
|
||||
}
|
||||
|
||||
equeue_destroy(&q);
|
||||
}
|
||||
|
||||
void equeue_dispatch_prof(void)
|
||||
{
|
||||
struct equeue q;
|
||||
equeue_create(&q, EQUEUE_EVENT_SIZE);
|
||||
|
||||
prof_loop() {
|
||||
equeue_call(&q, no_func, 0);
|
||||
|
||||
prof_start();
|
||||
equeue_dispatch(&q, 0);
|
||||
prof_stop();
|
||||
}
|
||||
|
||||
equeue_destroy(&q);
|
||||
}
|
||||
|
||||
void equeue_dispatch_many_prof(int count)
|
||||
{
|
||||
struct equeue q;
|
||||
equeue_create(&q, count * EQUEUE_EVENT_SIZE);
|
||||
|
||||
prof_loop() {
|
||||
for (int i = 0; i < count; i++) {
|
||||
equeue_call(&q, no_func, 0);
|
||||
}
|
||||
|
||||
prof_start();
|
||||
equeue_dispatch(&q, 0);
|
||||
prof_stop();
|
||||
}
|
||||
|
||||
equeue_destroy(&q);
|
||||
}
|
||||
|
||||
void equeue_cancel_prof(void)
|
||||
{
|
||||
struct equeue q;
|
||||
equeue_create(&q, EQUEUE_EVENT_SIZE);
|
||||
|
||||
prof_loop() {
|
||||
int id = equeue_call(&q, no_func, 0);
|
||||
|
||||
prof_start();
|
||||
equeue_cancel(&q, id);
|
||||
prof_stop();
|
||||
}
|
||||
|
||||
equeue_destroy(&q);
|
||||
}
|
||||
|
||||
void equeue_cancel_many_prof(int count)
|
||||
{
|
||||
struct equeue q;
|
||||
equeue_create(&q, count * EQUEUE_EVENT_SIZE);
|
||||
|
||||
for (int i = 0; i < count - 1; i++) {
|
||||
equeue_call(&q, no_func, 0);
|
||||
}
|
||||
|
||||
prof_loop() {
|
||||
int id = equeue_call(&q, no_func, 0);
|
||||
|
||||
prof_start();
|
||||
equeue_cancel(&q, id);
|
||||
prof_stop();
|
||||
}
|
||||
|
||||
equeue_destroy(&q);
|
||||
}
|
||||
|
||||
void equeue_alloc_size_prof(void)
|
||||
{
|
||||
size_t size = 32 * EQUEUE_EVENT_SIZE;
|
||||
|
||||
struct equeue q;
|
||||
equeue_create(&q, size);
|
||||
equeue_alloc(&q, 0);
|
||||
|
||||
prof_result(size - q.slab.size, "bytes");
|
||||
|
||||
equeue_destroy(&q);
|
||||
}
|
||||
|
||||
void equeue_alloc_many_size_prof(int count)
|
||||
{
|
||||
size_t size = count * EQUEUE_EVENT_SIZE;
|
||||
|
||||
struct equeue q;
|
||||
equeue_create(&q, size);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
equeue_alloc(&q, (i % 4) * sizeof(int));
|
||||
}
|
||||
|
||||
prof_result(size - q.slab.size, "bytes");
|
||||
|
||||
equeue_destroy(&q);
|
||||
}
|
||||
|
||||
void equeue_alloc_fragmented_size_prof(int count)
|
||||
{
|
||||
size_t size = count * EQUEUE_EVENT_SIZE;
|
||||
|
||||
struct equeue q;
|
||||
equeue_create(&q, size);
|
||||
|
||||
void *es[count];
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
es[i] = equeue_alloc(&q, (i % 4) * sizeof(int));
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
equeue_dealloc(&q, es[i]);
|
||||
}
|
||||
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
es[i] = equeue_alloc(&q, (i % 4) * sizeof(int));
|
||||
}
|
||||
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
equeue_dealloc(&q, es[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
equeue_alloc(&q, (i % 4) * sizeof(int));
|
||||
}
|
||||
|
||||
prof_result(size - q.slab.size, "bytes");
|
||||
|
||||
equeue_destroy(&q);
|
||||
}
|
||||
|
||||
|
||||
// Entry point
|
||||
int main()
|
||||
{
|
||||
printf("beginning profiling...\n");
|
||||
|
||||
prof_baseline(baseline_prof);
|
||||
|
||||
prof_measure(equeue_tick_prof);
|
||||
prof_measure(equeue_alloc_prof);
|
||||
prof_measure(equeue_post_prof);
|
||||
prof_measure(equeue_post_future_prof);
|
||||
prof_measure(equeue_dispatch_prof);
|
||||
prof_measure(equeue_cancel_prof);
|
||||
|
||||
prof_measure(equeue_alloc_many_prof, 1000);
|
||||
prof_measure(equeue_post_many_prof, 1000);
|
||||
prof_measure(equeue_post_future_many_prof, 1000);
|
||||
prof_measure(equeue_dispatch_many_prof, 100);
|
||||
prof_measure(equeue_cancel_many_prof, 100);
|
||||
|
||||
prof_measure(equeue_alloc_size_prof);
|
||||
prof_measure(equeue_alloc_many_size_prof, 1000);
|
||||
prof_measure(equeue_alloc_fragmented_size_prof, 1000);
|
||||
|
||||
printf("done!\n");
|
||||
}
|
||||
Reference in New Issue
Block a user