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 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
|
/****************************************************************
* *
* Copyright (c) 2001-2024 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. *
* *
****************************************************************/
#ifndef GT_TIMER_H
#define GT_TIMER_H
/* System dependent include file for gtm timer package */
#include <signal.h>
typedef INTPTR_T TID; /* Timer ID type */
typedef void (*timer_hndlr)(TID tid, int4 len, void *data); /* Timer handler type */
/* Gtm timer package uses ABS_TIME structure to carry
* the time information in operating system independent
* manner. The time in this structure is stored as
* an absolute time - elapsed time since some major historic
* event, or some other fixed date in the past. Different
* operating systems have different time reference points.
*
* The time is converted from the OS time format to
* the ABS_TIME format, and from then on, all
* timer related code uses this format.
*/
typedef struct tag_abs_time
{
#ifndef __osf__
long at_sec; /* seconds */
long at_usec; /* and microseconds */
#else /* avoid 8 byte alignment issues */
intszofptr_t at_sec; /* seconds */
intszofptr_t at_usec; /* and microseconds */
#endif
} ABS_TIME;
#include <sys/time.h>
/* Type that corresponds to the tv_usec field in a timeval struct. Valid across all platforms */
#if defined(__linux__) || defined(__ia64) || defined(__sparc) || defined(_AIX) || defined(__MVS__) \
|| defined(__CYGWIN__)
typedef suseconds_t gtm_tv_usec_t;
#elif defined(__hppa)
typedef long gtm_tv_usec_t;
#elif defined(__osf__)
typedef int gtm_tv_usec_t;
#elif !defined(VMS)
# error unsupported platform
#endif
/* All timer requests are placed into a linked list, or
* a queue of pending requests in a time order.
* The first timer in this queue is the currently
* active timer, and expires first.
*/
#define GT_TIMER_INIT_DATA_LEN 8
typedef struct tag_ts
{
ABS_TIME expir_time; /* Absolute time when timer expires */
ABS_TIME start_time; /* Time when the timer is added */
timer_hndlr handler; /* Pointer to handler routine */
struct tag_ts *next; /* Pointer to next */
TID tid; /* Timer id */
int4 safe; /* Indicates if handler can be delivered while we are in
* a deferred mode
*/
int4 block_int; /* Set to intrpt_state_t value if timer handling was blocked
* by an uninterruptible state. For use in debugging, but not
* conditional on DEBUG to keep the structure stable.
*/
int4 hd_len_max; /* Max length this blk can hold */
int4 hd_len; /* Handler data length */
char hd_data[GT_TIMER_INIT_DATA_LEN]; /* Handler data */
} GT_TIMER;
/* Struct to track timefree block allocations */
typedef struct st_timer_alloc
{
void *addr;
struct st_timer_alloc *next;
} st_timer_alloc;
#define MAX_SAFE_TIMER_HNDLRS 16 /* Max # of safe timer handlers */
#define GT_WAKE
#define CANCEL_TIMERS cancel_unsafe_timers()
/* Set a timeout timer, using a local variable as the timeout indicator.
* Note: This macro establishes a condition handler which cancels the timer in case of an rts_error.
* The TIMEOUT_DONE() macro must be used on all normal routine exit paths in order to REVERT the handler.
*/
#define TIMEOUT_INIT(TIMEOUT_VAR, TIMEOUT_MILLISECS) \
MBSTART { \
boolean_t *ptr_to_##TIMEOUT_VAR = &(TIMEOUT_VAR); \
boolean_t got_error; \
\
TIMEOUT_VAR = FALSE; \
start_timer((TID)ptr_to_##TIMEOUT_VAR, TIMEOUT_MILLISECS, simple_timeout_timer, \
SIZEOF(ptr_to_##TIMEOUT_VAR), &ptr_to_##TIMEOUT_VAR); \
ESTABLISH_NORET(timer_cancel_ch, got_error); \
if (got_error) \
{ \
TIMEOUT_DONE(TIMEOUT_VAR); \
DRIVECH(error_condition); \
} \
} MBEND
#define TIMEOUT_DONE(TIMEOUT_VAR) \
MBSTART { \
boolean_t *ptr_to_##TIMEOUT_VAR = &(TIMEOUT_VAR); \
\
assert(ctxt->ch == timer_cancel_ch); \
REVERT; \
cancel_timer((TID)ptr_to_##TIMEOUT_VAR); \
} MBEND
/* Lighter versions with no condition handler, for when it is safe to have the timer hang around after it is no longer relevant. */
#define TIMEOUT_INIT_NOCH(TIMEOUT_VAR, TIMEOUT_MILLISECS) \
MBSTART { \
boolean_t *ptr_to_##TIMEOUT_VAR = &(TIMEOUT_VAR); \
\
TIMEOUT_VAR = FALSE; \
start_timer((TID)ptr_to_##TIMEOUT_VAR, TIMEOUT_MILLISECS, simple_timeout_timer, \
SIZEOF(ptr_to_##TIMEOUT_VAR), &ptr_to_##TIMEOUT_VAR); \
} MBEND
#define TIMEOUT_DONE_NOCH(TIMEOUT_VAR) \
MBSTART { \
boolean_t *ptr_to_##TIMEOUT_VAR = &(TIMEOUT_VAR); \
\
cancel_timer((TID)ptr_to_##TIMEOUT_VAR); \
} MBEND
/* Uncomment the below #define if you want to print the status of the key timer-related variables as well as the entire timer queue
* when operations such as addition, cancellation, or handling of a timer occur.
*
* #define TIMER_DEBUGGING
*/
#define MAX_UNKNOWN_LEN 20 + 1
#ifdef TIMER_DEBUGGING
# define DUMP_TIMER_INFO(LOCATION) \
{ \
extern void (*fake_enospc_ptr)(); \
extern void (*simple_timeout_timer_ptr)(); \
int i; \
GT_TIMER *cur_timer; \
char *s_jnl_file_close_timer = "jnl_file_close_timer"; \
char *s_wcs_clean_dbsync = "wcs_clean_dbsync"; \
char *s_wcs_stale = "wcs_stale"; \
char *s_fake_enospc = "fake_enospc"; \
char *s_simple_timeout_timer = "simple_timeout_timer"; \
char s_unknown[MAX_UNKNOWN_LEN]; \
char *handler; \
\
cur_timer = (GT_TIMER *)timeroot; \
FPRINTF(stderr, "------------------------------------------------------\n" \
"%s\n---------------------------------\n" \
"Timer Info:\n" \
" system timer active: %d\n" \
" timer in handler: %d\n" \
" timer stack count: %d\n" \
" oldjnlclose started: %d\n", \
LOCATION, timer_active, timer_in_handler, \
timer_stack_count, oldjnlclose_started); \
FFLUSH(stderr); \
i = 0; \
while (cur_timer) \
{ \
if ((void (*)())jnl_file_close_timer_ptr == cur_timer->handler) \
handler = s_jnl_file_close_timer; \
else if ((void (*)())wcs_clean_dbsync_fptr == cur_timer->handler) \
handler = s_wcs_clean_dbsync; \
else if ((void (*)())wcs_stale_fptr == cur_timer->handler) \
handler = s_wcs_stale; \
else if ((void (*)())fake_enospc_ptr == cur_timer->handler) \
handler = s_fake_enospc; \
else if ((void (*)())simple_timeout_timer_ptr == cur_timer->handler) \
handler = s_simple_timeout_timer; \
else \
{ \
SNPRINTF(s_unknown, MAX_UNKNOWN_LEN, "%p", (void *)handler); \
handler = s_unknown; \
} \
FPRINTF(stderr, " - timer #%d:\n" \
" handler: %s\n" \
" safe: %d\n" \
" start_time: [at_sec: %ld; at_usec: %ld]\n" \
" expir_time: [at_sec: %ld; at_usec: %ld]\n", \
i, handler, cur_timer->safe, \
cur_timer->start_time.at_sec, cur_timer->start_time.at_usec, \
cur_timer->expir_time.at_sec, cur_timer->expir_time.at_usec); \
FFLUSH(stderr); \
cur_timer = cur_timer->next; \
i++; \
} \
FPRINTF(stderr, "------------------------------------------------------\n"); \
FFLUSH(stderr); \
}
#else
# define DUMP_TIMER_INFO(LOCATION)
#endif
int4 abs_time_comp(ABS_TIME *atp1, ABS_TIME *atp2);
void add_int_to_abs_time(ABS_TIME *atps, int4 ival, ABS_TIME *atpd);
void cancel_timer(TID tid);
void cancel_unsafe_timers(void);
void clear_timers(void);
void hiber_start(uint4 milliseconds);
void hiber_start_wall_time(uint4 milliseconds);
void hiber_start_wait_any(uint4 milliseconds);
void gtm_start_timer(TID tid, int4 time_to_expir, void(* handler)(), int4 data_length, void *handler_data);
void start_timer(TID tid, int4 time_to_expir, void(* handler)(), int4 data_length, void *handler_data);
ABS_TIME sub_abs_time(ABS_TIME *atp1, ABS_TIME *atp2);
void sys_get_curr_time(ABS_TIME *tp);
void sys_get_wall_time(ABS_TIME *atp);
void prealloc_gt_timers(void);
void set_blocksig(void);
void check_for_timer_pops(boolean_t sig_handler_changed);
GT_TIMER *find_timer_intr_safe(TID tid, GT_TIMER **tprev);
void check_for_deferred_timers(void);
void add_safe_timer_handler(int safetmr_cnt, ...);
void sys_canc_timer(void);
void simple_timeout_timer(TID tid, int4 hd_len, boolean_t **timedout);
STATICFNDCL void gt_timers_alloc(void);
STATICFNDCL void start_timer_int(TID tid, int4 time_to_expir, void (*handler)(), int4 hdata_len,
void *hdata, boolean_t safe_timer);
STATICFNDCL void sys_settimer (TID tid, ABS_TIME *time_to_expir);
STATICFNDCL void start_first_timer(ABS_TIME *curr_time);
STATICFNDCL void timer_handler(int why);
STATICFNDCL GT_TIMER *find_timer(TID tid, GT_TIMER **tprev);
STATICFNDCL GT_TIMER *add_timer(ABS_TIME *atp, TID tid, int4 time_to_expir, void (*handler)(), int4 hdata_len,
void *hdata, boolean_t safe_timer);
STATICFNDCL void remove_timer(TID tid);
STATICFNDCL void init_timers(void);
#endif
|