At any instant, a thread is in one of the four basic states described in Table 2.1. In implementations, you may see additional 'states' that distinguish between various reasons for entering the four basic states. Digital UNIX, for example, represents these finer distinctions as 'substates,' of which each state may have several. Whether they're called 'substates' or additional states, 'terminated' might be divided into 'exited' and 'cancelled'; 'blocked' might be broken up into 'blocked on condition variable,' 'blocked on mutex,' 'blocked in read,' and so forth.
State | Meaning |
Ready | The thread is able to run, but is waiting for a processor. It may have just started, or just been unblocked, or preempted by another thread. |
Running | The thread is currently running; on a multiprocessor there may be more than one running thread in the process. |
Blocked | The thread is not able to run because it is waiting for something; for example, it may be waiting for a condition variable, or waiting to lock a mutex, or waiting for an I/O operation to complete. |
Terminated | The thread has terminated by returning from its start function, calling pthread_exit, or having been cancelled and completing all cleanup handlers. It was not detached, and has not yet been joined. Once it is detached or joined, it will be recycled. |
TABLE 2.1
These finer distinctions can be important in debugging and analyzing threaded programs. However, they do not add substantially to the basic understanding of thread scheduling, and we will not deal with them here.
Threads begin in the
2.2.1 Creation
The 'initial thread' of a process is created when the process is created. In a system that fully supports threaded programming, there's probably no way to execute any code without a thread. A thread is likely to be the only software context that includes the hardware state needed to execute code: registers, program counter, stack pointer, and so forth.
Additional threads are created by explicit calls. The primary way to create threads on a Pthreads system is to call pthread_create. Threads may also be created when the process receives a POSIX signal if the process signal notify mechanism is set to SIGEV_THREAD. Your system may provide additional nonstandard mechanisms to create a thread.
FIGURE 2.1
When a new thread is created, its state is
The most important thing to remember about thread creation is that there is no synchronization between the creating thread's return from pthread_create and the scheduling of the new thread. That is, the thread may start before the creating thread returns. The thread may even run to completion and terminate before pthread_create returns. Refer to Section 8.1.1 for more information and warnings about what to expect when you create a thread.
2.2.2 Startup
Once a thread has been created, it will eventually begin executing machine instructions. The initial sequence of instructions will lead to the execution of the
In the initial thread, the thread 'start function' (main) is called from outside your program; for example, many UNIX systems link your program with a file called crt0.o, which initializes the process and then calls your main. This is a minor implementation distinction, but it is important to remember because there are a few ways in which the initial thread is different. For one thing, main is called with different arguments than a thread start function: the program's argument array (argc and argv) instead of a single void* argument. For another thing, when a thread start function returns, the thread terminates but other threads continue to run. When the function main returns in the initial thread, the process will be terminated immediately. If you want to terminate the initial thread while allowing other threads in the process to continue running, call pthread_exit instead of returning from main.
Another important difference to remember is that on most systems, the initial thread runs on the default process stack, which can grow to a substantial size. 'Thread' stacks may be much more limited on some implementations, and the program will fail with a segmentation fault or bus error if a thread overflows its stack.
2.2.3 Running and blocking
Like us, threads usually can't stay awake their entire life. Most threads occasionally go to sleep. A thread can go to sleep because it needs a resource that is not available (it becomes 'blocked') or because the system reassigned the processor on which it was running (it is 'preempted'). A thread spends most of its active life in three states: