153 lines
4.5 KiB
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);
|
||
|
}
|