113 lines
6.1 KiB
C
113 lines
6.1 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2010, 2011 Fidelity Information Services, Inc *
|
|
* *
|
|
* This source code contains the intellectual property *
|
|
* of its copyright holder(s), and is made available *
|
|
* under a license. If you do not know the terms of *
|
|
* the license, please stop and do not read further. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
|
|
#ifndef GTM_THREADGBL_included
|
|
#define GTM_THREADGBL_included
|
|
|
|
#ifndef NO_THREADGBL_DEFTYPES
|
|
# include "gtm_threadgbl_deftypes.h" /* Avoided for gtm_threadgbl_deftypes.c which builds this header file */
|
|
#endif
|
|
|
|
/* The following three macros allow access to global variables located in the thread-global array. The ultimate
|
|
* goal of this array is to permit GTM to become thread-safe. That is not yet true but this framework is the first
|
|
* step in taming our global variable use. In the future, these macros will change to their thread-safe counterparts
|
|
* such that we can have different arrays per thread.
|
|
*
|
|
* The macros can be classified as declaration (DCL_THREADGBL_ACCESS), definition (SETUP_THREADGBL_ACCESS), and
|
|
* usage (TADR, TREF, TAREF1, TAREF2, RFPTR, SFPTR, IVFPTR).
|
|
*
|
|
* DCL_THREADGBL_ACCESS - simple job is to declare the local variable used as an anchor to the thread global
|
|
* array. It should be located in the declaration section of an entry point.
|
|
*
|
|
* SETUP_THREAD_GBL_ACCESS - Sets the value of the local variable used as an anchor. Today, this is just a
|
|
* global var de-reference. In the future, it will use thread-logic to access a
|
|
* thread related base var. This should be placed near the top of the executable
|
|
* code for the routine - certainly before the first TREF macro.
|
|
* TADR - Used to obtain the address of the element.
|
|
* TREF - Used to dereference a global var (see notes at TREF macro for usage).
|
|
* TAREF1/TAREF2 - Used to access array elements - TAREF1 for vectors, TAREF2 for 2 subscript access.
|
|
* RFPTR - Used to reference a function pointer in an expression or conditional.
|
|
* SFPTR - Used to set a new value into a function pointer.
|
|
* IVFPTR - Used to invoke a function pointer.
|
|
*/
|
|
|
|
/* Declare local thread global anchor */
|
|
#define DCL_THREADGBL_ACCESS void *lcl_gtm_threadgbl
|
|
|
|
/* Setup the local thread global anchor giving a value (and purpose in life) */
|
|
#define SETUP_THREADGBL_ACCESS lcl_gtm_threadgbl = gtm_threadgbl
|
|
|
|
/* Reference a given global in the thread global array. There are a couple of different ways this macro can be
|
|
* used. Note that its first term is a "de-reference" (aka "*"). As an example, say we have a global name defined
|
|
* as follows:
|
|
*
|
|
* somestruct *gblname;
|
|
*
|
|
* and we wish to access gblname->subfield. If we code "TREF(gblname)->subfield", that would generate
|
|
*
|
|
* *((somestruct **)((char *)lcl_gtm_threadgbl + nnn))->subfield
|
|
*
|
|
* Note that the first dereference covers the entire expression instead of just the TREF expression. This is an incorrect
|
|
* reference that hopefully produces a compiler error instead of a hard-to-find bug. What needs to be coded instead is
|
|
* (TREF(gblname))->subfield which generates:
|
|
*
|
|
* (*((somestruct **)((char *)lcl_gtm_threadgbl + nnn)))->subfield
|
|
*
|
|
* This isolates the dereference to the expression it needs to refer to and produces an expression to correctly access the
|
|
* desired field. However, if the global is not a pointer, but say, a boolean, then you CANNOT surround the TREF macro with
|
|
* parens if the expression is on the left hand side of the "=" operator because that is not a valid LREF expression. So if
|
|
* the field were a boolean, you could modify it as "TREF(somebool) = TRUE;".
|
|
*
|
|
* The general rule of thumb is if the global is a pointer being used to access a subfield, or if the global is a structure
|
|
* itself and you are accessing subfields with a "." operator (e.g. (TREF(fnpca)).fnpcs[i].indx = i;) surround the TREF with ().
|
|
* Otherwise* you can leave it unadorned.
|
|
*
|
|
* Note that function pointers present some odd constraints. You can cast something to a function pointer type but only
|
|
* when you are going to actually invoke it (as the IVFPTR() macro does below). But this means that non-invoking references
|
|
* (or assignments) cannot use casts to make types match. So we need 2 additional macros for reference in an expression (RFPTR)
|
|
* or setting a function pointer (SFPTR) so we can control the necessary aspects of the expressions involved. See
|
|
* $sr_unix/generic_signal_handler.c for uses of most of these macros used with function pointers.
|
|
*/
|
|
#define TREF(name) *((ggt_##name *)((char *)lcl_gtm_threadgbl + ggo_##name))
|
|
|
|
/* For address of item use TADR(name) macro */
|
|
#define TADR(name) ((ggt_##name *)((char *)lcl_gtm_threadgbl + ggo_##name))
|
|
|
|
/* For access to single dimension array (vector), use TAREF1 macro */
|
|
#define TAREF1(name, indx1) (TADR(name))[indx1]
|
|
|
|
/* For access to 2 dimension array, use TAREF2 macro */
|
|
#define TAREF2(name, indx1, indx2) ((ggt_##name *)((char *)lcl_gtm_threadgbl + ggo_##name + /* Base addr of array */ \
|
|
(((indx1) - 1) * SIZEOF(ggt_##name) * ggd_##name)))[indx2] /* Row offset */
|
|
|
|
/* To set a function pointer, use SFPTR(name) macro - Used to copy an address INTO a function pointer */
|
|
#define SFPTR(name, value) *((char **)((char *)lcl_gtm_threadgbl + ggo_##name)) = (char *)(value)
|
|
|
|
/* To reference a function pointer's value, use RFPTR(name) macro. Use only in rvalue RHS expressions. Does not produce
|
|
* an lvalue suitable for LHS usage. See SFPTR() above if function pointer needs a new value.
|
|
*/
|
|
#define RFPTR(name) (ggt_##name (*)gga_##name)(*(char **)((char *)lcl_gtm_threadgbl + ggo_##name))
|
|
|
|
/* To invoke a function pointer, use IVFPTR(name) macro */
|
|
#define IVFPTR(name) ((ggf_##name)(*(char **)((char *)lcl_gtm_threadgbl + ggo_##name)))
|
|
|
|
/* In the main routines for GTM and the utilities that need to initialize the thread global structure all other routines access,
|
|
* this macro should be used in lieu of SETUP_THREADGBL_ACCESS.
|
|
*/
|
|
#define GTM_THREADGBL_INIT \
|
|
{ \
|
|
gtm_threadgbl_init(); \
|
|
SETUP_THREADGBL_ACCESS; \
|
|
}
|
|
|
|
#endif
|