99 lines
3.5 KiB
C
99 lines
3.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. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
#include "mdef.h"
|
|
#include "gdsroot.h"
|
|
#include "gtm_facility.h"
|
|
#include "fileinfo.h"
|
|
#include "gdsbt.h"
|
|
#include "gdsfhead.h"
|
|
#include "filestruct.h"
|
|
#include "mlkdef.h"
|
|
#include "cdb_sc.h"
|
|
#include "jnl.h"
|
|
#include "gdscc.h"
|
|
#include "gdskill.h"
|
|
#include "buddy_list.h" /* needed for tp.h */
|
|
#include "hashtab_int4.h" /* needed for tp.h */
|
|
#include "tp.h"
|
|
#include "t_retry.h"
|
|
#include "mlk_shrblk_delete_if_empty.h"
|
|
#include "mlk_tree_wake_children.h"
|
|
#include "mlk_unlock.h"
|
|
#include "mlk_wake_pending.h"
|
|
#include "gvusr.h"
|
|
#include "min_max.h"
|
|
|
|
GBLREF int4 process_id;
|
|
GBLREF short crash_count;
|
|
GBLREF uint4 dollar_tlevel;
|
|
GBLREF unsigned int t_tries;
|
|
GBLREF tp_region *tp_reg_free_list; /* Ptr to list of tp_regions that are unused */
|
|
GBLREF tp_region *tp_reg_list; /* Ptr to list of tp_regions for this transaction */
|
|
|
|
void mlk_unlock(mlk_pvtblk *p)
|
|
{
|
|
int status;
|
|
mlk_shrblk_ptr_t d, pnt;
|
|
mlk_ctldata_ptr_t ctl;
|
|
bool stop_waking, was_crit;
|
|
sgmnt_addrs *csa;
|
|
float ls_free; /* Free space in bottleneck subspace */
|
|
|
|
if (p->region->dyn.addr->acc_meth != dba_usr)
|
|
{
|
|
ctl = p->ctlptr;
|
|
assert((ctl->max_blkcnt > 0) && (ctl->max_prccnt > 0) && ((ctl->subtop - ctl->subbase) > 0));
|
|
csa = &FILE_INFO(p->region)->s_addrs;
|
|
d = p->nodptr;
|
|
if (csa->critical)
|
|
crash_count = csa->critical->crashcnt;
|
|
if (dollar_tlevel && !((t_tries < CDB_STAGNATE) || csa->now_crit)) /* Final retry and region not locked down */
|
|
{ /* make sure this region is in the list in case we end up retrying */
|
|
insert_region(p->region, &tp_reg_list, &tp_reg_free_list, SIZEOF(tp_region));
|
|
/* insert_region() will additionally attempt CRIT on the region and restart if not possible */
|
|
assert(csa->now_crit);
|
|
}
|
|
if (FALSE == (was_crit = csa->now_crit))
|
|
grab_crit(p->region);
|
|
if (d->owner == process_id && p->sequence == d->sequence)
|
|
{
|
|
d->owner = 0;
|
|
d->sequence = csa->hdr->trans_hist.lock_sequence++;
|
|
assert(!d->owner || d->owner == process_id);
|
|
/* do not call mlk_tree_wake_children/mlk_wake_pending on "d" if d->owner is non-zero.
|
|
* for comments on why, see comments about d->owner in mlk_wake_pending.c
|
|
*/
|
|
stop_waking = (d->children && !d->owner)
|
|
? mlk_tree_wake_children(ctl, (mlk_shrblk_ptr_t)R2A(d->children), p->region)
|
|
: FALSE;
|
|
for ( ; d ; d = pnt)
|
|
{
|
|
pnt = ((d->parent) ? (mlk_shrblk_ptr_t)R2A(d->parent) : 0);
|
|
if (!stop_waking && d->pending && !d->owner)
|
|
{
|
|
mlk_wake_pending(ctl, d, p->region);
|
|
stop_waking = TRUE;
|
|
} else
|
|
mlk_shrblk_delete_if_empty(ctl, d);
|
|
}
|
|
}
|
|
/* Find the ratio of least free subspace. Here we intentionally ignore shr_sub_len to keep unlock lightweight. */
|
|
ls_free = MIN(((float)ctl->blkcnt) / ctl->max_blkcnt, ((float)ctl->prccnt) / ctl->max_prccnt);
|
|
if (ls_free >= LOCK_SPACE_FULL_SYSLOG_THRESHOLD)
|
|
csa->nl->lockspacefull_logged = FALSE; /* Allow syslog writes if enough free space is established. */
|
|
if (FALSE == was_crit)
|
|
rel_crit(p->region);
|
|
} else /* acc_meth == dba_usr */
|
|
gvusr_unlock(p->total_length, &p->value[0], p->region);
|
|
return;
|
|
}
|