User-Level Native Thread Primitives (GThread Library) 02/15/2012 NonStop Enterprise Division User-Level Native Thread Primitives (GThread Library) © Copyright 2012 Hewlett-Packard Development Company L.P.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 TABLE OF CONTENTS 1. Introduction .........................................................................................................................................................3 1.1. Overview ......................................................................................................................................................3 1.2. Background and Definitions..........................................................
User-Level Native Thread Primitives (GThread Library) 02/15/2012 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) 02/15/2012 restricts total stack space. An advantage of stack swapping is that all threads share the special attributes of one stack area, including its stack overflow detection mechanism. Stack swapping may also require less total memory, because the swap area needs to hold only the frames of a waiting thread; an active thread might call additional procedures that (without preemption) will exit before the thread waits.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 1.4. User Thread Support The NonStop operating system provides user-level thread support for TNS processes; both TNS and native thread primitives are available, with essentially the same source-level API. The TNS threads serve the following two purposes: • Migration: An existing TNS program or thread library can be converted to use the new primitives and tested in the TNS environment.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 passed into GTHREAD_INITIATE, so that the Gthread library will initiate the user thread using a protected stack. 1.7. Changes to Support 64-bit Addresses Starting from the H06.24 and J06.13 Release Version Updates, the GThread library supports 64-bit OSS processes. The 64-bit OSS process infrastructure is built by using 64-bit addresses and the LP64 data model, wherein the long int and the default pointer types are 64 bits wide.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 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) 02/15/2012 The program must provide a GThread_CB and a stack or swap area for each thread it creates. A thread package can include a GThread_CB as a substruct or overlay of a larger structure associated with its own thread implementation. For simplicity, especially in diagnostic situations, the GThread_CB fields should occur at the front of the structure. The program must provide a GThread_CB for the original thread of the process.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 • STRING .EXT StackStart and INT(32) StackUsed are the starting (lowest) address and byte length of the in-use mem stack area, set by GTHREAD_SETJMP_ for use by the program for swapping or checkpointing. • STRUCT GThread_Private (GThread_Private_Template) is a private structure for GThread (an augmented jump buffer). 2.4. Alignment Considerations The alignment considerations for stack/swap space vary with the platform and the thread model.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 expands to the text of the first parameter in TNS compilations, the second parameter in TNS/R native compilations, and the third parameter in TNS/E native compilations.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 GT_BAD_MAIN_CB: MainCB.GTh_Marker is wrong: the structure is corrupted, or GTHREAD_INITIALIZE_(...,MainCB) was not called. GT_BAD_MAIN_STATE: The MainCB context is not valid: the structure is corrupted, or GTHREAD_SETJMP_(MainCB,...) was not called. 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.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 GTS_DISCONTIGUOUS = 4: The swap area is not contiguous. (TNS and TNS/R only) GTS_STATIC = 8: This a static thread. (GTS_STATIC was previously defined as 0. The 0 value is therefore reserved for backwards compatibility.) GTS_STATIC_RegPerCent(n) = (((n) & 0x7) << 8 ) This define specifies a percentage of Length to be used for the reg stack on TNS/E and is not applicable to protected stacks. See Section 3.6.2 for a discussion of this option.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 2.6. 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) 02/15/2012 additional “resting” space is reserved for the principal stacks. May be called for either static or swapped threads. Input: MainCB - The address of the thread control block that was established by GTHREAD_INITIALIZE_. moreStack Number of bytes by which to increase the “resting” space on the mem stack. moreRegStack - Number of bytes by which to increase the “resting” space on the reg stack.
User-Level Native Thread Primitives (GThread Library) MainCB Start Length Swaptions - 02/15/2012 The address of the main thread control block that designates the initial processing environment, as established by GTHREAD_INITIALIZE. The starting (lowest) address of the stack area provided for the new thread. (For a swapped thread, this is the swap area.) The length allocated for the new thread stack. Characterizes static or swapped threads and thread argument size: GTS_STATIC specifies a static thread.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 local to a procedure (such as the one that invokes GTHREAD_INITIATE_) that will exit immediately. It must not designate anything local to any swapped thread. To avoid architecture dependencies in parameter passing, the initial procedure should have a simple calling sequence (not EXTENSIBLE or VARIABLE) with a fixed number of 32-bit parameters, such as INT(32) values or INT/STRING .EXT pointers.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 The caller of this function should typically link the new thread onto its list of threads ready to run. Subsequent calls to GTHREAD_SWAPIN_SETUP_ (for a swapped thread) and GTHREAD_LONGJMP_ will "resume" the thread at its beginning, which is a call to the InitialProc. 2.8. 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.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 GTH_ALLOCATED_BASE_( GThread_CB cb ) Description: Returns the base (lowest) address of the allocated stack space for the specified thread. May be called for either static or swapped threads. For a swapped thread, the base address returned is the base of the swap area. For a static thread, it is the base of the static stack area.
User-Level Native Thread Primitives (GThread Library) reg_used – 02/15/2012 Pointer to location for the amount of reg stack space being used in bytes at the point where GTHREAD_SETJMP_ was last called. Return: none Considerations: This interface returns stack usage information captured at the last call to GTHREAD_SETJMP_ when the thread was active. It is provided for users of swapped threads who wish to manage swaparea overflow or overflow of the unthreaded (master) code.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 stack_delta - An indication of how much bigger the mem stack could potentially grow, in bytes. Return: int16 Returns zero if there is available stack space.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 an overflow condition existed at the time GTHREAD_SETJMP_ was called to capture stack pointer information. On TNS/E native platforms both the reg and mem stacks are checked. stack_delta is treated as the memory ‘stack delta’ and a reg ‘stack delta’ is implicitly calculated from stack_delta.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 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. May be called only for an unprotected static thread. This replaces accessing the thread control block elements StackSize and StackUsed.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 Return: void * The thread’s stack origin address. Considerations: Provided for completeness. Can be used for debugging or tracing purposes. The origin is the address from which the stack grows. For TNS stacks, which grow toward higher addresses, it is the same as the base of the stack. For TNS/R native stacks, which grow toward lower addresses, it is at the high end of the stack area.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 Input: cb - The address of the thread control block. Return: GThread_CB The address of the previous thread. Considerations: Provided for completeness. 2.10. Saving and Restoring Stacks GTH_STACK_SAVE_( GThread_CB cb ) Description: As part of suspending the current thread execution (dispatching another thread), performs a copy (save) of the current thread’s runtime stack. This may be called only for a swapped thread.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 Return: int16 Returns zero if restore completed successfully. nonzero indicates the restore failed due to a static thread model or an invalidated or discontiguous swap area. Considerations: The routine does not validate that the thread control block supplied belongs to the currently executing thread. If the control block of a suspended thread is provided, corruption of the specified thread’s runtime environment occurs.
User-Level Native Thread Primitives (GThread Library) Input: cb mem_alloc_ – mem_used – reg_alloc – reg_used – 02/15/2012 The address of the thread control block for the thread being analyzed. Pointer to location for the size in bytes of the space allocated for the mem stack. Pointer to location for the size in bytes of the mem stack area used by the thread while running. Pointer to location for the size in bytes of the space allocated for the reg stack.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 GTH_VALIDATE_GUARD_( GThread_CB cb, int32 mem_guard, int32 reg_guard ) Description: Performs a validation of the pattern written during GTHREAD_INITIATE_ in the allocated stack area. The validation is performed starting at the ‘end of the stack area’ allocated for the specified length. The ‘end of the stack area’ is defined as the end of the allocated area based on the direction of stack growth.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 2.12. Context Manipulation GTHREAD_SETJMP_( GThread_CB cb, GTH_FUNC SuspendProc ) Description: An augmented implementation of the C setjmp() function. May be called 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) 02/15/2012 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. May be called for either static or swapped threads. Input: cb – val Callee- The address of a thread control block containing the target context.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 GTHREAD_MAINCONTEXT_CHECK_( GThreadCB MainCB ) Description: Checks for errors in the main context. May be called only for swapped threads. Input: MainCB - The address of the thread control block that was established by GTHREAD_INITIALIZE_. Return: int16 Returns zero if the mem and reg (TNS/E) stacks are each resting within their initial bounds.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 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. Considerations: CB should not designate the current thread or MainCB. Passing one of these control blocks produces undefined behavior; the error is not detected.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 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, unprotected stack implementation are sketched.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 ..; -- stack is in overflow condition @CurThread := @NextThread; GTHREAD_LONGJMP_(CurThread,1d,GTH_NULL_PROCADDR_); END; A master protocol is similar, except the work is split: Suspend current thread (executed in a thread): 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) 02/15/2012 Setting the swap origin address correctly will allow enough space for the unthreaded (master) code activations (see "Thread Model Variations," Section 1.3). The approach used here is based on the following observations and rules: 1. Activation of the Thread^Dispatch procedure (sketched subsequently) defines the tip of the unthreaded stack at rest. 2.
User-Level Native Thread Primitives (GThread Library) ,{swap-area length} -- Length ,GTS_SWAPPED -- swapped thread ,@InitialProc -- proc for thread ,Arg -- ArgStart 02/15/2012 ,$LEN(Arg)*$OCCURS(Arg) -- ArgLen ,@Thread^Terminate -- FinalProc ) THEN -- error {link the new thread onto the ready list} Termination: Thread^Terminate(Thread) is the thread termination procedure passed as FinalProc to GTHREAD_INITIATE_.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 Thread^SwapOut(CTh) swaps out the current thread, puts it to sleep, and awakens the main thread (unthreaded code): IF (GTH_STACK_USED_(CTh) > GTH_ALLOCATED_SIZE_(CTh)) THEN {deallocate current swap area} newLen := GTH_STACK_USED_(CTh) + room to grow; NewAddr := {allocate new swap area with newLen}; GTH_SET_ALLOCATION_(CTh, newAddr, newLen); GTH_STACK_SAVE_(CTh); {handle possible error return} @CurThread := {null value}; -- indicate unthreade
User-Level Native Thread Primitives (GThread Library) 02/15/2012 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) 02/15/2012 Main thread as an unthreaded context. However, a static thread could dispatch another static thread directly, and any other thread can dispatch the Main thread. 3.5. Checkpointing In “passive” checkpointing, the backup process duplicates exactly the memory image of the primary. Passive checkpointing of threads is very difficult, and is not known to occur among GThread clients.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 that can be applied on a TNS/E platform. The estimate may be appropriate for typical clients, but threads exhibiting unusual stack-consumption behavior might need different allocations. Ultimately, client developers must determine the needed thread stack sizes empirically on any platform. Note that this interface estimates the total space for the mem and reg stacks.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 If GT_BAD_SWAPTIONS is returned, the thread control block specified on the call to GTHREAD_INITIATE_ has not been properly set up and therefore cannot be activated until successfully initialized (by calling GTHREAD_INITIATE_ with a valid Swaptions argument). Some minor adjustments to the percentage value specified are performed for alignment purposes.
User-Level Native Thread Primitives (GThread Library) 3.6.3. 02/15/2012 • Use protected stacks allocated with STACK_ALLOCATE_() • Use the 32-bit heap, such as by calling malloc32() • Allocate stacks within one or more 32-bit segments created by the program. For example, use memory allocated through SEGMENT_ALLOCATE_() or shmget () or shmat ().
User-Level Native Thread Primitives (GThread Library) 02/15/2012 The first two interfaces replace the explicit stack copying currently performed by clients for steps 2 and 3, respectively: GTH_STACK_SAVE_( GThread_CB cb ) GTH_STACK_RESTORE_( GThread_CB cb ) 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) 02/15/2012 too short, it can be skipped over (native stack frames often contain “gaps” in which nothing is stored), but a longer guard area requires more time to validate. Furthermore, while the TNS/R architecture involves a single memory stack growing towards lower memory addresses, TNS/E introduces a new architecture (two stacks, growing in opposite directions) requiring two guard areas.
User-Level Native Thread Primitives (GThread Library) 02/15/2012 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.