Linux Process and Thread Concepts
A conceptual map of Linux processes, threading models, LWPs, kernel and user-space threads, coroutines, and fibers.
Linux threading models
Linux has used three threading models over its lifetime:
- LinuxThreads, the earliest model, which implemented only part of the POSIX Threads standard.
- NGPT, or Next Generation POSIX Threads, which has been discontinued.
- NPTL, or Native POSIX Thread Library, which has been used since the 2.6 kernel.
NPTL uses a 1:1 model in which each user thread corresponds to a kernel thread. Many other systems—including Windows, Solaris, NetBSD, FreeBSD, macOS, and iOS—use the same model. It is simpler to implement than N:1 and M:N models.
When the pthread library creates a thread, pthread_create invokes the clone system call. This ultimately creates a lightweight process (LWP) and a kernel thread. Under NPTL’s 1:1 model, one LWP corresponds to one kernel thread. The LWP has its own task_struct process descriptor in kernel space and is an independently schedulable unit.
Processes and threads in Linux
The system does not draw a strict distinction between processes and threads. Both processes and threads are created through the fork system call, with different arguments. A child process, for example, has an independent address space, while threads share an address space. The kernel schedules task instances.
One way to think about a Linux thread is as a process that shares resources with a group of related processes.
LWPs, user-space threads, and kernel threads
An LWP, or lightweight process, is essentially a kernel-supported user thread.
A kernel thread accesses only kernel space. Kernel threads share the same kernel page tables and kernel address space. User threads belonging to different processes, by contrast, have separate address spaces.
In the strict sense, a user-space thread exists entirely in user space. Its creation, synchronization, destruction, and scheduling happen without kernel assistance. This definition overlaps to some extent with the concept of an LWP.
Context switches
When an LWP is preempted, it must save its current registers in user mode, switch into kernel mode, and save the registers of the corresponding kernel thread. Resuming it requires restoring both contexts. This involves at least two stack switches and causes some cache invalidation.
Green threads
Green threads are “threads” scheduled by a runtime library or virtual machine and managed entirely in user space.
Before JDK 1.2, Java used a green-thread model on platforms such as Solaris. Early Linux threading models also fell into this category. Common related implementations are coroutines, including Quasar in Java and Greenlet in Python.
Coroutines
A coroutine is a generalized subroutine for cooperative multitasking. At its core, it is a program-control mechanism. A coroutine can have multiple entry points and can suspend and resume execution at defined locations.
Coroutines fall into two categories:
- Asymmetric coroutines form a caller–callee chain and transfer control through two operations, commonly
resumeandyield. An asymmetric coroutine can be considered subordinate to its caller. - Symmetric coroutines transfer control through a single operation, such as
coroutine.transfer.
Fibers
A fiber can broadly be understood as a stackful coroutine implementation with a scheduler.
What kind of thread does Java create?
Some Java implementations before version 1.2 used green threads. From Java 1.2 onward, on Linux for example, thread creation ultimately calls pthread_create and produces a kernel-level thread. See the implementation details here.