fis-gtm/sr_port/mlk_shrblk_find.c

150 lines
4.3 KiB
C

/****************************************************************
* *
* Copyright 2001, 2007 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 "mlkdef.h"
#include "mmemory.h"
#include "is_proc_alive.h"
#include "mlk_shrblk_find.h"
#include "mlk_shrblk_create.h"
GBLREF int4 process_id;
bool mlk_find_blocking_child_lock(mlk_pvtblk *p, mlk_shrblk_ptr_t child, UINTPTR_T auxown);
bool mlk_find_blocking_child_lock(mlk_pvtblk *p, mlk_shrblk_ptr_t child, UINTPTR_T auxown)
{
mlk_shrblk_ptr_t d, dhead, d1;
bool blocked;
blocked = FALSE;
for (dhead = d = child, d1 = NULL ; dhead != d1 && !blocked ; d = d1 = (mlk_shrblk_ptr_t)R2A(d->rsib))
{
/* There is similar code below to check if the
* process that owns the lock still exists. Any change in this
* part of the code should be propogated to those segments
* too.
*/
if (d->owner && (d->owner != process_id || d->auxowner != auxown))
{ /* If owned and not owned by us check if owner is alive */
if (is_proc_alive(d->owner, d->image_count))
{ /* Signal that this lock request is blocked by this node */
p->blocked = d;
p->blk_sequence = d->sequence;
blocked = TRUE;
} else
{ /* Owner is dead so release this node */
d->owner = 0;
d->auxowner = 0;
}
}
if (!blocked && d->children)
blocked = mlk_find_blocking_child_lock(p, (mlk_shrblk_ptr_t)R2A(d->children), auxown);
}
return blocked;
}
bool mlk_shrblk_find(mlk_pvtblk *p,
mlk_shrblk_ptr_t *ret,
UINTPTR_T auxown)
{
mlk_shrblk_ptr_t pnt, d, d0, d1, dhead;
ptroff_t *chld_of_pnt, *cop1;
mlk_shrsub_ptr_t dsub;
int i, j, slen;
unsigned char *cp;
bool blocked;
blocked = FALSE;
*ret = 0;
for (pnt = 0 , chld_of_pnt = (ptroff_t *)&p->ctlptr->blkroot , i = p->subscript_cnt , cp = p->value ;
i > 0 ; i-- , pnt = d , chld_of_pnt = (ptroff_t *)&d->children, cp += slen)
{
slen = *cp++;
if (!*chld_of_pnt)
{
if (!(d = mlk_shrblk_create(p, cp, slen, pnt, chld_of_pnt, i)))
{
return TRUE;
}
A2R(d->lsib, d);
A2R(d->rsib, d);
} else
{
for (d = (mlk_shrblk_ptr_t)R2A(*chld_of_pnt), dhead = d , cop1 = 0; ; d = (mlk_shrblk_ptr_t)R2A(d->rsib))
{
dsub = (mlk_shrsub_ptr_t)R2A(d->value);
j = memvcmp(cp, slen, dsub->data, dsub->length);
if (!j)
{ /* We found the right node */
if (d->owner && (d->owner != process_id || d->auxowner != auxown))
{ /* If owned and not owned by us check if owner is alive */
if (is_proc_alive(d->owner, d->image_count))
{ /* Signal that this lock request is blocked by this node */
p->blocked = d;
p->blk_sequence = d->sequence;
blocked = TRUE;
} else
{ /* Owner is dead so release this node */
d->owner = 0;
d->auxowner = 0;
}
}
break;
}
if (j < 0)
{ /* Insert new sibling to left of existing sibling */
if (d == dhead) /* New entry will be first in list */
cop1 = chld_of_pnt;
d0 = (mlk_shrblk_ptr_t)R2A(d->lsib);
d1 = d;
if (!(d = mlk_shrblk_create(p, cp, slen, pnt, cop1, i)))
{
return TRUE; /* resource starve -- no room for new shrblk */
}
A2R(d->lsib, d0);
A2R(d->rsib, d1);
A2R(d0->rsib, d);
A2R(d1->lsib, d);
break;
} else if ((mlk_shrblk_ptr_t)R2A(d->rsib) == dhead)
{ /* Insert new sibling to right of existing sibling */
d1 = (mlk_shrblk_ptr_t)R2A(d->rsib);
d0 = d;
if (!(d = mlk_shrblk_create(p, cp, slen, pnt, cop1, i)))
{
return TRUE; /* resource starve -- no room for new shrblk */
}
A2R(d->lsib, d0);
A2R(d->rsib, d1);
A2R(d0->rsib, d);
A2R(d1->lsib, d);
break;
}
}
}
/* When we get to the last "subscript", it's node is our lock target */
if (i == 1)
*ret = d;
}
if (*chld_of_pnt && !blocked)
{
/* look at the subtree owners to see if we will be blocked by someone underneath */
blocked = mlk_find_blocking_child_lock(p, (mlk_shrblk_ptr_t)R2A(*chld_of_pnt), auxown);
}
return blocked;
}