Skip to content

Commit 4fa864a

Browse files
equeue: add user allocated event support
Allow posting events allocated outside queue memory
1 parent e4e6c64 commit 4fa864a

File tree

2 files changed

+54
-19
lines changed

2 files changed

+54
-19
lines changed

events/equeue.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,9 @@ void equeue_event_dtor(void *event, void (*dtor)(void *));
165165
// Post an event onto the event queue
166166
//
167167
// The equeue_post function takes a callback and a pointer to an event
168-
// allocated by equeue_alloc. The specified callback will be executed in the
169-
// context of the event queue's dispatch loop with the allocated event
170-
// as its argument.
168+
// allocated by equeue_alloc or allocated by user. The specified callback will
169+
// be executed in the context of the event queue's dispatch loop with
170+
// the allocated event as its argument.
171171
//
172172
// The equeue_post function is irq safe and can act as a mechanism for
173173
// moving events out of irq contexts.

events/source/equeue.c

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@
2121
#include <stdint.h>
2222
#include <string.h>
2323

24+
// check if the event is allocaded by user - event address is outside queues internal buffer address range
25+
#define IS_USER_ALLOCATED_EVENT(e) (((unsigned int)(e) < (unsigned int)q->buffer) || ((unsigned int)(e) > ((unsigned int)q->slab.data)))
26+
// for user allocated events set id as its address with first bit set
27+
#define MAKE_USER_ALLOCATED_EVENT_ID(e) ((int)(((unsigned int)e) | 1))
28+
#define IS_USER_ALLOCATED_EVENT_ID(id) (((id) & 1) == 1)
29+
2430
// calculate the relative-difference between absolute times while
2531
// correctly handling overflow conditions
2632
static inline int equeue_tickdiff(unsigned a, unsigned b)
@@ -220,15 +226,16 @@ void equeue_dealloc(equeue_t *q, void *p)
220226
e->dtor(e + 1);
221227
}
222228

223-
equeue_mem_dealloc(q, e);
229+
if (!IS_USER_ALLOCATED_EVENT(e)) {
230+
equeue_mem_dealloc(q, e);
231+
}
224232
}
225233

226-
227234
// equeue scheduling functions
228235
static int equeue_enqueue(equeue_t *q, struct equeue_event *e, unsigned tick)
229236
{
230237
// setup event and hash local id with buffer offset for unique id
231-
int id = (e->id << q->npw2) | ((unsigned char *)e - q->buffer);
238+
int id = IS_USER_ALLOCATED_EVENT(e) ? MAKE_USER_ALLOCATED_EVENT_ID(e) : ((e->id << q->npw2) | ((unsigned char *)e - q->buffer));
232239
e->target = tick + equeue_clampdiff(e->target, tick);
233240
e->generation = q->generation;
234241

@@ -275,14 +282,29 @@ static int equeue_enqueue(equeue_t *q, struct equeue_event *e, unsigned tick)
275282

276283
static struct equeue_event *equeue_unqueue(equeue_t *q, int id)
277284
{
278-
// decode event from unique id and check that the local id matches
279-
struct equeue_event *e = (struct equeue_event *)
280-
&q->buffer[id & ((1 << q->npw2) - 1)];
281-
282-
equeue_mutex_lock(&q->queuelock);
283-
if (e->id != id >> q->npw2) {
284-
equeue_mutex_unlock(&q->queuelock);
285-
return 0;
285+
struct equeue_event *e = 0;
286+
if (IS_USER_ALLOCATED_EVENT_ID(id)) {
287+
equeue_mutex_lock(&q->queuelock);
288+
struct equeue_event *cur = q->queue;
289+
while (cur) {
290+
if (MAKE_USER_ALLOCATED_EVENT_ID(cur) == id) {
291+
e = cur;
292+
break;
293+
}
294+
cur = cur->next;
295+
}
296+
if (!e) {
297+
equeue_mutex_unlock(&q->queuelock);
298+
return 0;
299+
}
300+
} else {
301+
// decode event from unique id and check that the local id matches
302+
e = (struct equeue_event *)&q->buffer[id & ((1 << q->npw2) - 1)];
303+
equeue_mutex_lock(&q->queuelock);
304+
if (e->id != id >> q->npw2) {
305+
equeue_mutex_unlock(&q->queuelock);
306+
return 0;
307+
}
286308
}
287309

288310
// clear the event and check if already in-flight
@@ -311,7 +333,9 @@ static struct equeue_event *equeue_unqueue(equeue_t *q, int id)
311333
}
312334
}
313335

314-
equeue_incid(q, e);
336+
if (!IS_USER_ALLOCATED_EVENT_ID(id)) {
337+
equeue_incid(q, e);
338+
}
315339
equeue_mutex_unlock(&q->queuelock);
316340

317341
return e;
@@ -394,11 +418,22 @@ int equeue_timeleft(equeue_t *q, int id)
394418
return -1;
395419
}
396420

397-
// decode event from unique id and check that the local id matches
398-
struct equeue_event *e = (struct equeue_event *)
399-
&q->buffer[id & ((1 << q->npw2) - 1)];
400-
421+
struct equeue_event *e = 0;
401422
equeue_mutex_lock(&q->queuelock);
423+
if (IS_USER_ALLOCATED_EVENT_ID(id)) {
424+
struct equeue_event *cur = q->queue;
425+
while (cur) {
426+
if (MAKE_USER_ALLOCATED_EVENT_ID(cur) == id) {
427+
e = cur;
428+
break;
429+
}
430+
cur = cur->next;
431+
}
432+
} else {
433+
// decode event from unique id and check that the local id matches
434+
e = (struct equeue_event *)&q->buffer[id & ((1 << q->npw2) - 1)];
435+
}
436+
402437
if (e->id == id >> q->npw2) {
403438
ret = equeue_clampdiff(e->target, equeue_tick());
404439
}

0 commit comments

Comments
 (0)