231 lines
7.5 KiB
C
231 lines
7.5 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 MUTEXSP_H
|
|
#define MUTEXSP_H
|
|
|
|
#ifdef MUTEX_MSEM_WAKE
|
|
#ifdef POSIX_MSEM
|
|
#include <semaphore.h>
|
|
#else
|
|
#include <sys/mman.h>
|
|
#endif
|
|
#endif
|
|
|
|
#define MUTEX_INIT_SEMVAL LOCK_AVAILABLE
|
|
#define MUTEX_IMPOSSIBLE_SEMVAL -1024 /* Any value other than
|
|
* GLOBAL_LOCK_AVAILABLE,
|
|
* GLOBAL_LOCK_IN_USE, and
|
|
* REC_UNDER_PROGRESS */
|
|
|
|
#define MUTEX_CONST_TIMEOUT_VAL 16
|
|
|
|
#define MUTEX_NUM_WAIT_BITS 19 /* max p such that 2**p <= 10**6 */
|
|
|
|
#define MUTEX_INTR_SLPCNT 2
|
|
|
|
#define WRTPND_LSBIT_MASK 1
|
|
|
|
#define MUTEX_SOCK_DIR GTM_TMP_ENV
|
|
#define DEFAULT_MUTEX_SOCK_DIR DEFAULT_GTM_TMP
|
|
#define MUTEX_SOCK_FILE_PREFIX "gtm_mutex"
|
|
|
|
#define BIN_TOGGLE(x) ((x) ? 0 : 1)
|
|
|
|
#define ONE_MILLION 1000000
|
|
|
|
#define MICROSEC_SLEEP(x) m_usleep(x)
|
|
|
|
typedef struct
|
|
{
|
|
uint4 pid;
|
|
int mutex_wake_instance;
|
|
} mutex_wake_msg_t;
|
|
|
|
typedef enum
|
|
{
|
|
MUTEX_LOCK_WRITE,
|
|
MUTEX_LOCK_WRITE_IMMEDIATE
|
|
} mutex_lock_t;
|
|
|
|
/*
|
|
* Initialize a mutex with n que entries. If crash is TRUE, then this is
|
|
* a "crash" reinitialization; otherwise it's a "clean" initialization.
|
|
*/
|
|
void gtm_mutex_init(gd_region *reg, int n, bool crash);
|
|
|
|
/* mutex_lockw - write access to mutex for region reg */
|
|
enum cdb_sc mutex_lockw(gd_region *reg, mutex_spin_parms_ptr_t mutex_spin_parms, int crash_count);
|
|
|
|
/*
|
|
* mutex_lockwim - write access to mutex for region reg; if cannot lock,
|
|
* immediately return cdb_sc_nolock
|
|
*/
|
|
enum cdb_sc mutex_lockwim(gd_region *reg, mutex_spin_parms_ptr_t mutex_spin_parms, int crash_count);
|
|
|
|
/* mutex_unlockw - unlock write access to mutex for region reg */
|
|
enum cdb_sc mutex_unlockw(gd_region *reg, int crash_count);
|
|
|
|
/* mutex_seed_init - set the seed for pseudo random mutex sleep times */
|
|
void mutex_seed_init(void);
|
|
|
|
void mutex_cleanup(gd_region *reg);
|
|
|
|
#ifdef MUTEX_MSEM_WAKE
|
|
# ifdef POSIX_MSEM
|
|
void mutex_wake_proc(sem_t *mutex_wake_msem_ptr);
|
|
# else
|
|
void mutex_wake_proc(msemaphore *mutex_wake_msem_ptr);
|
|
# endif
|
|
#else
|
|
void mutex_wake_proc(sm_int_ptr_t pid, int mutex_wake_instance);
|
|
#endif
|
|
|
|
void mutex_sock_init(void);
|
|
void mutex_sock_cleanup(void);
|
|
unsigned char *pid2ascx(unsigned char *pid_str, pid_t pid);
|
|
|
|
void mutex_per_process_init(void);
|
|
|
|
#ifdef MUTEX_MSEM_WAKE
|
|
#ifdef POSIX_MSEM
|
|
# define MSEM_LOCKW(X) sem_wait(X)
|
|
# define MSEM_LOCKNW(X) sem_trywait(X)
|
|
# define MSEM_UNLOCK(X) sem_post(X)
|
|
#else
|
|
# define MSEM_LOCKW(X) msem_lock(X, 0)
|
|
# define MSEM_LOCKNW(X) msem_lock(X, MSEM_IF_NOWAIT)
|
|
# define MSEM_UNLOCK(X) msem_unlock(X, 0)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#if defined(MUTEX_DEBUG) || defined(MUTEX_TRACE) || defined(MUTEX_TEST_RECOVERY)
|
|
#include "gtm_stdio.h"
|
|
#endif
|
|
|
|
#ifdef MUTEX_DEBUG
|
|
#define MUTEX_DPRINT1(p) {FPRINTF(stderr, p); FFLUSH(stderr);}
|
|
#define MUTEX_DPRINT2(p, q) {FPRINTF(stderr, p, q); FFLUSH(stderr);}
|
|
#define MUTEX_DPRINT3(p, q, r) {FPRINTF(stderr, p, q, r); FFLUSH(stderr);}
|
|
#define MUTEX_DPRINT4(p, q, r, s) {FPRINTF(stderr, p, q, r, s); FFLUSH(stderr);}
|
|
#define MUTEX_DPRINT5(p, q, r, s,t) {FPRINTF(stderr, p, q, r, s, t); FFLUSH(stderr);}
|
|
#else
|
|
#define MUTEX_DPRINT1(p)
|
|
#define MUTEX_DPRINT2(p, q)
|
|
#define MUTEX_DPRINT3(p, q, r)
|
|
#define MUTEX_DPRINT4(p, q, r, s)
|
|
#define MUTEX_DPRINT5(p, q, r, s, t)
|
|
#endif
|
|
|
|
#ifdef MUTEX_TRACE
|
|
#define DECLARE_MUTEX_TRACE_CNTRS \
|
|
GBLDEF int mutex_trc_lockw = 0; \
|
|
GBLDEF int mutex_trc_lockwim = 0; \
|
|
GBLDEF int mutex_trc_w_atmpts = 0; \
|
|
GBLREF int mutex_trc_mutex_slp_fn = 0; \
|
|
GBLREF int mutex_trc_mutex_slp_fn_noslp = 0; \
|
|
GBLDEF int mutex_trc_slp = 0; \
|
|
GBLDEF int mutex_trc_wt_short_slp = 0; \
|
|
GBLDEF int mutex_trc_wtim_short_slp = 0; \
|
|
GBLDEF int mutex_trc_slp_tmout = 0; \
|
|
GBLDEF int mutex_trc_intr_tmout = 0; \
|
|
GBLDEF int mutex_trc_slp_intr = 0; \
|
|
GBLDEF int mutex_trc_slp_wkup = 0; \
|
|
GBLDEF int mutex_trc_pgybckd_dlyd_wkup = 0; \
|
|
GBLDEF int mutex_trc_xplct_dlyd_wkup = 0; \
|
|
GBLDEF int mutex_trc_crit_wk = 0; \
|
|
GBLDEF int mutex_trc_dump_done = 0;
|
|
|
|
#define USE_MUTEX_TRACE_CNTRS \
|
|
GBLREF int mutex_trc_lockw; \
|
|
GBLREF int mutex_trc_lockwim; \
|
|
GBLREF int mutex_trc_w_atmpts; \
|
|
GBLREF int mutex_trc_mutex_slp_fn; \
|
|
GBLREF int mutex_trc_mutex_slp_fn_noslp; \
|
|
GBLREF int mutex_trc_slp; \
|
|
GBLREF int mutex_trc_wt_short_slp; \
|
|
GBLREF int mutex_trc_wtim_short_slp; \
|
|
GBLREF int mutex_trc_slp_tmout; \
|
|
GBLDEF int mutex_trc_intr_tmout; \
|
|
GBLDEF int mutex_trc_slp_intr; \
|
|
GBLREF int mutex_trc_slp_wkup; \
|
|
GBLREF int mutex_trc_pgybckd_dlyd_wkup; \
|
|
GBLREF int mutex_trc_xplct_dlyd_wkup; \
|
|
GBLREF int mutex_trc_crit_wk; \
|
|
GBLDEF int mutex_trc_dump_done;
|
|
|
|
#define MUTEX_TRACE_CNTR(x) ((x)++)
|
|
|
|
#define DUMP_MUTEX_TRACE_CNTRS \
|
|
if (!mutex_trc_dump_done) \
|
|
{ \
|
|
FPRINTF(stderr, "mutex_lockw : %d\n", mutex_trc_lockw);\
|
|
FPRINTF(stderr, "mutex_lockwim : %d\n", mutex_trc_lockwim);\
|
|
FPRINTF(stderr, "Lock write attempts : %d\n", mutex_trc_w_atmpts);\
|
|
FPRINTF(stderr, "Calls to mutex_sleep : %d\n", mutex_trc_mutex_slp_fn);\
|
|
FPRINTF(stderr, "Mutex_sleep no sleep : %d\n", mutex_trc_mutex_slp_fn_noslp);\
|
|
FPRINTF(stderr, "Write short sleep count : %d\n", mutex_trc_wt_short_slp);\
|
|
FPRINTF(stderr, "Wrt Imm short slp count : %d\n", mutex_trc_wtim_short_slp);\
|
|
FPRINTF(stderr, "Sleep timeout : %d\n", mutex_trc_slp_tmout);\
|
|
FPRINTF(stderr, "Sleep timeout caused by intr: %d\n", mutex_trc_intr_tmout);\
|
|
FPRINTF(stderr, "Sleep interrupted : %d\n", mutex_trc_slp_intr);\
|
|
FPRINTF(stderr, "Sleep woken up : %d\n", mutex_trc_slp_wkup);\
|
|
FPRINTF(stderr, "Dlyd pgybckd slp wkup : %d\n", mutex_trc_pgybckd_dlyd_wkup);\
|
|
FPRINTF(stderr, "Dlyd xplct slp wkup : %d\n", mutex_trc_xplct_dlyd_wkup);\
|
|
FPRINTF(stderr, "Crit wake others : %d\n", mutex_trc_crit_wk);\
|
|
mutex_trc_dump_done = 1;\
|
|
}
|
|
|
|
#else
|
|
|
|
#define DECLARE_MUTEX_TRACE_CNTRS
|
|
#define USE_MUTEX_TRACE_CNTRS
|
|
#define MUTEX_TRACE_CNTR(x)
|
|
#define DUMP_MUTEX_TRACE_CNTRS
|
|
|
|
#endif /* MUTEX_TRACE */
|
|
|
|
#ifdef MUTEX_TEST_RECOVERY
|
|
|
|
#include <signal.h>
|
|
#define DECLARE_MUTEX_TEST_SIGNAL_FLAG GBLDEF int mutex_test_signalled = FALSE;
|
|
#define USE_MUTEX_TEST_SIGNAL_FLAG GBLREF int mutex_test_signalled;
|
|
#define MUTEX_TEST_SIGNAL_HERE(x, y) \
|
|
if ((y) && !mutex_test_signalled) \
|
|
{ \
|
|
FPRINTF(stderr, x); \
|
|
FFLUSH(stderr); \
|
|
mutex_test_signalled = TRUE; \
|
|
exi_rundown(SIGQUIT); change this before use \
|
|
} \
|
|
else ;
|
|
#define MUTEX_TEST_PRINT1(p) {FPRINTF(stderr, p); FFLUSH(stderr);}
|
|
#define MUTEX_TEST_PRINT2(p, q) {FPRINTF(stderr, p, q); FFLUSH(stderr);}
|
|
#define MUTEX_TEST_PRINT3(p, q, r) {FPRINTF(stderr, p, q, r); FFLUSH(stderr);}
|
|
#define MUTEX_TEST_PRINT4(p, q, r, s) {FPRINTF(stderr, p, q, r, s); FFLUSH(stderr);}
|
|
#define MUTEX_TEST_PRINT5(p, q, r, s,t) {FPRINTF(stderr, p, q, r, s, t); FFLUSH(stderr);}
|
|
|
|
#else
|
|
|
|
#define DECLARE_MUTEX_TEST_SIGNAL_FLAG
|
|
#define USE_MUTEX_TEST_SIGNAL_FLAG
|
|
#define MUTEX_TEST_SIGNAL_HERE(x, y)
|
|
#define MUTEX_TEST_PRINT1(p)
|
|
#define MUTEX_TEST_PRINT2(p, q)
|
|
#define MUTEX_TEST_PRINT3(p, q, r)
|
|
#define MUTEX_TEST_PRINT4(p, q, r, s)
|
|
#define MUTEX_TEST_PRINT5(p, q, r, s, t)
|
|
|
|
#endif /* MUTEX_TEST */
|
|
|
|
#endif /* MUTEXSP_H */
|