This section describes the architecture of threads on MPE/iX.
The following terminology is adopted throughout the remainder of this document.
The term process refers to the MPE/iX operating system notion of process.
The term task is defined as a multi-threaded application (depending on
the implementation, a task can consist of a single process or multiple
processes).
Threads on MPE/iX
A multi-threaded task on MPE/iX is implemented with multiple processes
(one per thread). A task's threads are a cooperative processes in
that they share some resources that are normally private to a process.
All threads within a task share the same SR 5 space as the initial
thread (a process created using run or createprocess). The heap and
global variables are shared by all threads, along with loader information
and system information regarding open files and sockets.
All other process resources are private to the thread. Each
thread has its own NM stack, CM stack, pin number, PIB, PIBX, TCB,
PCB, PCBX, process port, and so on. Fields within these data structures
that are shared among threads (such as, file system information)
are kept in a common location.
Process Management and Threads
An initial thread is a process created using run or createprocess
(or fork and exec for POSIX). The threads of a task cannot exist
independently of the initial thread. If the initial thread terminates or is
killed, all of the task's threads are terminated. A secondary thread cannot
be adopted by another task.
Each thread begins execution at an entry point specified at creation time. The
entry point is an MPE/iX procedure with one parameter. This procedure resides
in either the program file or the linked libraries of the task.
When a thread is created, the following attributes can be specified:
Stack size:
NM stack size for the thread
Inherit scheduling:
inherit the scheduling policies of the creating thread
Priority:
priority of the thread
Scheduling policy:
round robin, FIFO,...
Scheduling scope:
priority is global/local
These attributes are required in order to be POSIX compliant. POSIX also
permits each implementation to add its own thread creation attributes.
The following attribute was added for MPE/iX:
Debug:
Enter debug before starting the thread
NOTE: PH capability is required to create a thread.
From a process management point of view, thread creation is just
an abbreviated form of process creation.
All threads are created as siblings. The threads of a task all have the same
father task; namely, the father of the initial thread. If a thread creates a
child using creatprocess, that child is the child of the task, not of the
thread. From the tasks child-point-of-view, its father is the initial thread.
When a thread exits, the children and the threads it created are not terminated.
Threads do not "own" the child processes they create. However, threads may find
it necessary to wait for the termination of the offspring that they created.
Therefore, a thread is permitted to wait for a specific child to terminate and
is permitted to wait on the termination of any child. Refer to the
suspend and activate intrinsics for more explanation.
While threads are implemented with multiple processes, to the end user threads
should appear to coexist within a single process. Process management hides the
MPE/iX implementation of threads from the programmer. The process handling
intrinsics work on a task basis.
Development, Debugging, and Application Execution of Threads
This section discusses the development, debugging, and execution of
applications that use threads on MPE/iX. It should be read before attempting
to create or run an application that uses threads.
Debug has the following features to facilitate debugging in a threaded
environment:
Breakpoints
Commands
Environmental Variable
Breakpoints.
There are three types of breakpoints available when debugging a threaded
program:
Breakpoint Type
Description
Task-Wide
Breakpoints that are recognized by any thread within a task.
Thread-Specific
Breakpoints that are identical to pin-specific breakpoints, but are
thread-private, and are specified using an enhanced syntax.
Stop-All-Threads
Breakpoints with this option, when encountered by a thread within a
threaded task suspend all other threads within the task until a
CONTINUE command is issued.
The syntax for the address and pin parameters to breakpoint commands includes
the specification:
logaddr [:pin|:@]
and the following for threads:
logaddr [:[[init_thread_pin].tin |.@][:@]]
where tin is the thread number returned by pthread_create.
The pin number of the initial thread can be obtained using SHOWPROC.
The syntax [init_thread_pin].tin specifies a thread,
[init_thread_pin].@ specifies a task-wide breakpoint, and :@
following a [init_thread_pin].tin specification
specifies a stop-all-threads breakpoint option.
For example:
Example Breakpoint
Description
B thd_mtx:2e.2
Sets a breakpoint at thd_mtx to be recognized by tin 2 of the
task with initial thread 2e.
B thd_mtx:.2
Sets a breakpoint at thd_mtx to be recognized by tin 2 of the
current task.
B start_thread:2c.@
Sets a task-wide breakpoint at start_thread to be recognized by
all threads within the task with initial thread 2c.
B start_thread:.@
Sets a task-wide breakpoint at start_thread to be recognized by
all threads within the current task.
B HPFOPEN::@
Sets a breakpoint at HPFOPEN for the current pin (tin) with the
stop-all-threads option that is honored if the pin belongs to a threaded
task.
B HPFOPEN:.3:@
Sets a breakpoint at HPFOPEN for tin 3 of the current task, and
the breakpoint has the stop-all-threads option.
B HPFOPEN:.@:@
Sets a task-wide breakpoint at HPFOPEN for the current task,
and the breakpoint has the stop-all-threads option.
Commands
The following commands aid in debugging threaded applications.
Command
Description
TIN[init_thread_pin.]tin
This command causes debug to switch to the environment of the
specified tin. The default init_thread_pin is that of the
current task. Privilege mode is required to switch to any tin in another
task.
SUSPEND
This command suspends all other threads within the task of the tin
being debugged. The suspended threads are not resumed automatically with
the continue command.
ACTIVATE
This command resumes the threads that were suspended by the
SUSPEND command. It should be issued from the same tin that issued
the SUSPEND command.
Environmental Variables
There are two environment variables that simplify debugging applications:
Environment Variable
Description
SS_TERM_KEEPLOCK
When set to TRUE, a pin (tin) being debugged retains the terminal
semaphore while single-stepping. This prevents any other pin (tin), that
is waiting to enter debug, from obtaining the terminal semaphore and
interfering with the debug session.
TERM_KEEPLOCK
Allows a process to retain the terminal semaphore under all conditions
until the process terminates or the variable is reset to FALSE. However,
this variable has the potential to create a deadlock. For example, a
deadlock occurs if the process owning the terminal semaphore waits for
another process that in turn is waiting for the debug terminal
semaphore.
Limitations
The following are know limitations for the debug thread commands:
The break command followed by an abort command hangs the
task if the initial thread is waiting to enter debug (such as,
another thread is currently in debug).
The SUSPEND command has the potential to hang a task if the
user does not issue an ACTIVATE command before doing the
CONTINUE command.
Each thread has its own debug environment. For example, loaded
macros and environmental variables are not shared by threads within
a task, and must be dealt with on an individual basis for each
thread.