Skip to content

CONCEPT Cited by 1 source

M:N scheduler

Definition

An M:N scheduler multiplexes M userspace tasks (green threads, fibers, goroutines, actors) onto N kernel threads where typically M >> N. The userspace scheduler is responsible for dispatch, preemption, and blocking / waking tasks; the kernel sees only the N threads.

Contrast:

  • 1:1 scheduling — each userspace task is backed by a dedicated kernel thread (Java green-thread-less threads, traditional pthreads). Kernel is authoritative for scheduling; userspace has no say.
  • N:1 scheduling — many userspace tasks multiplexed on a single kernel thread (some early coroutine runtimes). Cannot use multiple cores.
  • M:N scheduling — the compromise; lets you spawn cheaply (M in the millions), still uses all available cores (N = core count or similar).

Why the model matters

The userspace scheduler's choices directly shape a language's programming model:

  • Task creation cost — goroutines cost ~2 KiB of stack at spawn, vs. ~1 MiB for a pthread. Enables "spawn a goroutine per request".
  • Blocking semantics — a blocked userspace task does not block a kernel thread; the scheduler can run another task on that thread. Enables synchronous-looking I/O APIs without per-connection OS threads.
  • Preemption granularity — see concepts/async-preemption-go; the userspace scheduler decides whether preemption is cooperative (yield points only) or asynchronous (any instruction boundary).
  • Stack management — userspace schedulers often implement growable stacks; the runtime unwinds and copies stacks at growth points. See concepts/stack-unwinding.

Canonical production instance: Go

Go's runtime implements M:N via three types:

  • g — goroutine; the userspace task.
  • m — kernel thread ("machine").
  • p — physical execution context ("processor"), bound to an m when executing.

Documented in src/runtime/HACKING.md; deep-dive in systems/go-runtime-scheduler.

Other instances

  • Erlang/BEAM — M:N scheduler with preemption by reduction-count (no instruction boundary issues).
  • Tokio (Rust) — M:N with cooperative task scheduling (.await is the yield point; no async preemption).
  • Java Virtual Threads (Project Loom, JDK 21+) — M:N with continuation-based cooperative scheduling.

Seen in

Last updated · 200 distilled / 1,178 read