-
Notifications
You must be signed in to change notification settings - Fork 1.4k
sched/sched: add nxsched_wakeup(), introduce TSTATE_SLEEPING and improve nxsched_ticksleep() #17222
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
|
I think this needs to be tested with more than just CI. It is a code change that needs runtime testing, not just building. Also, why would we want to wake up a sleeping task before its timeout? Maybe I'm unfamiliar with the semantics of sleeping, but isn't it a requirement that the caller is never woken up prior to the timeout? Only on or after? |
Sleep and wakeup sometimes should be in pair in terms of syncronization For example task1 can not move on because some condition is not met and choose to sleep for a while in the simplest case, but before timeout task2 which has lower priority than task1 met the condition, then it can wakeup task1 to let task1 preempt it sleep/wakeup is simpler and lighter than mutex, semaphore or event in this case |
I will add test it and put the results in this PR later |
But this isn't what sleeping is for? If you want to wait for a condition, you block on a semaphore/mutex, not sleep (unless it's some hardware polling condition that requires sleeping). I personally don't support the addition of the wakeup function since now all the |
I see now that even the previous implementation of |
HI @linguini1 I used this sleep/wakeup pair to improve event implementation in #17223 |
c24f03d to
aae81a3
Compare
| TSTATE_TASK_INACTIVE, /* BLOCKED - Initialized but not yet activated */ | ||
| TSTATE_SLEEPING, /* BLOCKED - Waiting for wakeup or timeout */ | ||
| TSTATE_WAIT_SEM, /* BLOCKED - Waiting for a semaphore */ | ||
| TSTATE_WAIT_SIG, /* BLOCKED - Waiting for a signal */ |
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.
Reusing the signal list is actually a tricky implementation.
- It doesn't add any additional code size or new system state.
- Threads already sleeping via a signal are not affected, as kernel api won't enter cancellation points.
- Timeouts will call the corresponding timeout function, without any side effects.
But I don't object to adding new status.
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.
Yes, but do you think a separate list can save the api time for signal or sleep operations?
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.
- Sleep/signal is a niche use case. Application design should prioritize event triggering over timeouts.
- This change will maintain the same performance as before, as both use signal lists.
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.
restored the implementation using signal list
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.
You may have missed my comment. I'm not against adding a new queue, but you restored, just stick with the current base.
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 don't think call stack is enough in this case: the running taskB want to know the reason why taskA is blocked, even though this case is hardly needed in real world.
Anyway I agree that users may just care whether the task is running or waiting, but I think kernel need to separate which object the task is waiting on so the kernel can do things differently according to this, please check the code below, I think this is the main reason nuttx now have different wait state : TSTATE_WAIT_SEM/TSTATE_WAIT_SIG/TSTATE_WAIT_MQNOTEMPTY/TSTATE_WAIT_MQNOTFULL:
BTW: I have planed to update the code below for the new task state: TSTATE_SLEEPING
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 don't think call stack is enough in this case: the running taskB want to know the reason why taskA is blocked, even though this case is hardly needed in real world.
The backtrace will show you whether the thread is blocking in xxx_sleep or sig_xxx.
Anyway I agree that users may just care whether the task is running or waiting, but I think kernel need to separate which object the task is waiting on so the kernel can do things differently according to this,
Another problem is that each wait state has an entry in g_tasklisttable, but it's strange that the scheduler never modify TSTATE_SLEEPING list.
please check the code below, I think this is the main reason nuttx now have different wait state (I have planed to update the code below for the new task state: TSTATE_SLEEPING ): TSTATE_WAIT_SEM/TSTATE_WAIT_SIG/TSTATE_WAIT_MQNOTEMPTY/TSTATE_WAIT_MQNOTFULL:
The origin code distinguish the wait state between semaphore, queue, etc..., because the scheduler need handle the wait list in the different way. But, we can reuse the signal wait list because sleep is a special case of wait signal.
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 updated this patch and and chose to #define TSTATE_SLEEPING TSTATE_WAIT_SIG
Do you think this is OK?
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.
looks a good idea
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.
The CI check passed, Do you think this PR can be merged? @xiaoxiang781216 @anchao
In the current scheduler implementation, nxsched_ticksleep()
sets the current task state to TSTATE_WAIT_SIG, which is not
semantically appropriate. A dedicated TSTATE_SLEEPING state
is more suitable for this purpose.
Signed-off-by: Chengdong Wang <wangchengdong@lixiang.com>
Add a new function nxsched_wakeup() to the scheduler, which allows waking up a sleeping task before its timeout. Signed-off-by: Chengdong Wang wangchengdong@lixiang.com
aae81a3 to
8b77e97
Compare
8b77e97 to
4d85777
Compare
Refactor nxsched_timeout() to use nxsched_wakeup() in order to
eliminate code duplication and improve maintainability.
Signed-off-by: Chengdong Wang wangchengdong@lixiang.com
4d85777 to
17edd89
Compare
This PR includes three commits:
commit 1:
In the current scheduler implementation, nxsched_ticksleep()
sets the current task state to TSTATE_WAIT_SIG, which is not
semantically appropriate. A dedicated TSTATE_SLEEPING state
is more suitable for this purpose.
Additionally, list_sleepingtasks() is introduced to replace
list_waitingforsignal() in the nxsched_ticksleep() implementation,
to clearly distinguish tasks sleeping for timeout from those
waiting for signals.
commit 2:
Add a new function nxsched_wakeup() to the scheduler,
which allows waking up a sleeping task before its timeout.
commit 3:
Refactor nxsched_timeout() to use nxsched_wakeup() in order to
eliminate code duplication and improve maintainability
Summary
Improved implementation of nxsched_ticksleep() and introduced new function nxsched_wakeup()
Impact
Improvement of newly added function nxsched_ticksleep() and introduced a new function nxsched_wakeup()
No impact to other nuttx functions
Testing
PR 17204 has already replace all Signal-based sleep implement to Scheduled sleep, So CI will verify this PR's improvement of nxsched_ticksleep() is OK
also,
on the one hand:
sleep related api test were added on sim/nsh, sabre-6quad/smp: nxsched_sleep() / nxsched_usleep() / nxsched_msleep() / nxsched_ticksleep()
on the other hand:
sched/event implementation has been modified to use sleep/wakeup pair, and the ostest including event test cases passed on board a2g-tc397-5v-tft: