fis-gtm/sr_unix/ss_lock_facility.c

153 lines
4.5 KiB
C

/****************************************************************
* *
* Copyright 2010, 2011 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"
#include "gtm_string.h"
#include "gdsroot.h"
#include "gdskill.h"
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "iosp.h"
#include "relqop.h"
#include "copy.h"
#include "wcs_sleep.h"
#include "caller_id.h"
#include "rel_quant.h"
#include "sleep_cnt.h"
#include "interlock.h"
#include "is_proc_alive.h"
#include "mupipbckup.h"
#include "send_msg.h"
#include "performcaslatchcheck.h"
#include "gdsbgtr.h"
#include "lockconst.h"
#include "memcoherency.h"
#include "ss_lock_facility.h"
GBLREF volatile int4 fast_lock_count;
GBLREF pid_t process_id;
GBLREF uint4 image_count;
GBLREF int num_additional_processors;
GBLREF node_local_ptr_t locknl;
GBLREF gd_region *gv_cur_region;
/* The below lock modules are modeled over shmpool.c. Change in one should be reflected in the other one as well */
boolean_t ss_get_lock(gd_region *reg)
{
int retries, spins, maxspins;
sm_global_latch_ptr_t latch;
sgmnt_addrs *csa;
node_local_ptr_t cnl;
csa = &FILE_INFO(reg)->s_addrs;
cnl = csa->nl;
latch = &cnl->snapshot_crit_latch;
++fast_lock_count; /* Disable wcs_stale for duration */
maxspins = num_additional_processors ? MAX_LOCK_SPINS(LOCK_SPINS, num_additional_processors) : 1;
/* Since LOCK_TRIES is approx 50 seconds, give us 4X that long since IO is involved */
for (retries = (LOCK_TRIES * 4) - 1; 0 < retries; retries--) /* - 1 so do rel_quant 3 times first */
{
for (spins = maxspins; 0 < spins; spins--)
{ /* We better not hold it if trying to get it */
assert(latch->u.parts.latch_pid != process_id
VMS_ONLY(|| latch->u.parts.latch_image_count != image_count));
if (GET_SWAPLOCK(latch))
{
DEBUG_ONLY(locknl = csa->nl);
LOCK_HIST("OBTN", latch, process_id, retries);
DEBUG_ONLY(locknl = NULL);
/* Note that fast_lock_count is kept incremented for the duration that we hold the lock
to prevent our dispatching an interrupt that could deadlock getting this lock
*/
return TRUE;
}
}
if (retries & 0x3)
{ /* On all but every 4th pass, do a simple rel_quant */
rel_quant(); /* Release processor to holder of lock (hopefully) */
} else
{
/* On every 4th pass, we bide for awhile */
wcs_sleep(LOCK_SLEEP);
/* If near end of loop segment (LOCK_TRIES iters), see if target is dead and/or wake it up */
if (RETRY_CASLATCH_CUTOFF == (retries % LOCK_TRIES))
performCASLatchCheck(latch, TRUE);
}
}
DUMP_LOCKHIST();
--fast_lock_count;
assert(0 <= fast_lock_count);
assert(FALSE);
return FALSE;
}
boolean_t ss_get_lock_nowait(gd_region *reg)
{
sm_global_latch_ptr_t latch;
sgmnt_addrs *csa;
node_local_ptr_t cnl;
csa = &FILE_INFO(reg)->s_addrs;
cnl = csa->nl;
latch = &cnl->snapshot_crit_latch;
++fast_lock_count; /* Disable wcs_stale for duration */
/* We better not hold it if trying to get it */
assert(latch->u.parts.latch_pid != process_id VMS_ONLY(|| latch->u.parts.latch_image_count != image_count));
if (GET_SWAPLOCK(latch))
{
DEBUG_ONLY(locknl = csa->nl);
LOCK_HIST("OBTN", latch, process_id, -1);
DEBUG_ONLY(locknl = NULL);
/* Note that fast_lock_count is kept incremented for the duration that we hold the lock
* to prevent our dispatching an interrupt that could deadlock getting this lock
*/
return TRUE;
}
--fast_lock_count;
assert(0 <= fast_lock_count);
return FALSE;
}
void ss_release_lock(gd_region *reg)
{
sm_global_latch_ptr_t latch;
sgmnt_addrs *csa;
node_local_ptr_t cnl;
csa = &FILE_INFO(reg)->s_addrs;
cnl = csa->nl;
latch = &cnl->snapshot_crit_latch;
assert(process_id == latch->u.parts.latch_pid VMS_ONLY(&& image_count == latch->u.parts.latch_image_count));
DEBUG_ONLY(locknl = csa->nl);
LOCK_HIST("RLSE", latch, process_id, 0);
RELEASE_SWAPLOCK(latch);
DEBUG_ONLY(locknl = NULL);
--fast_lock_count;
assert(0 <= fast_lock_count);
}
boolean_t ss_lock_held_by_us(gd_region *reg)
{
sgmnt_addrs *csa;
node_local_ptr_t cnl;
csa = &FILE_INFO(reg)->s_addrs;
cnl = csa->nl;
return GLOBAL_LATCH_HELD_BY_US(&cnl->snapshot_crit_latch);
}