User-Level Native Thread Primitives (GThread Library) 03/31/2005 NonStop Enterprise Division User-Level Native Thread Primitives (GThread Library) Hewlett-Packard Company--540065-001 Page 1 of 46
User-Level Native Thread Primitives (GThread Library) 03/31/2005 Table of Contents 1. INTRODUCTION...............................................................................................................................................3 1.1. 1.2. 1.3. 1.4. 1.5. 2. OVERVIEW ....................................................................................................................................................3 BACKGROUND AND DEFINITIONS .................................................
User-Level Native Thread Primitives (GThread Library) 03/31/2005 1. Introduction 1.1. Overview The GThread library is a NonStop operating system facility that provides primitives supporting user-level multithreading on TNS/R and TNS/E systems. It is not a comprehensive threading package, but rather provides the primitives to save and restore thread context, and to create the context for new threads.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 Typically, each thread has a stack at a distinct, static address within the virtual memory space of the process. An alternative approach called "stack swapping" employs only a single stack area timeshared by all active threads; the frame images of waiting stacks are swapped to separate holding spaces. Static stacks have the advantage of much faster context switches, but they are impractical when the architecture restricts total stack space.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 |... In the master protocol, the swap origin must occur beyond the stack frames of those unthreaded procedures that remain on the stack while a thread is running. These frames are marked * in the diagram and may or may not remain while the unthreaded master code is running. Diagram 2 |--- stack root ---|--- unthreaded master ---| |- * -|--- thread 1 ---| |- * -|--- thread 2 ---------| |- * -|... 1.4.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 interface or continuing to use the original interfaces. Existing TNS clients using the GThread library on TNS/E can avoid recompilation if they choose. For TNS/E platforms, the following additions were made to existing interfaces: 1) A set of routines that replace directly accessing the thread control block. These routines abstract the knowledge of the TNS/E stack architecture such that the client can see one virtual ‘stack’ per thread.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 2. Thread Primitives The primitives defined below constitute a facility called "GThread." Procedure and structure identifiers begin with "GTHREAD" or “GTH” (for "Guardian Thread"), in contrast with the "pthread" identifiers specified for POSIX threads, and to avoid conflict with identifiers in existing thread packages. Defines and literals begin "GT".
User-Level Native Thread Primitives (GThread Library) 2.3. 03/31/2005 Thread Structures The basic control structure for a thread is a control block called a GThread_CB. Each thread is identified to the primitive routines by a reference to its GThread_CB; this address is used as a handle. A thread package may expose this handle to its clients, or may use some other identification (such as an index into an array of GThread_CB pointers).
User-Level Native Thread Primitives (GThread Library) 03/31/2005 For TNS or TNS/R threads, many of the following members relate to the single stack. For TNS/E, which must deal with two stack components, they are private; equivalent information can be acquired via the interfaces described in Section 2.9. STRING .EXT StackOrigin designates the stack origin for the thread; it is set by the GTHREAD_INITIATE_ procedure and used by the GTHREAD_SETJMP_ procedure.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 The standard dynamic memory-allocation functions on each platform, such as malloc() and POOL_GETSPACE_(), provide memory blocks suitably aligned for static threads. However, a statically allocated global stack area requires care to achieve proper alignment: The alignment of a static stack area, such as an array or structure, is the largest alignment of its elements.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 GTHREAD_BYTES(TSize,NSize) evaluates to an INT(32) stack length in bytes. This macro might help to deal with stack alignment and length architecture requirements: TNS, TNS/R, and TNS/E stacks differ in terms of stack requirements for the same processing. INT TSize specifies the TNS stack length in 16-bit words; INT(32) NSize specifies the native stack length in bytes; it is rounded up to a multiple of 8 for TNS/R and 16 for TNS/E.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 GT_BAD_CB: The designated CB.GTh_Marker is wrong: the structure is corrupted or GTHREAD_INITIATE_ was not called. GT_BAD_CB_NEXT: MainCB.ThreadNext.GTh_Marker is wrong. GT_BAD_CB_PREV: MainCB.ThreadPrev.GTh_Marker is wrong. GT_BAD_...
User-Level Native Thread Primitives (GThread Library) 03/31/2005 The following defines interpret or set GThread_CB.SwapArea: GTHREAD_STATIC(CB) reports true (nonzero) for a static thread. GTHREAD_SWAPAREA_VALID(CB) reports true for swapped thread with contiguous swap area. GTHREAD_SWAPAREA_INVALIDATE(CB) marks the thread as having discontiguous swap area. GTH_NULL_PROCADDR is the null value for passing to GTHREAD_SETJMP_ or GTHREAD_LONGJMP_ in lieu of the address of a procedure to call.
User-Level Native Thread Primitives (GThread Library) 2.6. 03/31/2005 Setup and Initialization GTHREAD_INITIALIZE_( int32 Version, GThreadCB MainCB ) Description: Initializes the GThread primitives. This includes setting all fields in MainCB to zero, followed by initializing the thread list anchors, setting the stack origin to a special invalid value, storing GTHREAD_VERSION into GTh_Marker, and saving the MainCB address in NonStop operating system process state.
User-Level Native Thread Primitives (GThread Library) 2.7. 03/31/2005 Initiation A program creates a new thread by allocating a GThread_CB and a stack area, and invoking the following procedure.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 Return: int16 Returns zero if the function succeeds. Returns GT_BAD_MAIN_CB, GT_BAD_CB_NEXT, GT_BAD_CB_PREV, GT_BAD_..._ALIGN (four cases), GT_BAD_ARGLEN, GT_BAD_LENGTH, or GT_BAD_SWAPTIONS if an error is detected. Considerations: The ArgStart parameter described above designates a set of discrete argument values, not a string being passed as a single argument.
User-Level Native Thread Primitives (GThread Library) 2.8. 03/31/2005 TNS/E Migration Aid GTH_GET_ESTIMATED_STACK_SIZE_( int32 sizeEstimate ) Description: Provides the caller with a TNS/E adjusted stack size given an estimated TNS/R size. Callable for either static or swapped threads. Input: SizeEstimate - Estimated size in bytes; size provided must be based on a TNS/R implementation. Return: int32 Returns the estimated stack size in bytes. Considerations: Use of this interface is optional.
User-Level Native Thread Primitives (GThread Library) 2.9. 03/31/2005 Access Functions The functions in this and the next two sections interface to attributes of the thread. To the greatest extent possible, these functions mask architectural dependencies. Where a TNS/E program requires this information or action, it must use this interface. Direct access to the CB structure fields remains an option in TNS and TNS/R programs; use of this interface increases portability.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 GTH_STACK_USED_( GThread_CB cb ) Description: Returns the number of bytes of allocated stack space that is currently in use on the user stack. Callable for either static or swapped threads. Replaces accessing the thread control block element StackUsed. Input: cb -The address of the thread control block being checked. Return: int32 Returns the amount of stack space being used in bytes at the point where GTHREAD_SETJMP_ was last called.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 GTH_ STACK_CHECK_ACTIVE_( GThread_CB cb, int32 stack_delta ) Description: Permits a client to determine whether there is a specified amount of stack space available on an active static thread using the current stack pointers. Callable only for a static thread. This replaces accessing the thread control block elements StackSize, StackOrigin, and then performing a check against the current value of the stack pointer (sp).
User-Level Native Thread Primitives (GThread Library) 03/31/2005 GTH_ STACK_CHECK_THREAD_( GThread_CB cb, int32 stack_delta ) Description: Permits a client to determine whether there is a specified amount of stack space available on a static thread using stack pointer information captured on the last call to GTHREAD_SETJMP_ for the specified thread. Callable only for a static thread. This replaces accessing the thread control block elements StackSize and StackUsed.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 GTH_STACK_CHECK_ACTIVE2_( GThread_CB cb, int32 mem_delta, int32 reg_delta ) Description: Permits a client to determine whether there is a specified amount of stack space available on an active static thread using the current stack pointers. Callable only for a static thread. This replaces accessing the thread control block elements StackSize, StackOrigin, and performing a check against the current value of the stack pointer (sp).
User-Level Native Thread Primitives (GThread Library) 03/31/2005 GTH_STACK_CHECK_THREAD2_( GThread_CB cb, int32 mem_delta, int32 reg_delta ) Description: Permits a client to determine whether there is a specified amount of stack space available on a static thread using stack pointer information captured on the last call to GTHREAD_SETJMP_ for the specified thread. Callable only by clients implementing static threading. This replaces accessing the thread control block elements StackSize and StackUsed.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 GTH_STACK_ORIGIN_( GThread_CB cb ) Description: Returns the stack origin used by the thread. Callable for either static or swapped threads. This replaces accessing the thread control block element StackOrigin. Input: cb - The address of the thread control block. Return: void * The thread’s stack origin address. Considerations: Provided for completeness. Can be used for debugging or tracing purposes.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 GTH_ THREAD_NEXT_( GThread_CB cb ) Description: Returns the next (younger) thread currently defined in the process. Callable for either static or swapped threads. This replaces accessing the thread control block element ThreadNext. Input: cb - The address of the thread control block. Return: GThread_CB The address of the next thread. Considerations: Provided for completeness.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 2.10. Saving and Restoring Stacks GTH_STACK_SAVE_( GThread_CB cb ) Description: Performs a copy (save) of the current thread’s runtime stack as part of suspending current thread execution (dispatching another thread). Callable only for a swapped thread. This replaces accessing the thread control block elements SwapArea, StackStart, StackUsed, and performing the copy of the stack to the save area from the runtime stack area.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 2.11. Measuring and Checking Stack Usage A simple method clients can use to analyze the stack usage of a given thread is to allocate a very large memory space for the stack and fill that space with a fixed pattern. The thread is then allowed to run (with emphasis on testing all possible code paths) and prior to terminating the thread, the memory space is examined.
User-Level Native Thread Primitives (GThread Library) mem_used – reg_alloc – reg_used – 03/31/2005 Pointer to location for the size of the mem stack, in bytes, used by the thread while running. Pointer to location for the size of the allocated space, in bytes, reserved for the reg stack. On platforms other than TNS/E native, zero is returned. Pointer to location for the size of the reg stack, in bytes, used by the thread while running. On platforms other than TNS/E native, zero is returned.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 Input: cb - The address of the thread control block for the thread being checked. mem_guard – The amount of mem stack space, in bytes, reserved as the guard area. reg_guard - The amount of reg stack space, in bytes, reserved as a guard area. On platforms other than TNS/E native, this argument is ignored.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 2.12. Context Manipulation GTHREAD_SETJMP_( GThread_CB cb, GTH_FUNC SuspendProc ) Description: An augmented implementation of the C setjmp() function. Callable for either static or swapped threads. Input: cb – The address of a thread control block that will receive the current context. On TNS/E, this must be aligned on a 16-byte boundary.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 GTHREAD_LONGJMP_( GThread_CB cb, int32 val, GTH_FUNC Callee ) Description: An augmented implementation of the C longjmp() function. This procedure returns to the site of the previous GTHREAD_SETJMP_ call for the designated thread. Callable for either static or swapped threads. Input: cb – The address of a thread control block containing the target context.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 GTHREAD_CONTEXT_LENGTH( void ) Description: Returns the length of the significant context in a GThread_CB. Input: None. Return: int32 Returns the length of the significant context in a GThread_CB. Considerations: The data at Gthread_Private for this length (in bytes) can be used to checkpoint the thread context.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 2.13. Termination GTHREAD_TERMINATE_( GThread_CB cb ) Description: Terminates the thread and delinks it from the list of threads. Callable for either static or swapped threads. Input: cb - The address of the defunct thread control block, which should be inactive. Return: int16 Returns zero if the termination completed successfully. nonzero occurs if any error is detected; error values are GT_BAD_CB, GT_BAD_CB_NEXT, or GT_BAD_CB_PREV.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 3. Usage The following sections use sketched pTAL/EpTAL examples to illustrate usage of the GThread primitives for several multithreading models. All models declare one GThread_CB structure named MainCB for the original thread. 3.1. Native Static The static model is the simplest to implement. The bare essentials of a simple native-only implementation are sketched. Initialization: IF GTHREAD_INITIALIZE_(GTHREAD_VERSION,MainCB) THEN ...
User-Level Native Thread Primitives (GThread Library) 03/31/2005 IF @NextThread <> @CurThread THEN IF GTHREAD_SETJMP_(CurThread,GTH_NULL_PROCADDR) = 0d THEN BEGIN IF GTH_STACK_CHECK_THREAD2_(CurThread, 0, 0) THEN ..
User-Level Native Thread Primitives (GThread Library) 03/31/2005 Initialization: Thread^Module^Init(...) is the procedure to initialize the thread package. Its actions include initializing GThread: IF GTHREAD_INITIALIZE_(GTHREAD_VERSION,MainCB) THEN ...; -- Version mismatch Thread^Dispatch; -- see following text Setting the swap origin address correctly will allow enough space for the unthreaded (master) code activations (see "Thread Model Variations," Section 1.3).
User-Level Native Thread Primitives (GThread Library) 03/31/2005 Arg[0] := P1; Arg[1] := P2; Arg[3] := P3; IF GTHREAD_INITIATE_ (Thread -- designates GThread_CB ,MainCB -- master CB ,{swap-area address} -- Start ,{swap-area length} -- Length ,GTS_SWAPPED ,@InitialProc -- swapped thread -- proc for thread ,Arg,$LEN(Arg)*$OCCURS(Arg) -- ArgStart,ArgLen ,@Thread^Terminate -- FinalProc ) THEN -- error {link the new thread onto the ready list} Termination: Thread^Terminate(Thread) is the thread te
User-Level Native Thread Primitives (GThread Library) 03/31/2005 Code at the resumption point of the unthreaded code would recognize that the value returned from GTHREAD_SETJMP_ was not 0 or 1, and perform (or schedule) the thread disposition, including a call to GTHREAD_TERMINATE_.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 -- Adjust environment and invoke Thread^SwapIn: GTHREAD_SWAPIN_SETUP_(NextThread,Thread^SwapIn); -- Does not return; Thread^SwapOut LONGJMPs to top of loop. END; Thread^SwapIn(NextThread) readies a thread for execution and activates it: This procedure must be called via GTHREAD_SWAPIN_SETUP_, so its activation record (stack frame) lies deeper than those of the procedures being copied onto the stack(s).
User-Level Native Thread Primitives (GThread Library) 3.4. 03/31/2005 Mixed Models It is possible for the same process to have some threads swapped and some static. This approach is useful if some threads are frequently dispatched and have predictable stack sizes, while other threads are less often dispatched but have unpredictable sizes.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 3.6. TNS/E Usage Changes Specific changes for TNS/E are described in the following sections. 3.6.1. Thread Setup and Initialization The client is responsible for the allocation of the ‘stack space’ associated with the thread’s runtime stacks. The allocated buffer is either used directly as a static stack (static threading), or as a save area for stack contents (swapped threading).
User-Level Native Thread Primitives (GThread Library) 03/31/2005 The GThread primitives apply a ‘default’ ratio when allocating the mem stack and reg stack during thread initialization (GTHREAD_INITIATE_). However, since this ratio may not be optimal for all client implementations, the interface provides clients with the option to change the fraction of allocated stack space devoted to the reg stack.
User-Level Native Thread Primitives (GThread Library) 3.6.3. 03/31/2005 Thread Switching (Context Manipulation) Changes to thread switching are divided into two types; changes associated with switching swapped threads, and changes associated with switching static threads. 3.6.3.1. Changes Associated with Swapped Threads For swapped threads, the TNS or TNS/R native clients must perform the four following steps to switch threads: 1) The context for the current thread must be captured (GTHREAD_SETJMP_).
User-Level Native Thread Primitives (GThread Library) 03/31/2005 where cb is the thread control block of the current thread whose context is being saved or restored. GTH_STACK_SAVE_ copies stack frames into the save area. GTH_STACK_RESTORE_ restores stack frames from the save area.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 towards lower memory addresses, TNS/E introduces a new architecture (two stacks, growing in opposite directions) requiring two guard areas. 2) Clients perform a simple check by retrieving the StackUsed element of the thread control block and validate that it is less than the stack space allocated.
User-Level Native Thread Primitives (GThread Library) 03/31/2005 where stack_delta or mem_delta and reg_delta are set to 0 to mimic the previous method of examining StackUsed to determine if an overflow condition existed at the time GTHREAD_SETJMP_ was last called.