-
Notifications
You must be signed in to change notification settings - Fork 791
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
Optimize enqueue a bit #3573
base: main
Are you sure you want to change the base?
Optimize enqueue a bit #3573
Conversation
44ccf40
to
07fade3
Compare
The new test cases fail on main, because exited tasks are not pended there:
Pending exited tasks make sure the RUNNING bit (which we now unconditionally set) is cleared, which is needed to not leak a task's storage. This clearing is done by ARM changes are best guess only. |
This is a measurable difference on Xtensa, on ESP32-S3 (atomic CAS). The difference for the ESP32-S2 (critical_section) disappeared after a compiler update, unfortunately 🤔
This PR adds a new
CLAIMED
state. Tasks are firstCLAIMED
, then transition toSPAWNED
. This establishes the invariant that if a task isSPAWNED
, it has a valid executor configured. Going fromCLAIMED
toSPAWNED
clears theCLAIMED
bit.The pull request then uses this invariant to enqueue a task unconditionally upon wake. This saves a few instructions in the common case, but
RUN_QUEUED
state no longer means that a task can definitely be found in a run queue.Edge cases (may be incomplete)
panic
s.CLAIMED
. As the task's executor may be written at any point, we don't enqueue the task. This prevents the task from getting enqueued in two different run queues. Transitioning a task toSPAWNED
will also enqueue it in its new executor.CLAIMED
.run_enqueue
is an atomic operation, so theRUN_QUEUED
bit will be set, and the task will not be claimed. The task will be enqueued in the last executor that ran it, and it will berun_dequeue
'd, then ignored. A subsequent spawn call may claim the task.CLAIMED
" case.RUN_QUEUED
, but not be present in any run queue. This is possible only if the task isCLAIMED
, and transitioning toSPAWNED
will properly enqueue the task.SPAWNED
andCLAIMED
clear, andRUN_QUEUED
set. The executor's next poll will clear this state inrun_enqueue
, and the unspawned task will NOT be polled.Not necessarily a separate edge case, but a concrete concern voiced on Matrix:
This case is covered by "Waking a task that is
CLAIMED
" and "Waking a task just before it becomesCLAIMED
" I believe. Depending on which thread gets to mutating the state first, the task will either not get spawned, or will not be enqueued.The
CLAIMED
state ensures that the task will not be queued until the executor is properly updated.