543 lines
21 KiB
C
543 lines
21 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. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
#include "mdef.h"
|
|
|
|
#ifdef VMS
|
|
#include <fab.h> /* needed for dbgbldir_sysops.h */
|
|
#endif
|
|
|
|
#include "gtm_string.h"
|
|
|
|
#include "lv_val.h"
|
|
#include <rtnhdr.h>
|
|
#include "error.h"
|
|
#include "mv_stent.h"
|
|
#include "find_mvstent.h" /* for zintcmd_active */
|
|
#include "gdsroot.h"
|
|
#include "gtm_facility.h"
|
|
#include "fileinfo.h"
|
|
#include "gdsbt.h"
|
|
#include "gdsfhead.h"
|
|
#include "filestruct.h"
|
|
#include "hashtab_int4.h"
|
|
#include "gdskill.h"
|
|
#include "jnl.h"
|
|
#include "gdscc.h"
|
|
#include "buddy_list.h"
|
|
#include "tp.h"
|
|
#include "gvname_info.h"
|
|
#include "op_merge.h"
|
|
#include "zwrite.h"
|
|
#include "zshow.h"
|
|
#include "dpgbldir.h"
|
|
#include "dpgbldir_sysops.h"
|
|
#include "error_trap.h" /* for STACK_ZTRAP_EXPLICIT_NULL macro */
|
|
#include "op.h"
|
|
#include "iotcpdef.h"
|
|
#include "iotcproutine.h"
|
|
#include "gt_timer.h"
|
|
#include "iosocketdef.h"
|
|
#ifdef UNIX
|
|
#include "iormdef.h"
|
|
#include "iottdef.h"
|
|
#endif
|
|
#include "stack_frame.h"
|
|
#include "alias.h"
|
|
#include "tp_timeout.h"
|
|
#ifdef GTM_TRIGGER
|
|
#include "gv_trigger.h"
|
|
#include "gtm_trigger.h"
|
|
#endif
|
|
|
|
GBLREF symval *curr_symval;
|
|
GBLREF boolean_t dollar_truth;
|
|
GBLREF lv_val *active_lv;
|
|
GBLREF gv_key *gv_currkey;
|
|
GBLREF gv_namehead *gv_target;
|
|
GBLREF gd_addr *gd_header;
|
|
GBLREF gd_binding *gd_map;
|
|
GBLREF gd_binding *gd_map_top;
|
|
GBLREF dollar_ecode_type dollar_ecode;
|
|
GBLREF dollar_stack_type dollar_stack;
|
|
GBLREF mval dollar_etrap;
|
|
GBLREF mval dollar_ztrap;
|
|
GBLREF mval dollar_zgbldir;
|
|
GBLREF volatile boolean_t dollar_zininterrupt;
|
|
GBLREF boolean_t ztrap_explicit_null; /* whether $ZTRAP was explicitly set to NULL in this frame */
|
|
GBLREF mstr extnam_str;
|
|
GBLREF stack_frame *frame_pointer, *error_frame;
|
|
GBLREF lv_xnew_var *xnewvar_anchor;
|
|
#ifdef GTM_TRIGGER
|
|
GBLREF mstr *dollar_ztname;
|
|
GBLREF mval *dollar_ztdata;
|
|
GBLREF mval *dollar_ztoldval;
|
|
GBLREF mval *dollar_ztriggerop;
|
|
GBLREF mval *dollar_ztupdate;
|
|
GBLREF mval *dollar_ztvalue;
|
|
GBLREF boolean_t *ztvalue_changed_ptr;
|
|
GBLREF int mumps_status;
|
|
GBLREF boolean_t run_time;
|
|
GBLREF int4 gtm_trigger_depth;
|
|
GBLREF symval *trigr_symval_list;
|
|
# ifdef DEBUG
|
|
GBLREF gv_trigger_t *gtm_trigdsc_last; /* For debugging purposes - parms gtm_trigger called with */
|
|
GBLREF gtm_trigger_parms *gtm_trigprm_last;
|
|
GBLREF ch_ret_type (*ch_at_trigger_init)();
|
|
# endif
|
|
#endif
|
|
GBLREF unsigned char *restart_pc, *restart_ctxt;
|
|
GBLREF mval *alias_retarg;
|
|
GBLREF tcp_library_struct tcp_routines;
|
|
GBLREF int merge_args;
|
|
GBLREF uint4 zwrtacindx;
|
|
GBLREF merge_glvn_ptr mglvnp;
|
|
GBLREF gvzwrite_datablk *gvzwrite_block;
|
|
GBLREF lvzwrite_datablk *lvzwrite_block;
|
|
GBLREF zshow_out *zwr_output;
|
|
GBLREF zwr_hash_table *zwrhtab;
|
|
GBLREF boolean_t tp_timeout_deferred;
|
|
|
|
#define FREEIFALLOC(ADR) if (NULL != (ADR)) free(ADR)
|
|
|
|
void unw_mv_ent(mv_stent *mv_st_ent)
|
|
{
|
|
lv_blk *lp, *lpnext;
|
|
lv_val *lvval_ptr;
|
|
symval *symval_ptr, *sym;
|
|
ht_ent_mname *hte;
|
|
lv_xnew_var *xnewvar, *xnewvarnext;
|
|
d_socket_struct *dsocketptr;
|
|
lvzwrite_datablk *zwrblk, *prevzwrblk;
|
|
zwr_zav_blk *zavb, *zavb_next;
|
|
UNIX_ONLY(d_rm_struct *rm_ptr;)
|
|
socket_interrupt *sockintr;
|
|
socket_struct *socketptr;
|
|
zintcmd_ops zintcmd_command;
|
|
UNIX_ONLY(d_tt_struct *tt_ptr;)
|
|
DBGRFCT_ONLY(mident_fixed vname;)
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
active_lv = (lv_val *)NULL; /* if we get here, subscript set was successful, clear active_lv to avoid cleanup problems */
|
|
switch (mv_st_ent->mv_st_type)
|
|
{
|
|
case MVST_MSAV:
|
|
*mv_st_ent->mv_st_cont.mvs_msav.addr = mv_st_ent->mv_st_cont.mvs_msav.v;
|
|
if (&dollar_etrap == mv_st_ent->mv_st_cont.mvs_msav.addr)
|
|
{
|
|
ztrap_explicit_null = FALSE;
|
|
dollar_ztrap.str.len = 0;
|
|
} else if (&dollar_ztrap == mv_st_ent->mv_st_cont.mvs_msav.addr)
|
|
{
|
|
if (STACK_ZTRAP_EXPLICIT_NULL == dollar_ztrap.str.len)
|
|
{
|
|
dollar_ztrap.str.len = 0;
|
|
ztrap_explicit_null = TRUE;
|
|
} else
|
|
ztrap_explicit_null = FALSE;
|
|
dollar_etrap.str.len = 0;
|
|
if (tp_timeout_deferred UNIX_ONLY( && !dollar_zininterrupt))
|
|
/* A tp timeout was deferred. Now that $ETRAP is no longer in effect and we are not in a
|
|
* job interrupt, the timeout can no longer be deferred and needs to be recognized.
|
|
*/
|
|
tptimeout_set(0);
|
|
} else if (mv_st_ent->mv_st_cont.mvs_msav.addr == &dollar_zgbldir)
|
|
{
|
|
if (0 != dollar_zgbldir.str.len)
|
|
{
|
|
gd_header = zgbldir(&dollar_zgbldir);
|
|
/* update the gd_map */
|
|
SET_GD_MAP;
|
|
} else
|
|
{
|
|
dpzgbini();
|
|
gd_header = NULL;
|
|
}
|
|
if (gv_currkey)
|
|
gv_currkey->base[0] = 0;
|
|
if (gv_target)
|
|
gv_target->clue.end = 0;
|
|
}
|
|
return;
|
|
case MVST_MVAL:
|
|
case MVST_IARR:
|
|
case MVST_TPHOLD:
|
|
case MVST_STORIG:
|
|
return;
|
|
case MVST_LVAL:
|
|
/* Reduce the reference count of this unanchored lv_val (current usage as callin argument
|
|
* holder) and put on free list if no longer in use.
|
|
*/
|
|
lvval_ptr = mv_st_ent->mv_st_cont.mvs_lvval;
|
|
DECR_BASE_REF_NOSYM(lvval_ptr, FALSE);
|
|
return;
|
|
case MVST_STAB:
|
|
if (mv_st_ent->mv_st_cont.mvs_stab)
|
|
{
|
|
assert(mv_st_ent->mv_st_cont.mvs_stab == curr_symval);
|
|
symval_ptr = curr_symval;
|
|
curr_symval = symval_ptr->last_tab;
|
|
DBGRFCT((stderr, "\n\n***** unw_mv_ent-STAB: ** Symtab pop with 0x"lvaddr" replacing 0x"
|
|
lvaddr"\n\n", curr_symval, symval_ptr));
|
|
# ifdef GTM_TRIGGER
|
|
/* If this is a trigger symval, don't fully unwind it but rather put it on the trigr_symval_list
|
|
* so it can be reused without having to be fully recreated again.
|
|
*/
|
|
if (symval_ptr->trigr_symval)
|
|
{ /* Relist it */
|
|
assert(NULL == symval_ptr->xnew_var_list);
|
|
assert(NULL == symval_ptr->xnew_ref_list);
|
|
symval_ptr->last_tab = trigr_symval_list;
|
|
trigr_symval_list = symval_ptr;
|
|
/* Note we do not set SFF_UNW_SYMVAL here because this being a trigger related symbol
|
|
* table, when it unwinds, so has any possible reference to what was using it.
|
|
*/
|
|
return;
|
|
}
|
|
# endif
|
|
if (symval_ptr->alias_activity && ((NULL != symval_ptr->xnew_var_list) || (NULL != alias_retarg)))
|
|
/* Special cleanup for aliases and passed through vars */
|
|
als_check_xnew_var_aliases(symval_ptr, curr_symval);
|
|
else
|
|
{ /* Drop reference counts & requeue any lv_xnew_var blocks we have */
|
|
assert(NULL == symval_ptr->xnew_ref_list); /* Without aliases, no ref list possible */
|
|
for (xnewvar = symval_ptr->xnew_var_list; xnewvar; xnewvar = xnewvarnext)
|
|
{
|
|
hte = lookup_hashtab_mname(&curr_symval->h_symtab, &xnewvar->key);
|
|
lvval_ptr = (lv_val *)hte->value;
|
|
assert(lvval_ptr);
|
|
DECR_CREFCNT(lvval_ptr);
|
|
assert(1 < lvval_ptr->stats.trefcnt);
|
|
DECR_BASE_REF_NOSYM(lvval_ptr, TRUE);
|
|
xnewvarnext = xnewvar->next;
|
|
xnewvar->next = xnewvar_anchor;
|
|
xnewvar_anchor = xnewvar;
|
|
}
|
|
}
|
|
for (lp = symval_ptr->lv_first_block; NULL != lp; lp = lpnext)
|
|
{
|
|
lpnext = lp->next;
|
|
free(lp);
|
|
}
|
|
symval_ptr->lv_first_block = NULL;
|
|
for (lp = symval_ptr->lvtree_first_block; NULL != lp; lp = lpnext)
|
|
{
|
|
lpnext = lp->next;
|
|
free(lp);
|
|
}
|
|
symval_ptr->lvtree_first_block = NULL;
|
|
for (lp = symval_ptr->lvtreenode_first_block; NULL != lp; lp = lpnext)
|
|
{
|
|
lpnext = lp->next;
|
|
free(lp);
|
|
}
|
|
symval_ptr->lvtreenode_first_block = NULL;
|
|
free_hashtab_mname(&symval_ptr->h_symtab);
|
|
free(symval_ptr);
|
|
frame_pointer->flags |= SFF_UNW_SYMVAL;
|
|
}
|
|
return;
|
|
case MVST_NTAB:
|
|
DEBUG_ONLY(hte = lookup_hashtab_mname(&curr_symval->h_symtab, mv_st_ent->mv_st_cont.mvs_ntab.nam_addr));
|
|
assert(hte);
|
|
assert(hte == mv_st_ent->mv_st_cont.mvs_ntab.hte_addr);
|
|
hte = mv_st_ent->mv_st_cont.mvs_ntab.hte_addr;
|
|
lvval_ptr = (lv_val *)hte->value;
|
|
DBGRFCT_ONLY(
|
|
memcpy(vname.c, hte->key.var_name.addr, hte->key.var_name.len);
|
|
vname.c[hte->key.var_name.len] = '\0';
|
|
);
|
|
DBGRFCT((stderr, "unw_mv_ent1: var '%s' hte 0x"lvaddr" being reset from 0x"lvaddr" to 0x"lvaddr"\n",
|
|
&vname.c, hte, hte->value, mv_st_ent->mv_st_cont.mvs_ntab.save_value));
|
|
hte->value = (char *)mv_st_ent->mv_st_cont.mvs_ntab.save_value;
|
|
if (lvval_ptr)
|
|
{
|
|
DECR_BASE_REF_NOSYM(lvval_ptr, FALSE);
|
|
}
|
|
return;
|
|
case MVST_PVAL:
|
|
if (mv_st_ent->mv_st_cont.mvs_pval.mvs_ptab.hte_addr)
|
|
{
|
|
assert(mv_st_ent->mv_st_cont.mvs_pval.mvs_ptab.nam_addr);
|
|
DEBUG_ONLY(hte = lookup_hashtab_mname(&curr_symval->h_symtab,
|
|
mv_st_ent->mv_st_cont.mvs_pval.mvs_ptab.nam_addr));
|
|
assert(hte);
|
|
assert(hte == mv_st_ent->mv_st_cont.mvs_pval.mvs_ptab.hte_addr);
|
|
hte = mv_st_ent->mv_st_cont.mvs_pval.mvs_ptab.hte_addr;
|
|
lvval_ptr = (lv_val *)hte->value; /* lv_val being popped */
|
|
DBGRFCT_ONLY(
|
|
memcpy(vname.c, hte->key.var_name.addr, hte->key.var_name.len);
|
|
vname.c[hte->key.var_name.len] = '\0';
|
|
);
|
|
DBGRFCT((stderr, "unw_mv_ent2: var '%s' hte 0x"lvaddr" being reset from 0x"lvaddr" to 0x"lvaddr"\n",
|
|
&vname.c, hte, hte->value, mv_st_ent->mv_st_cont.mvs_pval.mvs_ptab.save_value));
|
|
hte->value = (char *)mv_st_ent->mv_st_cont.mvs_pval.mvs_ptab.save_value;
|
|
/* At this point lvval_ptr has one of two values:
|
|
* 1 - It has the same value as in mv_st_ent->mv_st_cont.mvs_pval.mvs_val which is the lv_val
|
|
* allocated for use for the duration of this mv_stent (replaced the lv_val saved in
|
|
* our save_value field which was restored just above). This is the normal case when
|
|
* either this var is not aliased or if it was the source of the alias.
|
|
* 2 - Say this was variable "A" and someone did a "SET *A=B". In that case, the hashtable entry
|
|
* would be pointed to "B" and this temporary lv_val would be already returned to the free
|
|
* queue and we no longer need to worry about it. In this case lvval would not be the
|
|
* same address as the temp mval yet the same operations need to be done on it. Note that
|
|
* an lvval_ptr value of NULL is just a special version of this case since the hashtable
|
|
* value would not have changed except for alias processing that freed the original lv_val.
|
|
* So we end up with two possible types of addrs but we handle them exactly the same - namely
|
|
* decrement their reference counts and if they have gone to zero meaning nothing else points to
|
|
* them, then delete them and requeue them.
|
|
* There really isn't an assert we can put here to validate these conditions since in either case
|
|
* our var could have become an alias and been "unaliased" many times over.
|
|
*/
|
|
if (lvval_ptr)
|
|
DECR_BASE_REF_NOSYM(lvval_ptr, FALSE);
|
|
return;
|
|
}
|
|
/* We could use the LV_FREESLOT macro here but we already know which symbol-table we need to use and
|
|
* hence avoid that step by directly invoking the LV_FLIST_ENQUEUE macro instead. We however ensure
|
|
* that the bypass is valid by asserting that the symbol table for the lv is indeed what we think it is.
|
|
*/
|
|
assert(curr_symval == LV_GET_SYMVAL(mv_st_ent->mv_st_cont.mvs_pval.mvs_val));
|
|
LV_FLIST_ENQUEUE(&curr_symval->lv_flist, mv_st_ent->mv_st_cont.mvs_pval.mvs_val);
|
|
return;
|
|
case MVST_NVAL:
|
|
assert(mv_st_ent->mv_st_cont.mvs_nval.mvs_ptab.hte_addr);
|
|
DEBUG_ONLY(hte = lookup_hashtab_mname(&curr_symval->h_symtab, &mv_st_ent->mv_st_cont.mvs_nval.name));
|
|
assert(hte);
|
|
assert(hte == mv_st_ent->mv_st_cont.mvs_nval.mvs_ptab.hte_addr);
|
|
hte = mv_st_ent->mv_st_cont.mvs_nval.mvs_ptab.hte_addr;
|
|
lvval_ptr = (lv_val *)hte->value; /* lv_val being popped */
|
|
DBGRFCT_ONLY(
|
|
memcpy(vname.c, hte->key.var_name.addr, hte->key.var_name.len);
|
|
vname.c[hte->key.var_name.len] = '\0';
|
|
);
|
|
DBGRFCT((stderr, "unw_mv_ent3: var '%s' hte 0x"lvaddr" being reset from 0x"lvaddr" to 0x"lvaddr"\n",
|
|
&vname.c, hte, hte->value, mv_st_ent->mv_st_cont.mvs_nval.mvs_ptab.save_value));
|
|
hte->value = (char *)mv_st_ent->mv_st_cont.mvs_nval.mvs_ptab.save_value;
|
|
/* See comment in handling of MVST_PVAL above for content and treatment of lvval_ptr */
|
|
if (lvval_ptr)
|
|
{
|
|
DECR_BASE_REF_NOSYM(lvval_ptr, FALSE);
|
|
}
|
|
return;
|
|
case MVST_STCK:
|
|
case MVST_STCK_SP:
|
|
assert(mvs_size[MVST_STCK] == mvs_size[MVST_STCK_SP]);
|
|
if (0 < mv_st_ent->mv_st_cont.mvs_stck.mvs_stck_size)
|
|
memcpy(*(mv_st_ent->mv_st_cont.mvs_stck.mvs_stck_addr), (char*)mv_st_ent + mvs_size[MVST_STCK],
|
|
mv_st_ent->mv_st_cont.mvs_stck.mvs_stck_size);
|
|
else
|
|
*(mv_st_ent->mv_st_cont.mvs_stck.mvs_stck_addr) =
|
|
(unsigned char *)mv_st_ent->mv_st_cont.mvs_stck.mvs_stck_val;
|
|
return;
|
|
case MVST_TVAL:
|
|
dollar_truth = (boolean_t)mv_st_ent->mv_st_cont.mvs_tval;
|
|
return;
|
|
case MVST_ZINTDEV:
|
|
/* Since the interrupted device frame is popping off, there is no way that the READ
|
|
* that was interrupted will be resumed (if it already hasn't been). We don't bother
|
|
* to check if it is or isn't. We just reset the device.
|
|
*/
|
|
if (NULL == mv_st_ent->mv_st_cont.mvs_zintdev.io_ptr)
|
|
return; /* already processed */
|
|
switch(mv_st_ent->mv_st_cont.mvs_zintdev.io_ptr->type)
|
|
{
|
|
# ifdef UNIX
|
|
case tt:
|
|
if (NULL != mv_st_ent->mv_st_cont.mvs_zintdev.io_ptr)
|
|
{ /* This mv_stent has not been processed yet */
|
|
tt_ptr = (d_tt_struct *)(mv_st_ent->mv_st_cont.mvs_zintdev.io_ptr->dev_sp);
|
|
tt_ptr->mupintr = FALSE;
|
|
tt_ptr->tt_state_save.who_saved = ttwhichinvalid;
|
|
mv_st_ent->mv_st_cont.mvs_zintdev.buffer_valid = FALSE;
|
|
mv_st_ent->mv_st_cont.mvs_zintdev.io_ptr = NULL;
|
|
}
|
|
return;
|
|
case rm:
|
|
if (NULL != mv_st_ent->mv_st_cont.mvs_zintdev.io_ptr)
|
|
{ /* This mv_stent has not been processed yet */
|
|
rm_ptr = (d_rm_struct *)(mv_st_ent->mv_st_cont.mvs_zintdev.io_ptr->dev_sp);
|
|
assert(rm_ptr->pipe || rm_ptr->fifo);
|
|
rm_ptr->mupintr = FALSE;
|
|
rm_ptr->pipe_save_state.who_saved = pipewhich_invalid;
|
|
mv_st_ent->mv_st_cont.mvs_zintdev.buffer_valid = FALSE;
|
|
mv_st_ent->mv_st_cont.mvs_zintdev.io_ptr = NULL;
|
|
}
|
|
return;
|
|
# endif
|
|
case gtmsocket:
|
|
if (NULL != mv_st_ent->mv_st_cont.mvs_zintdev.io_ptr)
|
|
{ /* This mv_stent has not been processed yet */
|
|
dsocketptr = (d_socket_struct *)(mv_st_ent->mv_st_cont.mvs_zintdev.io_ptr->dev_sp);
|
|
sockintr = &dsocketptr->sock_save_state;
|
|
sockintr->end_time_valid = FALSE;
|
|
dsocketptr->mupintr = FALSE;
|
|
if (sockwhich_connect == sockintr->who_saved)
|
|
{ /* clean up socketptr structure */
|
|
socketptr = (socket_struct *)mv_st_ent->mv_st_cont.mvs_zintdev.socketptr;
|
|
if (socket_connect_inprogress == socketptr->state
|
|
&& (FD_INVALID != socketptr->sd))
|
|
tcp_routines.aa_close(socketptr->sd);
|
|
if (NULL != socketptr->zff.addr)
|
|
free(socketptr->zff.addr);
|
|
if (NULL != socketptr->buffer)
|
|
free(socketptr->buffer);
|
|
iosocket_delimiter((unsigned char *)NULL, 0, socketptr, TRUE);
|
|
free(socketptr);
|
|
}
|
|
sockintr->who_saved = sockwhich_invalid;
|
|
}
|
|
mv_st_ent->mv_st_cont.mvs_zintdev.buffer_valid = FALSE;
|
|
mv_st_ent->mv_st_cont.mvs_zintdev.io_ptr = NULL;
|
|
return;
|
|
default:
|
|
GTMASSERT; /* No other device should be here */
|
|
}
|
|
break;
|
|
case MVST_ZINTCMD:
|
|
zintcmd_command = mv_st_ent->mv_st_cont.mvs_zintcmd.command;
|
|
assert((0 < zintcmd_command) && (ZINTCMD_LAST > zintcmd_command));
|
|
/* restore previous active interrupted command information */
|
|
TAREF1(zintcmd_active, zintcmd_command).restart_pc_last
|
|
= mv_st_ent->mv_st_cont.mvs_zintcmd.restart_pc_prior;
|
|
TAREF1(zintcmd_active, zintcmd_command).restart_ctxt_last
|
|
= mv_st_ent->mv_st_cont.mvs_zintcmd.restart_ctxt_prior;
|
|
TAREF1(zintcmd_active, zintcmd_command).count--;
|
|
assert(0 <= TAREF1(zintcmd_active, zintcmd_command).count);
|
|
return;
|
|
case MVST_ZINTR:
|
|
/* Restore environment to pre-$zinterrupt evocation. Note the first few elements of MVST_ZINTR
|
|
* and MVST_TRIGR are the same, so the processing of those elements is commonized.
|
|
*/
|
|
dollar_zininterrupt = FALSE;
|
|
/* Get rid of old values that may exist */
|
|
if (dollar_ecode.begin)
|
|
free(dollar_ecode.begin);
|
|
if (dollar_ecode.array)
|
|
free(dollar_ecode.array);
|
|
if (dollar_stack.begin)
|
|
free(dollar_stack.begin);
|
|
if (dollar_stack.array)
|
|
free(dollar_stack.array);
|
|
/* Restore the old values from dollar_ecode_ci and dollar_stack_ci */
|
|
DBGEHND((stderr, "unw_mv_ent: Restoring saved error frame 0x"lvaddr" over existing error frame value 0x"
|
|
lvaddr"\n", mv_st_ent->mv_st_cont.mvs_zintr.error_frame_save, error_frame));
|
|
error_frame = mv_st_ent->mv_st_cont.mvs_zintr.error_frame_save;
|
|
memcpy(&dollar_ecode, &mv_st_ent->mv_st_cont.mvs_zintr.dollar_ecode_save, SIZEOF(dollar_ecode));
|
|
memcpy(&dollar_stack, &mv_st_ent->mv_st_cont.mvs_zintr.dollar_stack_save, SIZEOF(dollar_stack));
|
|
/* Fall into MVST_TRIGR */
|
|
case MVST_TRIGR:
|
|
dollar_truth = (boolean_t)mv_st_ent->mv_st_cont.mvs_trigr.saved_dollar_truth;
|
|
op_gvrectarg(&mv_st_ent->mv_st_cont.mvs_trigr.savtarg);
|
|
extnam_str.len = mv_st_ent->mv_st_cont.mvs_trigr.savextref.len;
|
|
if (extnam_str.len)
|
|
memcpy(extnam_str.addr, mv_st_ent->mv_st_cont.mvs_trigr.savextref.addr, extnam_str.len);
|
|
# ifdef GTM_TRIGGER
|
|
if (MVST_TRIGR != mv_st_ent->mv_st_type) /* MVST_ZINTR common handling ends here */
|
|
return;
|
|
ztvalue_changed_ptr = mv_st_ent->mv_st_cont.mvs_trigr.ztvalue_changed_ptr;
|
|
dollar_ztvalue = mv_st_ent->mv_st_cont.mvs_trigr.ztvalue_save;
|
|
dollar_ztname = mv_st_ent->mv_st_cont.mvs_trigr.ztname_save;
|
|
dollar_ztdata = mv_st_ent->mv_st_cont.mvs_trigr.ztdata_save;
|
|
dollar_ztoldval = mv_st_ent->mv_st_cont.mvs_trigr.ztoldval_save;
|
|
dollar_ztriggerop = mv_st_ent->mv_st_cont.mvs_trigr.ztriggerop_save;
|
|
dollar_ztupdate = mv_st_ent->mv_st_cont.mvs_trigr.ztupdate_save;
|
|
mumps_status = mv_st_ent->mv_st_cont.mvs_trigr.mumps_status_save;
|
|
run_time = mv_st_ent->mv_st_cont.mvs_trigr.run_time_save;
|
|
# ifdef DEBUG
|
|
gtm_trigdsc_last = (gv_trigger_t *)mv_st_ent->mv_st_cont.mvs_trigr.gtm_trigdsc_last_save;
|
|
gtm_trigprm_last = (gtm_trigger_parms *)mv_st_ent->mv_st_cont.mvs_trigr.gtm_trigprm_last_save;
|
|
# endif
|
|
assert(gtm_trigger_depth >= mv_st_ent->mv_st_cont.mvs_trigr.gtm_trigger_depth_save);
|
|
gtm_trigger_depth = mv_st_ent->mv_st_cont.mvs_trigr.gtm_trigger_depth_save;
|
|
if (0 == gtm_trigger_depth)
|
|
{ /* Only restore error handling environment if returning out of trigger-world */
|
|
dollar_etrap = mv_st_ent->mv_st_cont.mvs_trigr.dollar_etrap_save;
|
|
dollar_ztrap = mv_st_ent->mv_st_cont.mvs_trigr.dollar_ztrap_save;
|
|
ztrap_explicit_null = mv_st_ent->mv_st_cont.mvs_trigr.ztrap_explicit_null_save;
|
|
}
|
|
CHECKHIGHBOUND(mv_st_ent->mv_st_cont.mvs_trigr.ctxt_save);
|
|
CHECKLOWBOUND(mv_st_ent->mv_st_cont.mvs_trigr.ctxt_save);
|
|
ctxt = mv_st_ent->mv_st_cont.mvs_trigr.ctxt_save;
|
|
/* same assert as in gtm_trigger.c */
|
|
assert(((0 == gtm_trigger_depth)
|
|
&& (((ch_at_trigger_init == ctxt->ch)
|
|
|| ((ch_at_trigger_init == (ctxt - 1)->ch)
|
|
&& ((&gvcst_put_ch == ctxt->ch) || (&gvcst_kill_ch == ctxt->ch))))))
|
|
|| ((0 < gtm_trigger_depth)
|
|
&& (((&mdb_condition_handler == ctxt->ch)
|
|
|| ((&mdb_condition_handler == (ctxt - 1)->ch)
|
|
&& ((&gvcst_put_ch == ctxt->ch) || (&gvcst_kill_ch == ctxt->ch)))))));
|
|
active_ch = ctxt;
|
|
ctxt->ch_active = FALSE;
|
|
if (tp_timeout_deferred && !((0 < dollar_ecode.index) && (ETRAP_IN_EFFECT))
|
|
&& !dollar_zininterrupt)
|
|
{ /* A tp timeout was deferred. Now that $ETRAP is no longer in effect and/or we are no
|
|
* longer in a job interrupt, the timeout can no longer be deferred and needs to be
|
|
* recognized.
|
|
*/
|
|
tp_timeout_deferred = FALSE;
|
|
tptimeout_set(0);
|
|
}
|
|
# endif /* GTM_TRIGGER */
|
|
return;
|
|
case MVST_RSTRTPC:
|
|
restart_pc = mv_st_ent->mv_st_cont.mvs_rstrtpc.restart_pc_save;
|
|
restart_ctxt = mv_st_ent->mv_st_cont.mvs_rstrtpc.restart_ctxt_save;
|
|
return;
|
|
case MVST_MRGZWRSV:
|
|
merge_args = mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_merge_args;
|
|
zwrtacindx = mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_zwrtacindx;
|
|
if (NULL != mglvnp)
|
|
{ /* Release this block and sub-blocks */
|
|
FREEIFALLOC(mglvnp->gblp[0]);
|
|
FREEIFALLOC(mglvnp->gblp[1]);
|
|
free(mglvnp);
|
|
}
|
|
mglvnp = mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_mglvnp;
|
|
if (NULL != lvzwrite_block)
|
|
{
|
|
for (zwrblk = lvzwrite_block; zwrblk; zwrblk = prevzwrblk)
|
|
{
|
|
prevzwrblk = zwrblk->prev;
|
|
FREEIFALLOC(zwrblk->sub);
|
|
free(zwrblk);
|
|
}
|
|
}
|
|
lvzwrite_block = mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_lvzwrite_block;
|
|
if (NULL != gvzwrite_block)
|
|
{
|
|
FREEIFALLOC(gvzwrite_block->sub);
|
|
free(gvzwrite_block);
|
|
}
|
|
gvzwrite_block = mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_gvzwrite_block;
|
|
zwr_output = mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_zwr_output;
|
|
if (NULL != zwrhtab)
|
|
{
|
|
FREEIFALLOC(zwrhtab->h_zwrtab.base);
|
|
FREEIFALLOC(zwrhtab->h_zwrtab.spare_base);
|
|
for (zavb = zwrhtab->first_zwrzavb; zavb; zavb = zavb_next)
|
|
{
|
|
zavb_next = zavb->next;
|
|
free(zavb);
|
|
}
|
|
free(zwrhtab);
|
|
}
|
|
zwrhtab = mv_st_ent->mv_st_cont.mvs_mrgzwrsv.save_zwrhtab;
|
|
return;
|
|
default:
|
|
GTMASSERT;
|
|
break;
|
|
}
|
|
return; /* This should never get executed, added to make compiler happy */
|
|
}
|