Display process and thread status information from the Per Task Data Area (PTDA), Thread Control Block (TCB) and Thread Swappable Data (TSD).
Syntax:
────.P ───────────────────────┬──────────┬──────────────────── ├── # ──┤ ├── * ──┤ └── slot ──┘
Parameters:
slot
The following short-hand may be used for the slot number:
_TaskNumber
If no slot number is given then all thread slots are displayed, grouped by process.
Results & Notes:
The .P command locates a thread's TCB from either the thread slot table, the linear address of which is given by global variable:
_papTCBSlots
or by traversing the process tree using TCBpTCBNext (TCB +0x14), TCBpPTDA (TCB +0x08) and ptda_pTCBHead (PTDA + 0x20) fields. Output from the .P command appears in tabular form as follows:
Slot Pid Ppid Csid Ord Sta Pri pTSD pPTDA pTCB Disp SG Name 0001 0001 0000 0000 0001 blk 0100 ffe3a000 ffe3c7d4 ffe3c61c 1eb4 00 *ager 0002 0001 0000 0000 0002 blk 0200 7b7ca000 ffe3c7d4 7b9c8020 1f3c 00 *tsd 0003 0001 0000 0000 0003 blk 0200 7b7cc000 ffe3c7d4 7b9c81d8 1f50 00 *ctxh 0004 0001 0000 0000 0004 blk 081f 7b7ce000 ffe3c7d4 7b9c8390 1f48 00 *kdb 0005 0001 0000 0000 0005 blk 0800 7b7d0000 ffe3c7d4 7b9c8548 1f20 00 *lazyw 0006 0001 0000 0000 0006 blk 0800 7b7d2000 ffe3c7d4 7b9c8700 1f3c 00 *asyncr *0008 0002 0001 0002 0001 blk 0500 7b7d6000 7b9e4020 7b9c8a70 1eb8 01 pmshell 000a# 0002 0001 0002 0002 blk 0800 7b7da000 7b9e4020 7b9c8de0 1ed4 01 pmshell
Each of the fields has the following meaning:
slot
This value may be flagged with:
to the left to signify the current (or last)
dispatched thread.
to the right to signify the Kernel Debugger
or Dump Formatter default thread slot.
Slot may be found in the TCBNumber (TCB + 0x2) field of the TCB
This is normally the same value as the Pid. When the parent process dies any orphaned children are adopted by their grandparent by making Ppid equal to the grandparent's Pid. Each orphan inherits the Csid of its dying parent. This mechanism ensures that orphaned PTDAs are not retained for returning termination information to their parent (via DosWaitChild).
Csid is taken from the Csid (PTDA +0x4be (H/ R :+ 0x4b6 ) )fieldofthePTDA
Ord is taken from the TCBOrdinal (TCB+ 0x0) field of the TCB
Except when a state transition is progress this is the same as the current state of the thread (see Qst field of the .PQ command.)
The following states are possible:
┌────┬────────────────┬────────┬──────────────────────────────┐ │abrv│Sta │TCBState│description │ │ │ │value │ │ ├────┼────────────────┼────────┼──────────────────────────────┤ │--- │STATE_VOID │0 │Uninitialized or Dead thread │ ├────┼────────────────┼────────┼──────────────────────────────┤ │rdy │STATE_READY │1 │Thread ready to run │ ├────┼────────────────┼────────┼──────────────────────────────┤ │blk │STATE_BLOCKED │2 │Blocked on a Block Id │ ├────┼────────────────┼────────┼──────────────────────────────┤ │sus │STATE_SUSPENDED │3 │*** Not in Use *** │ ├────┼────────────────┼────────┼──────────────────────────────┤ │crt │STATE_CRITSEC │4 │Blocked by another CritSec │ │ │ │ │thread (after attempting to │ │ │ │ │run) │ ├────┼────────────────┼────────┼──────────────────────────────┤ │run │STATE_RUNNING │5 │Thread currently running │ ├────┼────────────────┼────────┼──────────────────────────────┤ │bst │STATE_READYBOOST│6 │Ready, but apply an IO boost │ │ │ │ │after swapping in a TSD │ ├────┼────────────────┼────────┼──────────────────────────────┤ │tsd │STATE_TSD │7 │Thread waiting for the TSD │ │ │ │ │daemon to page in the TSD. │ ├────┼────────────────┼────────┼──────────────────────────────┤ │dly │STATE_DELAYED │8 │Delayed TKWakeup (Almost │ │ │ │ │Ready) │ ├────┼────────────────┼────────┼──────────────────────────────┤ │frz │STATE_FROZEN │9 │Frozen Thread via │ │ │ │ │DosSuspendThread, │ │ │ │ │DosCreateThread, DosExecPgm or│ │ │ │ │DosSystemService │ ├────┼────────────────┼────────┼──────────────────────────────┤ │gsk │STATE_GETSTACK │10 │TSD daemon is waiting for the │ │ │ │ │page manager to page in a TSD │ ├────┼────────────────┼────────┼──────────────────────────────┤ │bad │STATE_BADSTACK │11 │TSD failed to page in │ └────┴────────────────┴────────┴──────────────────────────────┘
Notes:
The scheduler manages threads on queues by priority and state. See .PQ command for displaying scheduler queues.
The scheduler uses a finite state machine to manipulate thread queues. TCBQState and TCBState are the state transition drivers. They hold a thread's current and desired state. Except during a state transition current and desired state will be identical.
STATE_RUNNING is set when the next potential runner has been selected. The running thread's context is then switched and various dispatcher flags checked before finally giving control to user code. It is therefore possible for the running state to be set and for the user code not to run.
STATE_READYBOOST is a modified ready state and never becomes the current state, instead a priority boost is applied and the state becomes STATE_READY
STATE_CRTSEC This state applies to non-critical section threads only. It is only set when a critical section thread within the same process has given up the processor, while still in critical section, and another thread in the same process is selected to run. If this thread is thread 1 of the process and there are pending signals to process, the thread's signal handler will be dispatched. When there are no more pending signals or this thread is not thread 1 then STATE_CRITSEC will be set.
STATE_FROZEN is normally only seen when an application uses the DosSuspendThread API or creates a thread (or process) that is initially suspended. DosSystemService is used by the session manage to freeze all threads of a process in one system call.
Many states are transient accordingly the persistent appearance of a particular state might indicate a problem of the following nature:
This is the current priority calculated by the scheduler based upon priority class (TCBPriClass (TCB +0x164)), priority class level (TCBPrilevel (TCB +0x165)) and priority boosts (TCBPriClassMod (TCB +0x166)).
The following priority classes are defined:
┌────────────────────┬─────┬────────────────────┐ │class │value│description │ ├────────────────────┼─────┼────────────────────┤ │CLASS_IDLE_TIME │0x01 │Idle-Time class │ ├────────────────────┼─────┼────────────────────┤ │CLASS_REGULAR │0x02 │Regular class │ ├────────────────────┼─────┼────────────────────┤ │CLASS_TIME_CRITICAL │0x03 │Time-Critical class │ ├────────────────────┼─────┼────────────────────┤ │CLASS_SERVER │0x04 │Client-Server Server│ │ │ │class │ └────────────────────┴─────┴────────────────────┘
The following priority boosts (class modifiers) are defined:
┌──────────────────────────────┬─────┬────────────────────┐ │Boost │Value│Description │ ├──────────────────────────────┼─────┼────────────────────┤ │CLASSMOD_KEYBOARD │0x04 │Keyboard boost │ ├──────────────────────────────┼─────┼────────────────────┤ │CLASSMOD_STARVED │0x08 │Starvation boost │ ├──────────────────────────────┼─────┼────────────────────┤ │CLASSMOD_DEVICE │0x10 │Device I/O Done │ │ │ │Boost │ ├──────────────────────────────┼─────┼────────────────────┤ │CLASSMOD_FOREGROUND │0x20 │Foreground boost │ ├──────────────────────────────┼─────┼────────────────────┤ │CLASSMOD_WINDOW │0x40 │Window Boost │ ├──────────────────────────────┼─────┼────────────────────┤ │CLASSMOD_VDM_INTERRUPT │0x80 │VDM simulated │ │ │ │interrupt boost │ └──────────────────────────────┴─────┴────────────────────┘
Note:
CLASSMOD_KEYBOARD has no effect on CLASS_SERVER
The priority level is a value between 0x0 and 0x1f.
Priority class and modifier values are logically ORed to form an index into the priority class translation table, which is located at global symbol:
_schPriClassTbl
The resulting value is logically ORed with the priority level. The final value is subject to the minimum thread priority (TCBPriorityMin (TCB +016a)).
Priority boosts do not affect the priority of idle and time-critical threads.
Priority level has little or no effect on the priority of boosted regular and server class threads. threads pTSD
Note:
The TSD contains the ring 0 stack for the associated thread. For the current thread this is addressable from selector 30 however the base address of selector 30 is entirely different from TCBpTSD. This is because the two addresses are aliased using two PTEs to pin the same physical frame. This device allows the TSD for be accessed out-of-context by the system, at the same time protecting system code from erroneous stack references.
Note:
The output from .P is ordered by process and child process. TCBs are initially located from the thread table then the chain pointer TCBpTCBNext (TCB +0x14) is used to locate the remaining threads of a process.
Under the Dump Formatter .P will occasionally miss a thread because of the non-sequential manner in which the thread table slots are re-used. To ensure all active threads are displayed use .PU, or .PQ commands.
This value is calculated from TSDKernelESP, therefore requires the TSD to be present. If the TSD is not present then a blank value is given. The TSD may be forced present under the Kernel Debugger by use of the .I command.
The Screen Groups ID is taken from the console locus structure (Cons_Loc +0x2) embedded in the PTDA ((PTDA +0x526 (H/R: +0x51e))).
Except for process 1 and Dos Virtual Machines the name is obtained from the hmte stored in ptda_module (PTDA +0x5a6 (H/R: +0x59e)). If the SMTE is paged in then the name is taken from the file name pointed to by smte_path otherwise it it taken from mte_module and prefixed with an ! point. See .LM command for information on formating loader control blocks.
Process 1 comprises internal threads, that is threads which run in the kernel and are not separately loaded modules. ptda_module is zero for this process so the Dump Formatter and Kernel Debugger translate the Tids for Pid 1 as follows:
┌───┬────────┬──────────────────────────────┐ │Tid│name │description │ ├───┼────────┼──────────────────────────────┤ │1 │*ager │Ager thread used for │ │ │ │compressing the Swap File. │ ├───┼────────┼──────────────────────────────┤ │2 │*tsd │Scheduler's Daemon Thread used│ │ │ │to page in TSDs │ ├───┼────────┼──────────────────────────────┤ │3 │*ctxh │Default Global Context Hook │ │ │ │dispatching thread. │ ├───┼────────┼──────────────────────────────┤ │4 │*kdb │Kernel Debugger Daemon thread │ │ │ │used to process page-in │ │ │ │requests from the .ID command │ ├───┼────────┼──────────────────────────────┤ │5 │*lazyw │File system cache lazy writer │ │ │ │thread. │ ├───┼────────┼──────────────────────────────┤ │6 │*asyncr │File system asynchronous read │ │ │ │ahead thread. │ ├───┼────────┼──────────────────────────────┤ │7 │*sysinit│System initialisation thread. │ ├───┼────────┼──────────────────────────────┤ │8-n│ │Other transient internal │ │ │ │threads associated with system│ │ │ │initialisation have a blank │ │ │ │name. │ └───┴────────┴──────────────────────────────┘
Virtual DOS Machines run the DEM component of OS/2 to provide DOS emulation. DOS programs are loaded by the DEM and not known to the (OS/2) loader. Thus ptda_module is zero and the Kernel Debugger and Dump Formatter use the name *vdm to indicate a VDM. The PSP of the first loaded DOS program in a process may be located from CurrentPDB (PTDA +0x2ea), which contains its segment address. The preceding paragraph contains the DOS arena record, the last 8 bytes of which contains the DOS program name currently executing.