RU/2: Форум. Общение пользователей и разработчиков OS/2 (eCS). : Multithreading (VII)


Список сообщений | Написать новое | Ответить на сообщение | Домой Поиск:
Предыдущее сообщение | Следующее сообщение
From : ???
To : All
Subj : Multithreading (VII)

Thread management of the kernel mode

A thread that is running code in the top half of the OS/2 kernel is in the "kernel mode".
A thread makes the transition from "user mode" to kernel mode during API requests
to the kernel and potentially during interrupt processing.

A thread that enters the kernel has two options: it either completes the operation
and attempts to exit the kernel, or blocks awaiting some resource's avalaibility or event
to complete an operation(e.g. I/O). When running in kernel mode, a thread executes at
priviledge level 0, and is not preemptible.

An interrupt may cause control to transfer temporarily for interrupt service, but
control is always returned to the thread in kernel mode. A thread running in kernel
mode has access to all the memory in the system - all of the process virtual addres
spaces, as well as the kernel's code and data areas. The aggregate of these memory
areas is called the "system virtual space", or "kernel space".

The OS/2 kernel architecture makes further distinctions among user mode, kernel mode,
and the priviledge level architecture. It is possible for a thread to be excecuting at
priviledge level 0 but not to be in kernel mode. A thread officially enters kernel mode
when a special entry point in the dispatcher named EnterKmode is called.

EnterKmode saves the state of the thread and sets a global flag in the kernel named
InDOS. Actually, a thread is not preemtible if it is executing at priviledge level 0 or if
InDOS is set indicating that the thread is in kernel mode. An example of a thread exe-
cuting at priviledge level 0 that is not in kernel mode arises when an interrupt occurs
while a thread is in user mode - the interrupt handling occurs in interrupt mode.

A thread that is in kernel mode returns to whatever mode it was in previously by
calling the dispatcher routine ExitKmode. The only time that a context switch can occur
is when a thread exits kernel mode. This theme is described in another lesson.

The kernel process context

The data structure used by the kernel to track each process in the system is called
the Per-Task Data Area(PTDA). Each PTDA is allocated, when a proces is created,
by a call to DosExecPgm; each PTDA uses fixed memory within the kernel space. This
list shows the major fields of a PTDA:

Parent(parent process) PTDA link
First child(child process) PTDA link
Sibling PTDA link
TCB Chain Head
Thread count
Current thread pointer
Default process priority
Process virtual address space pointer
Module table pointer to the MTE
File system information:
Current/default drive
Current directory
Open file table
Critical section counts
Exception vectors (16-bit)
Signal vectors(16-bit)
Semaphores
Code page information

The PTDA contains the Process Identity(PID) of the process and links to the parent,
sibling, and first child process, a pointer to the virtual address space, a list of open
files handles and semaphores, a pointer to the chain of threads within the process,
and a pointer to the current thread within the process that is running.

Also in the PTDA are the default process priority, signal and exception handling infor-
mation, and a link to the module table entry(MTE) that describes the exucutable file
loaded into the process virtual address space. MTEs are part of the program loader
handling.

When a thread is in kernel mode, the PTDA for the current process is also mapped(
placed in the memory) by a global kernel variable so that kernel routines always have
access to the PTDA of the current process. In the 16-bit system each PTDA is a segment,
and the current PTDA is always mapped by having the SS register loaded with the
selector of the PTDA. In the 32-bit system, each PTDA is a flat memory object accessible
by a 32-bit offset relative to the kernel's virtual address space - the current PTDA is
accessible through a global kernel variable that contains the offset of the current PTDA.

The kernel thread context - The PTDA - TCB handling
***********************************************

The data structure used by the kernel to track each thread in the system is called the
Thread Control Block(TCB). Each TCB is allocated either by a call to DosCreateThread,
or _beginthread(see Multithreading (VI)) when a thread is created, or by a call to
DosExecPgm when the initial thread 1 is created during process creation. Like the PTDAs,
TCBs use fixed memory and reside within the kernel space.

The TCBs for each process are linked in a chain, with the head of the chain in the PTDA.
This list shows the major fields of the TCB:

TCB chain link
Forced action vector
User stack information(32-bit)
TSD link(32-bit)
I/O information
NPX information(e.g. numeric coprocessor)
Thread state
Priority
Scheduler queue links
Processor usage counts
Exception information(32-bit only)
--------------------------------
(TSD portion in 32-bits)
TCB link (32-bit)
Kernel stack

The primary structure in each TCB is the kernel stack, which is used when the thread
is running at priviledge level 0 or in kernel mode. Each thread in the system must have
its own kernel stack for two reasons. First, since a thread may block while in the kernel,
a place is needed for saving the blocked state information, as well the local data already
allocated as the thread made its way to the point where it had to block.

Second, since there are special cases where a a thread voluntarily yields the processor
while in kernel mode, the top half of the kernel must be resuable.

When a thread makes the transition from user mode to kernel mode through a gate,
the 80X86 gate hardware automatically switches from the user stack to the kernel stack.
Therefore, the gated architecture of the 80X86 processor supports a natural, stack-
based implementation of dynamic linking.

The pointer to the kernel stack for the current thread is maintained in the Task State
Segment(TSS), which is accessed by the processor when a priviledge level transition
occur. The kernel stack is used to preserve the stage of the user's context when
EnterKmode is called, and to provide local storage during kernel processing.

Also contained in each TCB is information for controllingh I/O; scheduling information,
such as priorities and processor usage fields; and forced-action flags that indicate
pending actions that the thread must perform when exiting the kernel.

The links in the chain of TCBs within a process are 32-bit offset fields. Since the 32-bit
kernel is written in 32-bit C, the kernel stacks are larger than in the 16-bit version,
since the code is 32-bit granular instead of 16-bit granular, and high-level languages
such as C use the stack for local storage.

Therefore, the 32-bit system divides the TCB into a fixed portion called the TCB and
a swappable portion called the Thread Swappable Data(TSD). The TSDs primarily
contain the kernel stacks, and can be swapped out when a thread is in the blocked
state.


Tue 30 Dec 2003 18:12 Mozilla/4.61 [en] (OS/2; U)




Programmed by Dmitri Maximovich, Dmitry I. Platonoff, Eugen Kuleshov.
25.09.99 (c) 1999, RU/2. All rights reserved.
Rewritten by Dmitry Ban. All rights ignored.