[an error occurred while processing this directive]
HP OpenVMS Systems Documentation |
Porting Applications from HP OpenVMS Alpha to HP OpenVMS Industry Standard 64 for Integrity Servers
Appendix B
|
Product | Suggested Replacement |
---|---|
BASEstar Classic | BASEstar Open |
HP Ada Compiler for OpenVMS Alpha Systems | GNAT Ada for OpenVMS Integrity Servers---from Ada Core Technologies |
Pathworks 32 | Advanced Server |
Many applications support small, private threading packages that switch stacks to perform multiple tasks within the context of a single process. Many of these packages use one or more small routines written in assembly language (Macro-32 on VAX or Macro-64 on Alpha) to manipulate the stack pointers and to cause, in effect, a context switch within a single process. Typically, the ability to stall and restart the tasks is also required. The replaced stack can be in any mode appropriate to the required task.
On I64, switching stacks is much more difficult.The I64 architecture includes two stacks, a memory stack and a register stack engine backing store (commonly called the RSE stack or simply the register stack.) The RSE stack is maintained by hardware and the architecture provides support for asynchronous manipulation of the stack. Also, the I64 architecture includes many specialized hardware registers (called control and application registers) that must be maintained across a context switch. In addition, the IAS assembler is not a supported part of the OpenVMS distribution.
To accommodate these types of applications, OpenVMS offers a set of system routines called KP services. Originally written to support device drivers written in higher-level languages, the KP services have been expanded to work in any mode and at any IPL. While the KP model may not match the needs of all private stack-switching code, HP strongly suggests moving to this model.
KP services are available on both Alpha and I64, allowing for common
code. There are some differences in implementation; however, whenever
possible, options valid on only one architecture are ignored on the
other.
C.1 Overview of KP Services
The KP model is most accurately described as a co-routine model with voluntary stall and resumption. A code stream running in process or system context desires to start another stream (called the KP routine) in the same mode but without disturbing the existing stack context and allowing the KP routine to stall and resume as necessary while maintaining its own distinct context. Resumption of a KP routine can be asynchronous to the original code stream that started the KP routine.
The easiest view of a KP routine is that of a routine that operates on a private stack (or on I64, a pair of stacks.) The routine can be stalled and resumed. To a compiler, the routines to start, stall, and resume simply appear as outbound procedure calls which obey the OpenVMS calling standard. The saving of state and stack switch takes place entirely within the context of the KP routines. When a code stream gives up control, the resumption point is always as if the call that caused transfer of control completed.
The base support includes routines to assist in the allocation of necessary stacks and data structures and routines to start, stall, restart, and terminate a KP routine.
A KP routine can start another KP routine.
The basic KP support routines are:
The routines and required data structures are described in
Section C.2.2.
C.1.1 Terminology
The memory stack is the stack that is pointed to the stack pointer register. The memory stack is the only stack on Alpha systems.
The register stack is the informal name for the register stack engine (RSE) backing store. The I64 architecture includes 96 stacked registers that are used for argument passing between routines and that can be used for local storage within a routine as well. The hardware maintains the stacked register state and flushes registers to the backing store as needed.
A KP routine is a sequence of code that runs on a private stack or stacks. It is started via a call to EXE$KP_START and is terminated by an implicit or explicit call to EXE$KP_END.
A KPB is the data structure that describes the stack or stacks and that maintains state and context information for the KP routine.
A KPB is valid if it has been used to activate a KP routine via EXE$KP_START. EXE$KP_END marks the KPB as invalid. The initial state of a KPB is invalid.
A KPB is active when the KP routine has been started
via EXE$KP_START or resumed via EXE$KP_RESTART. EXE$KP_STALL_GENERAL
and EXE$KP_END mark the KPB as inactive. The initial
state of a KPB is inactive.
C.1.2 Stacks and Data Structures
On I64, three pieces of memory are associated with a KP routine---a memory stack, an RSE stack, and a KPB, which is the data structure that ties them all together. On Alpha, there is no RSE stack and all parameters and fields related to the RSE stack are ignored.
The KPB and stacks each must be allocated from an appropriate region, and at an appropriate mode, protection, and ownership to match the mode in which the KP routine will execute. When porting an existing application, it is expected that the application already allocates an appropriate memory stack. The existing memory stack allocation routine can be adapted to the KP API. As with previous architectures, the memory stack is accessed from the highest address (the base of the stack) to the lowest address.
RSE stacks are typically allocated from 64-bit space because the register stack engine is a new entity with no previous 32-bit dependencies. A number of allocation routines have been supplied that should cover most common application needs. The RSE stack is accessed from the lowest address to the highest address.
Table C-1 offers guidelines for allocation by mode and scope of the application.
Mode-Scope1 | KPB | Memory Stack | Register Stack |
---|---|---|---|
Kernel---System
EXE$KP_ALLOC_KPB 2 |
Nonpaged pool
KW EXE$ALONONPAGED |
S0/S1
KW EXE$KP_ALLOC_MEM_STACK |
S2
KW EXE$KP_ALLOC_RSE_STACK 3 |
Kernel---Process |
Nonpaged pool or P1
KW EXE$ALONONPAGED or EXE$ALOP1PROC |
P1---Permanent
KW $CREATE_REGION/$CRETVA |
P2---Permanent
KW EXE$KP_ALLOC_RSE_STACK_P2 |
Kernel---Image |
P1 KW EXE$ALOP1IMAG |
P1-Nonpermanent
KW $CREATE_REGION/$CRETVA |
P2---Nonpermanent
KW $CREATE_REGION/$CRETVA |
Exec---Process |
P1
EW EXE$ALOP1PROC |
P1---Permanent
EW $CREATE_REGION/$CRETVA |
P2---Permanent
EW EXE$KP_ALLOC_RSE_STACK_P2 |
Exec---Image |
P1
EW EXE$ALOP1IMAG |
P1---Nonpermanent
EW $CREATE_REGION/$CRETVA |
P2---Nonpermanent
EW $CREATE_REGION/$CRETVA |
Super---Process |
P1
SW EXE$ALOP1PROC |
P1---Permanent
SW $CREATE_REGION/$CRETVA |
P2---Permanent
SW EXE$KP_ALLOC_RSE_STACK_P2 |
Super---Image |
P1
SW EXE$ALOP1IMAG |
P1---Nonpermanent
SW $CREATE_REGION/$CRETVA |
P2---Nonpermanent
SW $CREATE_REGION/$CRETVA |
User---Image |
P0
UW Heap/Malloc/LIB$GET_VM |
P0---Nonpermanent
4
UW EXE$KP_ALLOC_MEM_STACK_USER |
P2---Nonpermanent
UW EXE$KP_ALLOC_RSE_STACK_P2 |
The KPB is a data structure that is used to maintain the necessary context between the initiating code stream and the KP routine. The KPB is semitransparent. Some fields are maintained by the application, some by the KP routines and some are shared. The KP routines assume the KPB was zeroed on allocation and, thus that any nonzero field contains legitimate data.
The structure definitions for a KPB are defined by the $KPBDEF macro for Macro-32 and KPBDEF.H for C. The KPB definitions are considered system-internal and thus supplied in LIB.MLB and SYS$LIB_C.TLB. For BLISS, LIB.REQ or LIB.L32/LIB.L64 contain the KPB definitions.
The KPB is a variable-length structure consisting of a number of areas or substructures. Not all areas are required. The areas are:
The base area is required. It contains a standard structure header, the stack sizes and base addresses, flags (including what other areas are present), the memory stack pointer for the nonactive code stream, pointers to the other areas, and additional fields required by the base KP routines.
The scheduling area includes pointers to stall, restart and end handling routines, a fork block and a pointer to an additional fork block. With the exception of the end routine, most are required by high-IPL driver-level code only. Callers of EXE$KP_USER_ALLOC_KPB must supply an end routine to perform necessary cleanup of the allocated memory.
The VEST and spinlock areas are used primarily by the driver code.
The debug area offers limited tracing capability implemented in the driver support routines.
The user parameter area is simply undefined storage allocated
contiguously to the other areas. The application is free to use this
memory for its own needs.
C.1.4 Supplied KPB Allocation Routines
The operating system supplies two standard allocation routines for KPBs with associated stacks. The original kernel-mode, driver level interface has been retained unchanged from Alpha so that device drivers using the KP interface do not require source changes in this area. In addition, a mode-independent routine is available. The mode-independent routine calls application-specified routines to allocate the KPB and each of the stacks. Most new applications and applications porting to the KP API will use the latter routine.
Both the kernel and mode-independent routines initialize the KPB. C
prototypes for all the supplied routines can be found in the head file
EXE_ROUTINES.H.
C.1.5 Kernel Mode Allocation
The format for kernel mode allocation is as follows.
EXE$KP_ALLOCATE_KPB kpb, stack_size, flags, param_size |
C prototype
status = EXE$KP_ALLOCATE_KPB( KPB_PPS kpb, int stack_size, int flags, int param_size) |
For kernel mode use only. This routine has the same prototype as the original Alpha routine.
On I64, RSE stack size = memory stack size.
The stack size is in bytes. |
Parameters
Flag | Description |
---|---|
KP$M_VEST | OpenVMS system KPB. In general, this flag should be set. |
KP$M_SPLOCK | Allocate a spinlock area within the KPB. |
KP$M_DEBUG | Allocate a debug area within the KPB. |
KP$M_DEALLOC_AT_END | KPB should be automatically deallocated when the kernel process routine terminates. |
KP$M_SAVE_FP
(IA64 only) |
Save floating-point context as well as the general registers. Certain operations, such as integer multiplication and division on IA64, can be implemented using floating-point operations. These operations use the minimal floating-point register set, which is by definition not part of the preserved register set. If the application uses only the minimal floating-point register set, this bit need not be set. If the application uses floating-point data, this bit must be set to preserve the correct floating point context across the stack switch. |
KP$M_SET_STACK_LIMITS | Call $SETSTK_64 at every stack switch. Process-scope applications should always set this flag because condition handling requires accurate stack limit values. |
SS$_NORMAL
SS$_INSFMEM
SS$_INSFARG
SS$_INSFRPGS
The syntax for mode-independent allocation is as follows.
EXE$KP_USER_ALLOC_KPB kpb, flags, param_size, *kpb_alloc, mem_stack_bytes, *memstk_alloc, rse_stack_bytes, *rsestk_alloc, *end_rtn |
C prototype
status = EXE$KP_USER_ALLOC_KPB( KPB_PPS kpb, int flags, int param_size, int (*kpb_alloc)(), int mem_stack_bytes, int(*memstk_alloc)(), int rse_stack_bytes, int(*rsestk_alloc)(), void(*end_rtn)()) |
Parameters
Flag | Description |
---|---|
KP$M_VEST | OpenVMS system KPB. In general, this flag should be set. |
KP$M_SPLOCK | Allocate a spinlock area within the KPB. |
KP$M_DEBUG | Allocate a debug area within the KPB. |
KP$M_DEALLOC_AT_END | KPB should be automatically deallocated when the kernel process routine terminates. |
KP$M_SAVE_FP | (I64 only; ignored on Alpha) Save floating-point context as well as the general registers. Certain operations such as integer multiplication and division on I64 systems can be implemented using floating-point operations. These operations use the minimal floating-point register set, which is by definition not part of the preserved register set. If the application uses only the minimal floating-point register set, this bit need not be set. If the application uses floating-point data, this bit must be set to preserve the correct floating-point context across the stack switch. |
KP$M_SET_STACK_LIMITS | Call $SETSTK_64 at every stack switch. Process-scope applications should always set this flag because condition handling requires accurate stack limit values. |
The stack allocation routines have identical APIs for both memory and RSE stack allocation. The routine is called with a 64-bit address of the allocated KPB and an integral number of hardware-specific pages (not pagelets) to allocate.
The syntax for specifying stack allocation routines is as follows:
status = alloc-routine (KPB_PQ kpb, const int stack_pages) |
The allocation routine is expected to allocate page-aligned address space. While not strictly necessary, it is strongly suggested that the stack be protected by no-access guard pages on both ends. HP also recommends that the minimum stack size be at least the value of the SYSGEN parameter KSTACKPAGES (global cell SGN$GL_KSTACKPAG). This allows a certain measure of control of the stack size without necessitating recompilation of the application. Also, stack usage on I64 is significantly different than on previous architectures, and the previously allocated stack size might not be adequate.
The memory stack allocation routine must set the following KPB fields as follows:
The memory stack allocation routine can set the following KPB field as follows:
The RSE stack allocation routine must set the following KPB fields as follows:
The RSE stack allocation routine can set the following KPB field as follows:
Both routines must return status to the calling routine.
Previous | Next | Contents | Index |