121 lines
3.0 KiB
C
121 lines
3.0 KiB
C
|
/****************************************************************
|
||
|
* *
|
||
|
* Copyright 2001, 2005 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. *
|
||
|
* *
|
||
|
****************************************************************/
|
||
|
|
||
|
/* Routines to verify a simple double-linked queue.
|
||
|
|
||
|
If we fail any of these tests, we will gtmassert in case a call to
|
||
|
this routine is made from "pro" code. No messages are produced by
|
||
|
this code since they would be useful only in the context of the
|
||
|
dumped data and would scare the hell out of the user anyway.
|
||
|
|
||
|
Two versions of this test are supplied. The first will lock the queue
|
||
|
header first. The second assumes the queue is already locked.
|
||
|
|
||
|
Most(All?) calls to this routine are compiled in by specifying the compile
|
||
|
flag DEBUG_QUEUE.
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include "mdef.h"
|
||
|
|
||
|
|
||
|
#ifdef UNIX
|
||
|
#include "aswp.h"
|
||
|
#endif
|
||
|
#include "gtm_facility.h"
|
||
|
#include "gdsroot.h"
|
||
|
#include "fileinfo.h"
|
||
|
#include "gdsbt.h"
|
||
|
#include "gdsbml.h"
|
||
|
#include "gdsblk.h"
|
||
|
#include "gdsfhead.h"
|
||
|
#include "filestruct.h"
|
||
|
#include "lockconst.h"
|
||
|
#include "interlock.h"
|
||
|
#include "wcs_backoff.h"
|
||
|
|
||
|
#ifdef QI_STARVATION
|
||
|
# undef QI_STARVATION
|
||
|
# undef QI_RETRY
|
||
|
#endif
|
||
|
|
||
|
#define QI_STARVATION 1000
|
||
|
#define QI_RETRY 256
|
||
|
|
||
|
GBLREF volatile int4 fast_lock_count;
|
||
|
GBLREF pid_t process_id;
|
||
|
VMS_ONLY(GBLREF uint4 image_count;) /* Needed for GET/RELEASE_SWAPLOCK */
|
||
|
|
||
|
void verify_queue_lock(que_head_ptr_t qhdr)
|
||
|
{
|
||
|
que_ent_ptr_t qe, last_qe;
|
||
|
int i, k;
|
||
|
boolean_t got_lock;
|
||
|
|
||
|
++fast_lock_count;
|
||
|
|
||
|
/* Before we can play with the queue, we have to lock it
|
||
|
to prevent it from being changed out from underneath us */
|
||
|
for (got_lock = FALSE, k = 0; k < QI_STARVATION; ++k)
|
||
|
{
|
||
|
for (i = 0; got_lock == FALSE && i < QI_RETRY; ++i)
|
||
|
got_lock = GET_SWAPLOCK(&qhdr->latch);
|
||
|
if (got_lock)
|
||
|
break;
|
||
|
if (0 != k)
|
||
|
wcs_backoff(k);
|
||
|
}
|
||
|
|
||
|
if (!got_lock) /* We gotta have our lock */
|
||
|
GTMASSERT;
|
||
|
|
||
|
/* Now run through queue. Verify the fwd and backward chain ptrs */
|
||
|
last_qe = (que_ent_ptr_t)qhdr;
|
||
|
for (qe = (que_ent_ptr_t)((sm_uc_ptr_t)qhdr + qhdr->fl);
|
||
|
qe != (que_ent_ptr_t)qhdr;
|
||
|
qe = (que_ent_ptr_t)((sm_uc_ptr_t)qe + qe->fl))
|
||
|
{
|
||
|
|
||
|
if ((que_ent_ptr_t)((sm_uc_ptr_t)qe + qe->bl) != last_qe) /* Back pointer works good? */
|
||
|
{
|
||
|
/* ASWP(&qhdr->latch, LOCK_AVAILABLE, latch); */
|
||
|
GTMASSERT;
|
||
|
}
|
||
|
last_qe = qe;
|
||
|
}
|
||
|
|
||
|
/* Release locks */
|
||
|
RELEASE_SWAPLOCK(&qhdr->latch);
|
||
|
--fast_lock_count;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void verify_queue(que_head_ptr_t qhdr)
|
||
|
{
|
||
|
que_ent_ptr_t qe, last_qe;
|
||
|
|
||
|
/* Now run through queue. Verify the fwd and backward chain ptrs */
|
||
|
last_qe = (que_ent_ptr_t)qhdr;
|
||
|
for (qe = (que_ent_ptr_t)((sm_uc_ptr_t)qhdr + qhdr->fl);
|
||
|
qe != (que_ent_ptr_t)qhdr;
|
||
|
qe = (que_ent_ptr_t)((sm_uc_ptr_t)qe + qe->fl))
|
||
|
{
|
||
|
|
||
|
if ((que_ent_ptr_t)((sm_uc_ptr_t)qe + qe->bl) != last_qe) /* Back pointer works good? */
|
||
|
GTMASSERT;
|
||
|
last_qe = qe;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|