Skip to content

Commit 59baf07

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

File tree

2 files changed

+70
-19
lines changed

2 files changed

+70
-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: 67 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 EQUEUE_IS_USER_ALLOCATED_EVENT(e) (((uintptr_t)(e) < (uintptr_t)q->buffer) || ((uintptr_t)(e) > ((uintptr_t)q->slab.data)))
26+
// for user allocated events set id as its address with first bit set
27+
#define EQUEUE_MAKE_USER_ALLOCATED_EVENT_ID(e) ((int)(((uintptr_t)e) | 1))
28+
#define EQUEUE_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 (!EQUEUE_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 = EQUEUE_IS_USER_ALLOCATED_EVENT(e) ? EQUEUE_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,37 @@ 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 (EQUEUE_IS_USER_ALLOCATED_EVENT_ID(id)) {
287+
equeue_mutex_lock(&q->queuelock);
288+
struct equeue_event *cur_h = q->queue;
289+
while (cur_h && !e) {
290+
if (EQUEUE_MAKE_USER_ALLOCATED_EVENT_ID(cur_h) == id) {
291+
e = cur_h;
292+
break;
293+
}
294+
struct equeue_event *cur_v = cur_h->sibling;
295+
while (cur_v) {
296+
if (EQUEUE_MAKE_USER_ALLOCATED_EVENT_ID(cur_v) == id) {
297+
e = cur_v;
298+
break;
299+
}
300+
cur_v = cur_v->sibling;
301+
}
302+
cur_h = cur_h->next;
303+
}
304+
if (!e) {
305+
equeue_mutex_unlock(&q->queuelock);
306+
return 0;
307+
}
308+
} else {
309+
// decode event from unique id and check that the local id matches
310+
e = (struct equeue_event *)&q->buffer[id & ((1 << q->npw2) - 1)];
311+
equeue_mutex_lock(&q->queuelock);
312+
if (e->id != id >> q->npw2) {
313+
equeue_mutex_unlock(&q->queuelock);
314+
return 0;
315+
}
286316
}
287317

288318
// clear the event and check if already in-flight
@@ -311,7 +341,9 @@ static struct equeue_event *equeue_unqueue(equeue_t *q, int id)
311341
}
312342
}
313343

314-
equeue_incid(q, e);
344+
if (!EQUEUE_IS_USER_ALLOCATED_EVENT_ID(id)) {
345+
equeue_incid(q, e);
346+
}
315347
equeue_mutex_unlock(&q->queuelock);
316348

317349
return e;
@@ -394,11 +426,30 @@ int equeue_timeleft(equeue_t *q, int id)
394426
return -1;
395427
}
396428

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-
429+
struct equeue_event *e = 0;
401430
equeue_mutex_lock(&q->queuelock);
431+
if (EQUEUE_IS_USER_ALLOCATED_EVENT_ID(id)) {
432+
struct equeue_event *cur_h = q->queue;
433+
while (cur_h && !e) {
434+
if (EQUEUE_MAKE_USER_ALLOCATED_EVENT_ID(cur_h) == id) {
435+
e = cur_h;
436+
break;
437+
}
438+
struct equeue_event *cur_v = cur_h->sibling;
439+
while (cur_v) {
440+
if (EQUEUE_MAKE_USER_ALLOCATED_EVENT_ID(cur_v) == id) {
441+
e = cur_v;
442+
break;
443+
}
444+
cur_v = cur_v->sibling;
445+
}
446+
cur_h = cur_h->next;
447+
}
448+
} else {
449+
// decode event from unique id and check that the local id matches
450+
e = (struct equeue_event *)&q->buffer[id & ((1 << q->npw2) - 1)];
451+
}
452+
402453
if (e->id == id >> q->npw2) {
403454
ret = equeue_clampdiff(e->target, equeue_tick());
404455
}

0 commit comments

Comments
 (0)