The NT kernel is responsible for the creation of process objects for all applications that are run on the system. The kernel is objected orientated, is never paged out of memory and its execution is never interrupted. A process object is the primary thread from which one or more thread objects may originate, and is defined as an executing instance of an application. A thread is a unit of code that can be scheduled by the operating system. In terms of CPU scheduling, the most significant data members a process or thread object contain are its base priority, and CPU affinity. It is possible for either to change. The CPU affinity indicates which of the processors in the system the thread is designated to execute on. Windows NT can support up to eight CPU's, so the CPU affinity of any given thread must be between one and eight, with each CPU being explicitly defined.

Each thread object of the process also has one of six states associated with it at any given time during its life. They are:

  • READY: indicates the thread is ready to be run.
  • STANDBY: indicates it will be the next thread to run on one of its designated CPU(s). Each processor in a multiprocessor system has a standby state affiliated with it.
  • RUNNING: indicates thread execution on a processor. Execution will continue until the thread is
    preempted by a higher priority thread, it terminates, its time quantum ends, or it calls a blocking system call, such as I/O.
  • WAITING: indicates the thread is waiting for some request to be completed.
  • TRANSITION: indicates the thread is waiting for the resources necessary for execution.
  • TERMINATED: indicates the thread has finished execution.

NT's kernel schedules thread objects based on a multi-level feedback queue algorithm. There are 32 priority levels defined (0 - 31) with the higher numbers representing higher priorities. These 32 levels are subdivided into two major classes: the real-time class, which supports soft real time applications (levels 16 - 31), and the variable class (levels 0 - 15). Each priority level contains a queue that is checked by the dispatcher. It starts at the highest and goes to the lowest level. The dispatcher traverses the priority queues searching for any thread that is in its standby state. When one is found, the dispatcher must determine whether there is a CPU available that the thread has an affinity for. If there is, then the thread is allocated that processor. If no CPU is currently available, but the thread has a higher priority than any of the currently running threads, it will preempt the lowest priority thread and begin execution on that CPU. If it is unable to preempt a thread it will be skipped, and the dispatcher will continue its traversal. If no thread can be found to execute, the dispatcher will execute a special thread called the idle thread.

The kernel may give the thread a different priority level than its base priority by virtue of its I/O-CPU burst characteristics. The change in priority is a positive offset of the primary process object's base priority level. A change in a thread's priority level, from that of its primary process base priority, is done to facilitate not only CPU utilization, but also to enhance the response time of the application. A thread's priority is lowered if its time quantum expires, it is not already at its base priority, and its not real time. A thread's priority is raised if it exits a device queue and its not real time. For example, if a thread is not a real time thread, and it exhausts its time quantum, it may be considered a CPU bound thread. Too many CPU bound threads may choke off I/O bound threads, resulting in under-utilization of the system's
devices, and, from the users standpoint, decreased performance of an interactive application (most I/O bound threads are interactive, e.g., keyboard or mouse I/O). To provide a better mix of CPU and I/O bound threads, the kernel may decide to lower a CPU bound thread's priority level. An I/O bound thread's priority level may be increased once it re-enters the ready state from a device queue. An increase or decrease in priority level can be of different degrees depending upon the nature of the thread - for instance, a thread waiting for keyboard or mouse I/O will receive a higher priority boost than one waiting for disk access, because it has a higher degree of interaction with the user.