-
Notifications
You must be signed in to change notification settings - Fork 1
OQueue/ORPC aware scheduling #165
Copy link
Copy link
Open
Description
Current Feature
OQueues are implemented on top of other scheduling primitives (Waker, WaitQueue, etc). The schedule is not aware of OQueues or ORPC.
Enhancement Description
As OQueues and ORPC permeate through the system, we may want to make the scheduler OQueue/ORPC aware and optimize the scheduling of those patterns.
This would probably involve making new scheduling primitives specifically to support OQueues. This could include placing OQueue related data in the Task structure. It could also include adding new features like hand-off scheduling, to transfer control directly from a producer to a consumer.
Notes
@arthurp placed some notes in an old version of the code:
asterinas/ostd/src/orpc/sync/mod.rs
Lines 34 to 75 in b7c3cb1
| /// To use this, the scheduler will: | |
| /// | |
| /// 1. Lock the task (spinning) and disable preemption. | |
| /// 2. Use `add_task` to register the task to be awoken when the blocker unblocks. | |
| /// 3. Call `should_try` to check if it should actually block. | |
| /// 4. If the task should try: | |
| /// 1. Unregister the task with `remove_task`. | |
| /// 2. Unlock the task into the running state. | |
| /// | |
| /// If the task should not try: | |
| /// 1. Unlock the task into the blocked state. | |
| /// | |
| /// To block on multiple blockers: | |
| /// | |
| /// 1. Lock the task (spinning) and disable preemption. | |
| /// 2. For each blocker: | |
| /// 1. Use `add_task` to register the task to be awoken when the blocker unblocks. | |
| /// 2. Call `should_try` to check if it should actually block. | |
| /// 4. If the task should try: | |
| /// 1. Unregister the task from all blockers registered so far with `remove_task`. | |
| /// 2. Unlock the task into the running state. | |
| /// | |
| /// If the task should not try: | |
| /// 1. Unlock the task into the blocked state. | |
| /// | |
| /// To wake tasks the blocker will iterate the tasks and for each: (The waker must atomically "take" the list, | |
| /// guanteeing that exactly one waker gets the non-empty list.) | |
| /// | |
| /// 1. Lock the task. (Spinning) | |
| /// 2. Unlock the task into the runnable state and place it into the run queue. | |
| /// | |
| /// As written, this does not allow for `wake_one`, only `wake_all`. This is because we have no way to know if a task | |
| /// will actually "try" the action after it is woken. This could fail because the task could have been woken already and | |
| /// already passed the point where it would perform the check. This could happen in an ABA situation as well, where the | |
| /// thread has blocked again, but waiting for a different blocker. | |
| /// | |
| /// These wait semantics also force every blocker to be checked everytime a task is awoken. This is because multiple | |
| /// wakes could have occurred from different blockers. These is no way to distinguish multiple wakes from a single. | |
| /// | |
| /// NOTE: Many requirements here can be relaxed in cases where there is guaranteed to be only one waker thread or | |
| /// similar limitations. This *may* improve performance, but may not. An obvious case would be single sender queues | |
| /// not requiring an atomic take operation on the wait queue. |
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels