Skip to content

Conversation

@wangchdo
Copy link
Contributor

@wangchdo wangchdo commented Oct 21, 2025

Summary

The current event implementation uses semaphores for wait and post
operations. Since semaphores are relatively heavy-weight and intended
for resource-based synchronization, this is suboptimal.

So this patch replaced the semaphore-based mechanism with direct
scheduler operations to improve performance and reduce memory footprint.

This patch also introduce a new task state TSTATE_WAIT_EVENT to indicate
the task is waiting for a event.

Impact

improvement for the event module, no impact to other nuttx parts

Testing

ostest passed on board a2g-tc397-5v-tft (including event testcases)

image

@github-actions github-actions bot added Area: OS Components OS Components issues Size: M The size of the change in this PR is medium labels Oct 21, 2025
@wangchdo wangchdo changed the title sched/event: improve sched/event implementation with sleep/wakeup paire sched/event: improve sched/event implementation with sleep/wakeup pair Oct 22, 2025
@wangchdo wangchdo force-pushed the improve_event_1021 branch 3 times, most recently from ff596cb to fa2e152 Compare October 22, 2025 03:10
    Restore the use of critical sections to provide mutual exclusion
    between event wait and post operations. This allows replacing the
    heavier semaphore-based mechanism with direct scheduler operations
    for synchronization.

Signed-off-by: Chengdong Wang wangchengdong@lixiang.com
@wangchdo wangchdo changed the title sched/event: improve sched/event implementation with sleep/wakeup pair sched/event: Replace semaphore with direct scheduler operations in event implementation to improve performance Oct 23, 2025
@wangchdo wangchdo requested a review from anchao October 23, 2025 01:07
@wangchdo wangchdo force-pushed the improve_event_1021 branch 7 times, most recently from 2b211e7 to e3e98e8 Compare October 23, 2025 02:26
    The current event implementation uses semaphores for wait and post
    operations. Since semaphores are relatively heavy-weight and intended
    for resource-based synchronization, this is suboptimal.

    So this patch replaced the semaphore-based mechanism with direct
    scheduler operations to improve performance and reduce memory footprint.

    This patch also introduce a new task state TSTATE_WAIT_EVENT to indicate
    the task is waiting for a event.

Signed-off-by: Chengdong Wang wangchengdong@lixiang.com
{
struct list_node list; /* Waiting list of nxevent_wait_t */
volatile nxevent_mask_t events; /* Pending Events */
spinlock_t lock; /* Spinlock */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but spinlock could avoid the global big lock, why do we switch back?

Copy link
Contributor Author

@wangchdo wangchdo Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mainly for removing reliance on semaphore, after removing semaphore, we will use critical section to protect event, and spinlock is not needed any more.

The reason to remove semaphore is that it is too heavy for event timeout:

  1. It has global big lock inside the sema_wait/sema_post api,so in fact there are double lock here: spinlock for event and critical section lock for semaphore
  2. Semaphore object costs more memory
  3. It has lost of logic inside sema_wait and sema_post that are not related to event timeout, these logic is even more complicated than event itself

Indeed the lock scope is very small in event, and after removing semaphore it is even smaller, so i think this would be better

By the way The current spinlock is also a global one for event post, it uses flags = spin_lock_irqsave_nopreempt(&event->lock) api.

How do you think?

TSTATE_TASK_INACTIVE, /* BLOCKED - Initialized but not yet activated */
TSTATE_WAIT_SEM, /* BLOCKED - Waiting for a semaphore */
TSTATE_WAIT_SIG, /* BLOCKED - Waiting for a signal */
TSTATE_WAIT_EVENT, /* BLOCKED - Waiting for a event */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not continue use TSTATE_WAIT_SIG with alias

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think event is different than sleep... the main reason is for the function nxevent_wait_irq() I implemented and it is called from nxnotify_cancellation():

image

Copy link
Contributor Author

@wangchdo wangchdo Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to introduce a new state TSTATE_WAIT_EVENT...... Because although the scheduler list is shared with signals, but in event case the task not only needs a timeout, it is also blocked on a new object — the event object and then in some cases the scheduler need to do special actions for blocked task is waiting on a event(to separate it from task that is waiting on a semaphore or just is waiting for a timeout(sleep wait or signal wait)), just like this XXX_wait_irq function for task cancel cases. This is similar to how a semaphore blocks a task on a semaphore object.

@wangchdo wangchdo force-pushed the improve_event_1021 branch 2 times, most recently from 87471dc to 077e0be Compare October 24, 2025 00:56
   If the thread is blocked waiting on a event, then the
   thread must be unblocked to handle the task cancellation.

Signed-off-by: Chengdong Wang wangchengdong@lixiang.com
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: OS Components OS Components issues Size: M The size of the change in this PR is medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants