Skip to content

Commit

Permalink
Merge pull request #20916 from derMihai/mir/event_sync_mainline
Browse files Browse the repository at this point in the history
sys/event: add event_sync()
  • Loading branch information
benpicco authored Oct 21, 2024
2 parents 616e6a5 + 9996909 commit c48247f
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 3 deletions.
25 changes: 25 additions & 0 deletions sys/event/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include "event.h"
#include "clist.h"
#include "mutex.h"
#include "thread.h"

#if IS_USED(MODULE_XTIMER)
Expand Down Expand Up @@ -174,3 +175,27 @@ event_t *event_wait_timeout_ztimer(event_queue_t *queue,
return result;
}
#endif

typedef struct {
event_t ev;
mutex_t synced;
} sync_ev_t;

static void sync_ev_handler(event_t *ev)
{
sync_ev_t *sync_ev = (sync_ev_t *)ev;
mutex_unlock(&sync_ev->synced);
}

void event_sync(event_queue_t *queue)
{
/* if we're on the queue, this would block forever */
assert(!queue->waiter || queue->waiter->pid != thread_getpid());

sync_ev_t sync_ev = {
.ev.handler = sync_ev_handler,
.synced = MUTEX_INIT_LOCKED,
};
event_post(queue, &sync_ev.ev);
mutex_lock(&sync_ev.synced);
}
21 changes: 21 additions & 0 deletions sys/include/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,27 @@ static inline void event_loop(event_queue_t *queue)
event_loop_multi(queue, 1);
}

/**
* @brief Synchronize with the last event on the queue
*
* Blocks until the last event on the queue at the moment of calling this is
* processed.
*
* @warning May not be called from the event queue, as it would block forever.
* @warning If the queue has no waiter, this will block until the queue is
* claimed. See @ref event_queue_claim()
*
* @param[in] queue event queue to sync with
*
* Usage example:
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
* event_post(queue, my_event);
* // When event_sync() returns, my_event will have been processed.
* event_sync(queue);
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
void event_sync(event_queue_t *queue);

#ifdef __cplusplus
}
#endif
Expand Down
12 changes: 9 additions & 3 deletions tests/sys/events/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
#endif

#define STACKSIZE THREAD_STACKSIZE_DEFAULT
#define PRIO (THREAD_PRIORITY_MAIN - 1)
/* in order to actually test @ref event_sync(), the waiter's prio should be lower
* than main s.t. it doesn't start executing right after events are enqueued */
#define PRIO (THREAD_PRIORITY_MAIN + 1)
#define DELAYED_QUEUES_NUMOF 2

static char stack[STACKSIZE];
Expand Down Expand Up @@ -164,15 +166,19 @@ int main(void)
event_queue_init_detached(&dqs[0]);
event_queue_init_detached(&dqs[1]);

printf("running thread that will claim event queues %p\n", (void *)&dqs);
thread_create(stack, sizeof(stack), PRIO, 0, claiming_thread, dqs, "ct");

printf("posting %p to delayed queue at index 1\n", (void *)&delayed_event1);
event_post(&dqs[1], &delayed_event1);
printf("posting %p to delayed queue at index 1\n", (void *)&delayed_event2);
event_post(&dqs[1], &delayed_event2);
printf("posting %p to delayed queue at index 0\n", (void *)&delayed_event3);
event_post(&dqs[0], &delayed_event3);

printf("running thread that will claim event queues %p\n", (void *)&dqs);
thread_create(stack, sizeof(stack), PRIO, 0, claiming_thread, dqs, "ct");
event_sync(&dqs[1]);
expect(order == 3);
printf("synced with %p\n", (void *)&delayed_event3);

/* test posting different kind of events in order to a statically
* initialized queue */
Expand Down

0 comments on commit c48247f

Please sign in to comment.