Starvation and aging
A thread starves when it is ready to run and the scheduler never picks it. Strict priority invites this: while any higher-priority thread is ready, a lower one does not run, and a busy high level can keep it off the CPU indefinitely. A scheduler that ranks threads protects the low ranks with aging, which raises a thread's priority the longer it waits, or with a periodic boost, which lifts every thread back to the top level now and then. A fair-share scheduler avoids starvation by construction, since every thread with a positive weight receives its share, but the placement of a woken thread can bring it back: a thread placed far behind the others in virtual time runs first until it catches up, and holds the CPU from all of them meanwhile.
The trap is that starvation is usually a bookkeeping bug rather than a property of the policy. A thread that left the run queue and was never put back, a queue that holds a thread twice, and a sorted queue whose order broke all look the same from outside: some thread stops running, and no rule of the policy says it should. When a thread starves under a policy that should not starve anyone, the first thing to check is whether each ready thread is queued exactly once.
In Cosmos, the Stride policy's OnThreadYield raises a thread's Pass to the CPU's GlobalPass when it has fallen behind, so a thread that started early, such as the idle thread, cannot keep ranking ahead of threads created later. Wakeup placement guards the same way, in two steps. A woken thread rejoins at GlobalPass plus Remain, the offset it had when it parked, rather than at the Pass it left with: Remain is frozen at the park, so sleeping longer does not lower it, and a long sleep cannot buy a long run ahead of everyone else. The cap, never more than two Stride1 behind GlobalPass, bounds a Remain that was already far negative when the thread parked, which the yield floor makes rare. The manager keeps the queue-once rule on its side. A wake for a thread already Ready or Running does nothing, and a switch puts the outgoing thread back only if it was still Running, because a second entry in Stride's sorted queue would keep its place while the thread's Pass rises, and PickNext, which only takes the head, would then never reach the threads behind it. A policy that ranks threads brings its own guard: the MLFQ sketch resets every thread to the top level every few ticks. See The Stride policy and Worked sketches.