fis-gtm/sr_port/mv_stent.h

303 lines
13 KiB
C

/****************************************************************
* *
* Copyright 2001, 2012 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 MV_STENT_H
#define MV_STENT_H
#ifndef ERROR_TRAP_H
# include "error_trap.h"
#endif
#include "io.h"
#include "lv_val.h"
#include "error.h"
typedef struct
{
ht_ent_mname *hte_addr; /* Hash table entry for name (updated automagically when ht expands) */
struct lv_val_struct *save_value; /* value to restore to hashtab and lst_addr (if supplied) on pop */
DEBUG_ONLY(var_tabent *nam_addr;) /* Name associated with hash table entry for the saved value (for asserts) */
} mvs_ntab_struct;
/* PVAL includes NTAB plus a pointer to the new value created which may or may not be in the hashtable anymore
* by the time this is unstacked but it needs to be cleaned up when the frame pops.
*/
typedef struct
{
lv_val *mvs_val; /* lv_val created to hold new value */
mvs_ntab_struct mvs_ptab; /* Restoration-on-pop info */
} mvs_pval_struct;
/* NVAL is similar to PVAL except when dealing with indirect frames, the name of the var in the indirect frame's l_symtab
* can disappear before we are done with our potential need for it so the extra "name" field in this block allows us to
* cache the reference to it on the stack so it doesn't disappear.
*
* Note routine lvval_gcol() in alias_funcs.c has a dependency that mvs_ptab in PVAL and NVAL are at same offset within
* the structure.
*
* Note the extra "name" field is only carried in DEBUG mode. In non-Debug builds, the NVAL is the same as the PVAL.
*/
typedef struct
{
lv_val *mvs_val; /* lv_val created to hold new value */
mvs_ntab_struct mvs_ptab; /* Restoration-on-pop info */
DEBUG_ONLY(var_tabent name;) /* name.var_name.addr points to whatever the original vartab entry points to */
} mvs_nval_struct;
typedef struct
{
struct io_desc_struct *io_ptr; /* associated device structure */
boolean_t buffer_valid; /* if TRUE, need to update curr_sp_buffer during stp_gcol */
mstr curr_sp_buffer; /* buffer space in stringpool */
void *socketptr; /* void to avoid headers */
} mvs_zintdev_struct;
typedef struct
{ /* Note the top of this structure is a partial version of mvs_trigr_struct so needs to map into the top
* of that structure (below) since cleanups share the same code
*/
boolean_t saved_dollar_truth;
GTM64_ONLY(int4 filler;) /* Alignment */
mval savtarg; /* Current gv_currkey */
mstr savextref; /* Current extended reference name component (if any) */
/* End of common area with mvs_trigr_struct */
stack_frame *error_frame_save; /* Save/restore error_frame over $ZINTERRUPT processor */
dollar_ecode_type dollar_ecode_save; /* Save $ECODE array results */
dollar_stack_type dollar_stack_save; /* Save $STACK(...) array results */
} mvs_zintr_struct;
typedef struct
{ /* Saves "global" entries for a trigger invocation base frame. Note the top entries of this
* structure are the same as mvs_zintr_struct which should be kept in sync with this one as the
* cleanups in unw_mv_ent() share code.
*/
boolean_t saved_dollar_truth;
GTM64_ONLY(int4 filler;) /* Alignment */
mval savtarg; /* Current gv_currkey */
mstr savextref; /* Current extended reference name component (if any) */
/* End of requirement to match mvs_zintr_struct */
# ifdef GTM_TRIGGER
/* This ifdef cuts out the meat of a structure never used on VMS but allows the structure to exist so table
* references (e.g. in mtables) continue to be valid.
*/
boolean_t *ztvalue_changed_ptr; /* pointer to ztvalue_changed for previous trigger level */
mval *ztvalue_save; /* Save it once per trigger level */
mstr *ztname_save;
mval *ztdata_save;
mval *ztoldval_save;
mval *ztriggerop_save;
mval *ztupdate_save;
condition_handler *ctxt_save; /* Where condition handler stack should end up when unwound */
int4 gtm_trigger_depth_save; /* Where our depth guage should end up when unwound */
mval dollar_etrap_save; /* If $gtm_trigger_etrap is specified, save dollar_etrap here */
mval dollar_ztrap_save; /* .. likewise if saving $etrap, save $ztrap too */
boolean_t ztrap_explicit_null_save; /* Just save it rather than figuring out what to restore */
int4 mumps_status_save; /* Each invocation has its own return code */
boolean_t run_time_save; /* MUPIP & GTCM need this flag restored appropriately */
# ifdef DEBUG
void *gtm_trigdsc_last_save; /* types are generic so all includers don't need gv_trigger.h */
void *gtm_trigprm_last_save;
# endif
# endif
} mvs_trigr_struct;
typedef struct
{ /* When MERGE and/or ZWRITE nests (due to trigger or $ZINTRPT firing), the globals used need to be saved to
* prevent collisions and restored when this frame pops.
*/
int save_merge_args;
uint4 save_zwrtacindx;
boolean_t save_in_zwrite;
GTM64_ONLY(int4 filler;)
struct merge_glvn_struct_type *save_mglvnp;
struct gvzwrite_datablk_struct *save_gvzwrite_block;
struct lvzwrite_datablk_struct *save_lvzwrite_block;
struct zshow_out_struct *save_zwr_output;
struct zwr_hash_table_struct *save_zwrhtab;
} mvs_mrgzwrsv_struct;
typedef struct
{
uint4 tphold_tlevel; /* $TLEVEL prior to level we are entering */
# ifdef GTM_TRIGGER
mval ztwormhole_save; /* Saved $ZTWormhole value to be restored on restart if len != -1 */
# endif
} mvs_tphold_struct;
typedef struct
{
unsigned char *restart_pc_save;
unsigned char *restart_ctxt_save;
} mvs_rstrtpc_struct;
/* zintcmd* entries are for timed commands other than I/O which can be
* interrupted. Without an identifying structure such as the device
* structure, we use the restart_pc/ctxt values which must be save
* immediately before the commands opcode via a call to op_restartpc
* in ttt.txt (e.g. HANG) or generated via the m_ routine (e.g. LOCK.)
*/
typedef enum zintcmd_ops_enum
{
ZINTCMD_NOOP = 0,
ZINTCMD_HANG,
ZINTCMD_LOCK, /* also used for ZALLOCATE */
ZINTCMD_LAST
} zintcmd_ops;
typedef struct
{
zintcmd_ops command;
ABS_TIME end_or_remain; /* HANG = end_time, LOCK = remaining */
unsigned char *restart_pc_check; /* of interrupted command */
unsigned char *restart_ctxt_check;
unsigned char *restart_pc_prior; /* from zintcmd_active before */
unsigned char *restart_ctxt_prior; /* this entry was put on stack */
} mvs_zintcmd_struct;
/* Homogenous mv_stent structure containing all types. This structure is never allocated as is but is allocated
* on the M stack using the size for the size defined in mvs_size[] array in mtables.c
* Note that since mvs_size is unsigned char, the sizeof each struct must be under 256 bytes
*/
typedef struct mv_stent_struct
{
unsigned int mv_st_type : 6; /* Max type is 63 */
unsigned int mv_st_next : 26; /* Accomodates distances up to 64MB (stack currently 256KB) */
union
{
mval mvs_mval;
lv_val *mvs_lvval;
struct
{
mval v;
mval *addr;
} mvs_msav;
struct symval_struct *mvs_stab;
struct
{
unsigned short iarr_mvals;
unsigned char *iarr_base;
} mvs_iarr;
struct
{
void **mvs_stck_addr;
void *mvs_stck_val;
int4 mvs_stck_size;
} mvs_stck;
mvs_ntab_struct mvs_ntab;
mvs_zintdev_struct mvs_zintdev;
mvs_pval_struct mvs_pval;
mvs_nval_struct mvs_nval;
mvs_zintr_struct mvs_zintr;
mvs_trigr_struct mvs_trigr;
mvs_tphold_struct mvs_tp_holder;
mvs_rstrtpc_struct mvs_rstrtpc;
mvs_mrgzwrsv_struct mvs_mrgzwrsv;
mvs_zintcmd_struct mvs_zintcmd;
int4 mvs_tval;
int4 mvs_storig;
} mv_st_cont;
} mv_stent;
void unw_mv_ent(mv_stent *mv_st_ent);
void push_stck(void* val, int val_size, void** addr, int mvst_stck_type);
#define MVST_MSAV 0 /* An mval and an address to store it at pop time, most
* often used to save/restore new'd intrinsic variables.
* This is important because the restore addr is fixed,
* and no extra work is required to resolve it.
*/
#define MVST_MVAL 1 /* An mval which will be dropped at pop time */
#define MVST_STAB 2 /* A symbol table */
#define MVST_IARR 3 /* An array of (literal or temp) mval's and mstr's on the stack, due to indirection */
#define MVST_NTAB 4 /* A place to save old name hash table values during parameter passed functions (used for dotted
* parm/alias) */
#define MVST_ZINTCMD 5 /* Non IO timed commands when ZINTR */
#define MVST_PVAL 6 /* A temporary mval for formal parameters or NEW'd variable */
#define MVST_STCK 7 /* save value of stackwarn or save an object of generic C struct */
#define MVST_NVAL 8 /* A temporary mval for indirect news */
#define MVST_TVAL 9 /* Saved value of $T, to be restored upon QUITing */
#define MVST_TPHOLD 10 /* Place holder for MUMPS stack pertaining to TSTART */
#define MVST_ZINTR 11 /* Environmental save for $zinterrupt */
#define MVST_ZINTDEV 12 /* In I/O when ZINTR, mstr input to now protected */
#define MVST_STCK_SP 13 /* same as the MVST_STCK type except that it needs special handling in flush_jmp.c
* (see comment there)
*/
#define MVST_LVAL 14 /* Same as MVST_MVAL except we are pushing an lv_val instead of an mval */
#define MVST_TRIGR 15 /* Used to save the base environment for Trigger execution */
#define MVST_RSTRTPC 16 /* Used to save/restore the restartpc/context across error or jobinterrupt frames */
#define MVST_STORIG 17 /* This is the origin mv_stent placed on the stack during initialization */
#define MVST_MRGZWRSV 18 /* Block used to save merge/zwrite control blocks when one or more of them nest */
#define MVST_LAST 18 /* update this, mvs_size and mvs_save in mtables.c, and switches in unw_mv_ent.c,
* stp_gcol_src.h, and get_ret_targ.c when adding a new MVST type */
/* Variation of ROUND_UP2 macro that doesn't have the checking that generates a GTMASSERT. This is necessary because the
* MV_SIZE macro is used in a static table initializer so cannot have executable (non-constant) code in it
*/
#define ROUND_UP2_NOCHECK(VALUE,MODULUS) (((VALUE) + ((MODULUS) - 1)) & ~((MODULUS) - 1))
#define MV_SIZE(X) \
ROUND_UP2_NOCHECK(((SIZEOF(*mv_chain) - SIZEOF(mv_chain->mv_st_cont) + SIZEOF(mv_chain->mv_st_cont.X))), NATIVE_WSIZE)
#define PUSH_MV_STENT(T) (((msp -= mvs_size[T]) <= stackwarn) ? \
((msp <= stacktop) ? (msp += mvs_size[T]/* fix stack */, rts_error(VARLSTCNT(1) ERR_STACKOFLOW)) : \
rts_error(VARLSTCNT(1) ERR_STACKCRIT)) : \
(((mv_stent *) msp)->mv_st_type = T , \
((mv_stent *) msp)->mv_st_next = (int)((unsigned char *) mv_chain - msp)), \
mv_chain = (mv_stent *) msp)
#define PUSH_MV_STCK(size, st_type) (((msp -= (mvs_size[st_type] + (size))) <= stackwarn) ? \
((msp <= stacktop) ? (msp += (mvs_size[st_type] + (size))/* fix stack */, rts_error(VARLSTCNT(1) ERR_STACKOFLOW)) : \
rts_error(VARLSTCNT(1) ERR_STACKCRIT)) : \
(((mv_stent *) msp)->mv_st_type = st_type, \
((mv_stent *) msp)->mv_st_next = (int)((unsigned char *) mv_chain - msp)), \
mv_chain = (mv_stent *) msp)
#ifdef DEBUG
#define POP_MV_STENT() (assert(msp == (unsigned char *) mv_chain), \
msp += mvs_size[mv_chain->mv_st_type], \
mv_chain = (mv_stent *)((char *) mv_chain + mv_chain->mv_st_next))
#else
#define POP_MV_STENT() (msp += mvs_size[mv_chain->mv_st_type], \
mv_chain = (mv_stent *)((char *) mv_chain + mv_chain->mv_st_next))
#endif
#define IS_PTR_INSIDE_M_STACK(PTR) (((unsigned char *)PTR < (sm_uc_ptr_t)stackbase) && ((unsigned char *)PTR > stacktop))
#define PUSH_MVST_MRGZWRSV \
{ \
PUSH_MV_STENT(MVST_MRGZWRSV); \
mv_st_ent = mv_chain; \
mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_merge_args = merge_args; \
merge_args = 0; \
mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_zwrtacindx = zwrtacindx; \
zwrtacindx = 0; \
mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_in_zwrite = TREF(in_zwrite); \
TREF(in_zwrite) = 0; \
mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_mglvnp = mglvnp; \
mglvnp = NULL; \
mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_lvzwrite_block = lvzwrite_block; \
lvzwrite_block = NULL; \
mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_gvzwrite_block = gvzwrite_block; \
gvzwrite_block = NULL; \
mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_zwr_output = zwr_output; \
zwr_output = NULL; \
mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_zwrhtab = zwrhtab; \
zwrhtab = NULL; \
}
/* Declare those global variables and error messages that are used by the PUSH_MV_STENT and POP_MV_STENT macros */
LITREF unsigned char mvs_size[];
GBLREF unsigned char *stackbase, *stacktop, *stackwarn, *msp;
GBLREF mv_stent *mv_chain;
error_def(ERR_STACKCRIT);
error_def(ERR_STACKOFLOW);
#endif