1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
/****************************************************************
* *
* Copyright (c) 2012-2015 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* 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"
#include "gtm_string.h"
#include "gtm_stdio.h"
#include "gtmio.h"
#include "error.h"
#include "mv_stent.h"
GBLREF unsigned char *stackbase;
/* Expands the condition handler stack copying old stack to new expanded stack.
*
* Note, chnd_end is always set 2 entries from the actual true top of the stack. Consider what can happen
* if we go to expand the stack but storage is not available. We will fail but when running things down,
* we ALSO need to install handlers. So once process_exiting is set, we are allowed to use the extra handlers.
*/
void condstk_expand(void)
{
condition_handler *new_chnd, *new_chnd_end, *ctxt_ent;
int new_size, old_len, old_size, cnt;
UINTPTR_T delta;
mv_stent *mvs;
# ifdef DEBUG_ERRHND
static int nest_count = 0;
nest_count++;
assert(1 <= nest_count);
/* Prevent reentrance due to condition handler in one of the I/O functions invoked from flush_pio(). */
if (1 == nest_count)
DBGEHND((stderr, "condstk_expand: old: chnd: "lvaddr" chnd_end: "lvaddr" ctxt: "lvaddr" active_ch: "lvaddr
" chnd_incr: %d\n", chnd, chnd_end, ctxt, active_ch, chnd_incr));
if (ctxt >= (chnd_end + (!process_exiting ? 0 : CONDSTK_RESERVE)))
{
# endif
/* Make sure we are allowed to expand */
old_len = INTCAST((char *)chnd_end - (char *)chnd);
old_size = old_len / SIZEOF(condition_handler);
new_size = old_size + chnd_incr + CONDSTK_RESERVE; /* New count of entries in cond handlr stack */
/* Nothing known should allow/require stack to get this large */
assertpro(new_size <= CONDSTK_MAX_STACK);
new_chnd = malloc(new_size * SIZEOF(condition_handler)); /* Allocate new condition handler stack */
new_chnd_end = &new_chnd[new_size];
delta = (UINTPTR_T)((char *)new_chnd - (char *)chnd);
memcpy(new_chnd, chnd, old_len); /* Copy occupied part of old stack */
assert(chnd < chnd_end);
/* Modify the address of save_active_ch so points to relevant entry in new condition handler stack. Note first
* entry back pointer remains unmodified (as NULL).
*/
for (cnt = 2, ctxt_ent = new_chnd + 1; cnt <= old_size; cnt++, ctxt_ent++)
{
assert(ctxt_ent >= new_chnd);
assert(ctxt_ent < new_chnd_end);
# ifdef DEBUG_ERRHND
/* Prevent reentrance due to condition handler in one of the I/O functions invoked from flush_pio(). */
if (1 == nest_count)
DBGEHND((stderr, "condstk_expand: cnt: %d, chptr: 0x"lvaddr" save_active_ch from 0x"lvaddr
" to 0x"lvaddr"\n", cnt, ctxt_ent, ctxt_ent->save_active_ch,
((char *)ctxt_ent->save_active_ch + delta)));
# endif
ctxt_ent->save_active_ch = (condition_handler *)((char *)ctxt_ent->save_active_ch + delta);
assert(ctxt_ent->save_active_ch >= new_chnd);
assert(ctxt_ent->save_active_ch < new_chnd_end);
}
# ifdef GTM_TRIGGER
/* Trigger type mv_stent (MVST_TRIGR) save/restore the value of ctxt so look through the stack to locate those and
* fix them up too.
*/
for (mvs = mv_chain; mvs < (mv_stent *)stackbase; mvs = (mv_stent *)((char *)mvs + mvs->mv_st_next))
{
if (MVST_TRIGR != mvs->mv_st_type)
continue;
# ifdef DEBUG_ERRHND
/* Prevent reentrance due to condition handler in one of the I/O functions invoked from flush_pio(). */
if (1 == nest_count)
DBGEHND((stderr, "condstk_expand: Trigger saved ctxt modified from 0x"lvaddr" to 0x"lvaddr"\n",
mvs->mv_st_cont.mvs_trigr.ctxt_save, (char *)mvs->mv_st_cont.mvs_trigr.ctxt_save + delta));
# endif
/* Have a trigger mv_stent - appropriately modify the saved ctxt value (high water mark for condition handlers */
mvs->mv_st_cont.mvs_trigr.ctxt_save = (condition_handler *)((char *)mvs->mv_st_cont.mvs_trigr.ctxt_save + delta);
}
# endif
/* Condition handler stack now reset - modify globals of record accordingly */
free(chnd); /* Old version no longer needed */
chnd = new_chnd;
chnd_end = new_chnd_end;
if (CONDSTK_MAX_INCR > chnd_incr)
chnd_incr = chnd_incr * 2;
ctxt = (condition_handler *)((char *)ctxt + delta);
active_ch = (condition_handler *)((char *)active_ch + delta);
CHECKLOWBOUND(ctxt);
CHECKHIGHBOUND(ctxt);
CHECKLOWBOUND(active_ch);
CHECKHIGHBOUND(active_ch);
# ifdef DEBUG_ERRHND
}
/* Prevent reentrance due to condition handler in one of the I/O functions invoked from flush_pio(). */
if (1 == nest_count)
DBGEHND((stderr, "condstk_expand: new: chnd: "lvaddr" chnd_end: "lvaddr" ctxt: "lvaddr" active_ch: "lvaddr
" chnd_incr: %d delta: "lvaddr"\n", chnd, chnd_end, ctxt, active_ch, chnd_incr, delta));
nest_count--;
assert(0 <= nest_count);
# endif
}
|