-
Notifications
You must be signed in to change notification settings - Fork 1.4k
sched/event: Replace semaphore with direct scheduler operations in event implementation to improve performance #17223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
f1bbf2d to
307dcbd
Compare
ff596cb to
fa2e152
Compare
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
fa2e152 to
453e9dc
Compare
2b211e7 to
e3e98e8
Compare
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
e3e98e8 to
d37c771
Compare
| { | ||
| struct list_node list; /* Waiting list of nxevent_wait_t */ | ||
| volatile nxevent_mask_t events; /* Pending Events */ | ||
| spinlock_t lock; /* Spinlock */ |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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:
- 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
- Semaphore object costs more memory
- 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 */ |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
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.
87471dc to
077e0be
Compare
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
077e0be to
3afe62e
Compare

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)