Skip to content
This repository was archived by the owner on Aug 19, 2021. It is now read-only.

Commit 41e62fc

Browse files
committed
Merge commit 1b1ed81 into mbed-events/equeue
1b1ed81 Added support for low-power timers in mbed implementation 65d27b2 Moved to statically allocated Semaphores in mbed implementation b5a79ea Fixed race-conditions in non-rtos mbed wfi implementation f8dd3b0 Fixed compilation error on Cortex A platforms 90f2b7d Fixed underflow issue in deadline calculation
2 parents 8ec0934 + 1b1ed81 commit 41e62fc

File tree

4 files changed

+154
-28
lines changed

4 files changed

+154
-28
lines changed

equeue/equeue.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,9 @@ void equeue_dispatch(equeue_t *q, int ms) {
352352
equeue_mutex_lock(&q->queuelock);
353353
if (q->queue) {
354354
int diff = equeue_tickdiff(q->queue->target, tick);
355-
if (deadline < 0 || diff < deadline) {
355+
if (diff <= 0) {
356+
deadline = 0;
357+
} else if (deadline < 0 || diff < deadline) {
356358
deadline = diff;
357359
}
358360
}

equeue/equeue_mbed.cpp

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,18 @@
1313

1414
#include <stdbool.h>
1515
#include "mbed.h"
16-
#ifdef MBED_CONF_RTOS_PRESENT
17-
#include "rtos.h"
18-
#endif
1916

2017

2118
// Ticker operations
22-
static class GlobalTicker {
19+
class EqueueTicker {
2320
public:
24-
GlobalTicker() {
21+
EqueueTicker() {
2522
_tick = 0;
2623
_timer.start();
27-
_ticker.attach_us(this, &GlobalTicker::step, (1 << 16) * 1000);
24+
_ticker.attach_us(this, &EqueueTicker::update, (1 << 16) * 1000);
2825
};
2926

30-
void step() {
27+
void update() {
3128
_timer.reset();
3229
_tick += 1 << 16;
3330
}
@@ -38,12 +35,19 @@ static class GlobalTicker {
3835

3936
private:
4037
unsigned _tick;
38+
#ifdef DEVICE_LOWPOWERTIMER
39+
LowPowerTimer _timer;
40+
LowPowerTicker _ticker;
41+
#else
4142
Timer _timer;
4243
Ticker _ticker;
43-
} gticker;
44+
#endif
45+
};
46+
47+
static EqueueTicker equeue_ticker;
4448

4549
unsigned equeue_tick() {
46-
return gticker.tick();
50+
return equeue_ticker.tick();
4751
}
4852

4953

@@ -63,42 +67,55 @@ void equeue_mutex_unlock(equeue_mutex_t *m) {
6367
// Semaphore operations
6468
#ifdef MBED_CONF_RTOS_PRESENT
6569

66-
static inline Semaphore *sema(equeue_sema_t *s) {
67-
return static_cast<Semaphore*>(*s);
68-
}
69-
7070
int equeue_sema_create(equeue_sema_t *s) {
71-
*s = new Semaphore(0);
72-
return sema(s) ? 0 : -1;
71+
MBED_ASSERT(sizeof(equeue_sema_t) >= sizeof(Semaphore));
72+
new (s) Semaphore(0);
73+
return 0;
7374
}
7475

7576
void equeue_sema_destroy(equeue_sema_t *s) {
76-
delete sema(s);
77+
reinterpret_cast<Semaphore*>(s)->~Semaphore();
7778
}
7879

7980
void equeue_sema_signal(equeue_sema_t *s) {
80-
sema(s)->release();
81+
reinterpret_cast<Semaphore*>(s)->release();
8182
}
8283

8384
bool equeue_sema_wait(equeue_sema_t *s, int ms) {
84-
int t = sema(s)->wait(ms < 0 ? osWaitForever : ms);
85-
return t > 0;
85+
if (ms < 0) {
86+
ms = osWaitForever;
87+
}
88+
89+
return (reinterpret_cast<Semaphore*>(s)->wait(ms) > 0);
8690
}
8791

8892
#else
8993

9094
// Semaphore operations
91-
int equeue_sema_create(equeue_sema_t *s) { return 0; }
92-
void equeue_sema_destroy(equeue_sema_t *s) {}
93-
void equeue_sema_signal(equeue_sema_t *s) {}
95+
int equeue_sema_create(equeue_sema_t *s) {
96+
*s = false;
97+
return 0;
98+
}
9499

95-
static void equeue_sema_wakeup() {}
100+
void equeue_sema_destroy(equeue_sema_t *s) {
101+
}
102+
103+
void equeue_sema_signal(equeue_sema_t *s) {
104+
*s = true;
105+
}
96106

97107
bool equeue_sema_wait(equeue_sema_t *s, int ms) {
98108
Timeout timeout;
99-
timeout.attach_us(equeue_sema_wakeup, ms*1000);
109+
timeout.attach_us(s, equeue_sema_signal, ms*1000);
100110

101-
__WFI();
111+
core_util_critical_section_enter();
112+
while (!*(volatile equeue_sema_t *)s) {
113+
__WFI();
114+
core_util_critical_section_exit();
115+
core_util_critical_section_enter();
116+
}
117+
*s = false;
118+
core_util_critical_section_exit();
102119

103120
return true;
104121
}

equeue/equeue_sema.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ extern "C" {
2323
typedef sem_t equeue_sema_t;
2424
#elif defined(__MBED__)
2525
#ifdef MBED_CONF_RTOS_PRESENT
26-
typedef void *equeue_sema_t;
26+
typedef unsigned equeue_sema_t[8];
2727
#else
28-
typedef struct {} equeue_sema_t;
28+
typedef bool equeue_sema_t;
2929
#endif
3030
#endif
3131

equeue/tests/tests.c

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ void simple_func(void *p) {
4646
(*(int *)p)++;
4747
}
4848

49+
void sloth_func(void *p) {
50+
usleep(10000);
51+
(*(int *)p)++;
52+
}
53+
4954
struct indirect {
5055
int *touched;
5156
uint8_t buffer[7];
@@ -102,6 +107,19 @@ void cancel_func(void *p) {
102107
equeue_cancel(cancel->q, cancel->id);
103108
}
104109

110+
struct nest {
111+
equeue_t *q;
112+
void (*cb)(void *);
113+
void *data;
114+
};
115+
116+
void nest_func(void *p) {
117+
struct nest *nest = (struct nest *)p;
118+
equeue_call(nest->q, nest->cb, nest->data);
119+
120+
usleep(10000);
121+
}
122+
105123

106124
// Simple call tests
107125
void simple_call_test(void) {
@@ -375,6 +393,92 @@ void period_test(void) {
375393
equeue_destroy(&q);
376394
}
377395

396+
void nested_test(void) {
397+
equeue_t q;
398+
int err = equeue_create(&q, 2048);
399+
test_assert(!err);
400+
401+
int touched = 0;
402+
struct nest *nest = equeue_alloc(&q, sizeof(struct nest));
403+
test_assert(nest);
404+
nest->q = &q;
405+
nest->cb = simple_func;
406+
nest->data = &touched;
407+
408+
int id = equeue_post(&q, nest_func, nest);
409+
test_assert(id);
410+
411+
equeue_dispatch(&q, 5);
412+
test_assert(touched == 0);
413+
414+
equeue_dispatch(&q, 5);
415+
test_assert(touched == 1);
416+
417+
touched = 0;
418+
nest = equeue_alloc(&q, sizeof(struct nest));
419+
test_assert(nest);
420+
nest->q = &q;
421+
nest->cb = simple_func;
422+
nest->data = &touched;
423+
424+
id = equeue_post(&q, nest_func, nest);
425+
test_assert(id);
426+
427+
equeue_dispatch(&q, 20);
428+
test_assert(touched == 1);
429+
430+
equeue_destroy(&q);
431+
}
432+
433+
void sloth_test(void) {
434+
equeue_t q;
435+
int err = equeue_create(&q, 2048);
436+
test_assert(!err);
437+
438+
int touched = 0;
439+
int id = equeue_call(&q, sloth_func, &touched);
440+
test_assert(id);
441+
442+
id = equeue_call_in(&q, 5, simple_func, &touched);
443+
test_assert(id);
444+
445+
id = equeue_call_in(&q, 15, simple_func, &touched);
446+
test_assert(id);
447+
448+
equeue_dispatch(&q, 20);
449+
test_assert(touched == 3);
450+
451+
equeue_destroy(&q);
452+
}
453+
454+
void *multithread_thread(void *p) {
455+
equeue_t *q = (equeue_t *)p;
456+
equeue_dispatch(q, -1);
457+
return 0;
458+
}
459+
460+
void multithread_test(void) {
461+
equeue_t q;
462+
int err = equeue_create(&q, 2048);
463+
test_assert(!err);
464+
465+
bool touched = false;
466+
equeue_call_every(&q, 1, simple_func, &touched);
467+
468+
pthread_t thread;
469+
err = pthread_create(&thread, 0, multithread_thread, &q);
470+
test_assert(!err);
471+
472+
usleep(10000);
473+
equeue_break(&q);
474+
err = pthread_join(thread, 0);
475+
test_assert(!err);
476+
477+
test_assert(touched);
478+
479+
equeue_destroy(&q);
480+
}
481+
378482
// Barrage tests
379483
void simple_barrage_test(int N) {
380484
equeue_t q;
@@ -483,6 +587,9 @@ int main() {
483587
test_run(loop_protect_test);
484588
test_run(break_test);
485589
test_run(period_test);
590+
test_run(nested_test);
591+
test_run(sloth_test);
592+
test_run(multithread_test);
486593
test_run(simple_barrage_test, 20);
487594
test_run(fragmenting_barrage_test, 20);
488595
test_run(multithreaded_barrage_test, 20);

0 commit comments

Comments
 (0)