RUNQUEUE(9)

πŸ’– RUNQUEUE(9) πŸ’–

okay bestie, welcome to the run queue page β€” this is from the Kernel Developer's Manual, section 9 (that's the kernel dev girly section, not the "how do I use ls" section, we're in the deep end and it's honestly iconic) ✨


🌸 NAME 🌸

choosethread, procrunnable, remrunqueue, setrunqueue β€” manage the queue of runnable processes

no cap, that's the whole vibe: these four functions are the group chat admins of "which process gets the CPU next" πŸ’…


πŸŽ€ SYNOPSIS πŸŽ€

#include <sys/param.h>
#include <sys/proc.h>

extern struct rq itqueues[];
extern struct rq rtqueues[];
extern struct rq queues[];
extern struct rq idqueues[];

struct thread *
choosethread(void);

int
procrunnable(void);

void
remrunqueue(struct thread *td);

void
setrunqueue(struct thread *td);

✨ DESCRIPTION ✨

so the run queue? it's literally four priority queues holding it down together 🫢

  • itqueues β€” for interrupt threads
  • rtqueues β€” for realtime priority processes
  • queues β€” for time sharing processes
  • idqueues β€” for idle priority processes

each priority queue is an array of NQS queue header structures. every one of those queue headers points at a list of runnable processes that all share the same priority β€” like, same energy, same line, periodt. each queue also has a single word holding a bit mask that flags which queues are non-empty, so the kernel can pick a process fast instead of doom-scrolling the whole array. those bit masks are named itqueuebits, rtqueuebits, queuebits, and idqueuebits πŸ’«

the run queues are protected by the sched_lock mutex. respect the lock bestie, she is not decorative 😭

πŸ’œ procrunnable()

procrunnable() returns zero if there are no runnable processes other than the idle process. if there's at least one runnable process that isn't the idle process, it returns a non-zero value. πŸ¦‹

ngl the cute part: the sched_lock mutex does not need to be held when you call this function. but there's a small race window πŸ™ˆ β€” one CPU might drop a process onto the run queue at a moment when there are currently no other runnable processes, while another CPU is in the middle of calling this function. in that case the second CPU just travels through the idle loop one additional time before it notices there's a runnable process. it works out because idle CPUs are not halted in SMP systems.

and if idle CPUs are halted in SMP systems? then this race condition might have more serious repercussions in the losing case, and procrunnable() may have to require that the sched_lock mutex be acquired. πŸ’€

πŸ’– choosethread()

choosethread() returns the highest priority runnable thread. if there are no runnable threads at all, then the idle thread is returned β€” somebody's gotta be the main character, even when nobody's around 😌

this function is called by cpu_switch() and cpu_throw() to figure out which thread to switch to.

choosethread() must be called with the sched_lock mutex held. not optional, not "maybe later", held. πŸ”₯

🌈 setrunqueue()

setrunqueue() adds the thread td to the tail of the appropriate queue in the proper priority queue. queue etiquette: you go to the back, no cutting πŸŽ€

the thread must be runnable β€” meaning p_stat must be set to SRUN.

this function must be called with the sched_lock mutex held.

πŸ“ remrunqueue()

remrunqueue() removes thread td from its run queue. bye bestie, off you go ✨

if td is not on a run queue, then the kernel will panic(9). yeah. that kind of panic. so make sure she's actually in the queue before you try to pull her out 😭 this function must be called with the sched_lock mutex held.

πŸ‘‘ SEE ALSO πŸ‘‘


and that's the page, bestie!! this one came from the Debian crew, dated August 15, 2010, and it lives as RUNQUEUE(9) in the Kernel Developer's Manual. go hold that sched_lock, ily, mwah πŸ’–βœ¨

πŸ“¦ where this page comes from