Extract from ksl.c
==================
/*
** Get the latch specified by "id", on behalf of the current
** session. If "wait" is FALSE, return immediately if the
** latch is in use; if TRUE, keep trying and return when the
** latch has been granted. Return TRUE if and only if the
** latch was granted. Raise an error if this is cleanup, wait
** is TRUE, and the latch is busy. This procedure checks for
** errors in latch sequence (based on level), and records what
** latches are held so they can be freed if needed.
*/
!!!*** C 01 ***!!!
word kslget(l, wait) /* get a latch */
reg0 ksllt *l; /* latch we are latching */
word wait; /* wait for latch or just return */
{
!!!*** C 02 ***!!!
reg1 kslla *state; /* latch state */
reg2 word level; /* latching level */
/* initialize */
!!!*** C 03 ***!!!
state = ksuglk(ksugcp()); /* get process latching state */
level = l->kslltlvl; /* get level of latch */
#ifdef KSLDEBUG
/* if currently hold a fast latch, cannot get another latch */
!!!*** C 04 ***!!!
if (state->ksllalaq)
ksesic2(OERI(503), ksenrg(state->ksllalaq),
ksesrgl((text *)kslldt[state->ksllalaq->kslltnum].kslldnam));
#endif
/* Enforce latch hirearchy to prevent deadlocks.
* Check if a latch is already held at this level or any higher level.
*/
!!!*** C 05 ***!!!
if (bit(state->ksllalow, levelbits[level]))
{
!!!*** C 06 ***!!!
if (!wait)
{
!!!*** C 07 ***!!!
if (!state->ksllalat[level]) /* no latch gotten at this level */
; /* allow nowait get to proceded */
/* allow one duplicate get at a level if it is gotten nowait */
else if (state->ksllalat[level] != l && !state->ksllalat[KSLLMXLV+1])
level = KSLLMXLV+1; /* use the slot that is one past the highest */
else /* never signal conflict on nowait get */
return FALSE;
}
else
ksesic4(
OERI(504), /* kslget: failure to follow lock hierarchy */
ksenrg(l), ksenrg(state->ksllalow),
ksenrg(level), ksesrgl((text *)kslldt[l->kslltnum].kslldnam));
}
/* set "we are waiting for the latch" and go try to get it */
state->ksllalaq = l;
/* Do a fast try to get the latch */
!!!*** C 08 ***!!!
if (sclgtf(&l->kslltlat)) /* do the test and set (or equivalent) */
{
/* Got the latch on first try */
bis(state->ksllalow, 1 << level); /* set level bit for level checking */
state->ksllalat[level] = l; /* indicate latch gotten at this level */
l->kslltefd = kgetfd(ksmgpga); /* error frame. depth for error recovery */
/* Note that the number of latch gets is used during cleanup (it is not
* just for statistics). So don't delete this code.
*/
if (wait)
l->kslltwgt++; /* bump wait gets */
else
l->kslltngt++; /* bump nowait gets */
KSLDBG(state->ksllalaq = (ksllt *)0;)
/* check if latch debugging is turned on */
if (ksldbg)
{
/* set trace info if appropriate */
kslsgtr(l, kslcmt);
/* unprotect the latch's recovery structure if necessary */
kslprrc(l, TRUE);
}
return TRUE; /* return success */
}
else if (!wait) /* if failed to get the latch and not supposed to wait */
{
/* Bump nowait attempts. This increment is not protected by the latch,
* so it may be lost or garbled if several processes do this at the same
* time.
*/
l->kslltnfa++; /* nowait failures */
state->ksllalaq = (ksllt *)0; /* not trying to get it anymore */
return FALSE;
}
/* Someone else has the latch, we must wait for it. Call kslges indirectly
* so the compiler will not inline the routine (this causes many registers
* to be saved unnecessarily).
*/
!!!*** C 09 ***!!!
return (*kslger)(l, FALSE);
}
/* remove myself from list of waiter processes on a latch. */
STATICF void kslwrmv(state)
reg0 kslla *state;
{
reg1 kslla *wait_proc;
reg2 kslla **proc_link;
/* walk list of processes waiting for this latch */
!!!*** C 10 ***!!!
for (wait_proc = state->ksllawtr->kslltwkp,
proc_link = &state->ksllawtr->kslltwkp;
wait_proc;
proc_link = &wait_proc->ksllanxw, wait_proc = *proc_link)
!!!*** C 11 ***!!!
if (wait_proc == state) /* if waiter is me */
{
*proc_link = state->ksllanxw; /* pop myself from list */
break;
}
/* Note that if I was previously killed while linking or unlinking myself
* from a wait list, I might never have made it on the list, but I would
* still have my state set as if I did. We always link on the the waiter
* list last when adding to the wait list, and unlink first when removing
* from the wait list. Therefore I need to clear my state whether I am on
* the list or not to cleanup from process death.
*/
state->ksllanxw = (kslla *)0; /* no next waiter */
state->ksllawtr = (ksllt *)0; /* not on wait list for this latch */
}
/* Second part of kslget. We failed to get the latch on the first try so
* now we have to wait for it.
*/
word kslges(l, from_macro)
reg0 ksllt *l; /* latch we are latching */
eword from_macro; /* true if called from kslatm macro */
{
ub4 i; /* miss counter */
reg1 kslla *state; /* latch state */
reg2 word level; /* latching level */
reg3 eword max_backoff = kslmex; /* Let's initialize this, okay? */
eword other_latch = FALSE;
/* initialize */
state = ksuglk(ksugcp()); /* get process latching state */
level = l->kslltlvl; /* get level of latch */
/* Don't sleep too long if currently holding a latch since this will tend to
* backup the people waiting for me. This does not apply if the latch is
* an allocated child latch since there are lots of those.
*/
if (state->ksllalow) /* if currently holding a latch */
{
for (i = 0; i <= level; i++) /* for all latches I am holding */
if (state->ksllalat[i] &&
!state->ksllalat[i]->kslltchn) /* if holding non-child latch */
{
max_backoff = kslmsl; /* set max backoff to smaller value */
other_latch = TRUE; /* remember we're holding another latch */
break;
}
}
/* keep trying to get the latch until we succeed */
for (i = 0; ; i++)
{
serc se;
/* set "we are waiting for the latch" and go get it */
state->ksllalaq = l;
/* try to get the latch again */
if (sclgts(&se, &l->kslltlat, /* the latch to get */
ksugpi(ksugcp()), /* the OSD process structure */
&state->ksllalaq, /* pointer to latch trying to acquire */
ksuicl())) /* am I the cleanup process */
{
l->kslltwgt++; /* bump wait gets statistic */
l->kslltwff++; /* bump failed first attempt statistic */
l->kslltwsl += i; /* increment sleeps statistic */
if (state->ksllalow) l->kslltwth++; /* increment sleeps holding latch */
/* increment histogram of wait times */
if (i >= KSLHSTMAX)
l->ksllthst[KSLHSTMAX-1]++;
else l->ksllthst[i]++;
if (!from_macro) /* don't set these if called by fast path macro */
{
bis(state->ksllalow, 1 << level);/* set level bit for level checking */
state->ksllalat[level] = l; /* indicate latch gotten at this level */
KSLDBG(state->ksllalaq = (ksllt *)0;)
}
l->kslltefd = kgetfd(ksmgpga); /* error frame. depth for error recovery */
/* check if latch debugging is turned on */
if (ksldbg)
{
/* set trace info if appropriate */
kslsgtr(l, kslcmt);
/* unprotect the latch's recovery structure if necessary */
kslprrc(l, TRUE);
}
return TRUE;
}
else
{
/* We did not get the latch, someone else must have it. We must wait */
state->ksllalaq = (ksllt *)0; /* we are not trying to get it now */
if (SERC_ERROR(se)) /* if something went wrong, signal error */
{
(*ksloet)(); /* Dump useful info */
DISCARD ksecrs(&se); /* record error code */
ksesic0(OERI(506));
}
if (i == 5 && !ksuicl()) /* if waited for a few hundreth's of a second */
ksupsx(); /* post cleanup in case dead process holds latch */
/* if should use post waiters option to latching */
!!!*** C 12 ***!!!
if ( kslpwt /* waiting is enabled */
&& l != kslwlst /* not waiting for the waiter list latch */
&& !from_macro /* not from macro, macros don't call kslfre */
&& (i == 0 || /* first time through loop */
!state->ksllawtr) /* someone woke me but I didn't get latch */
&& !state->ksllalat[kslwlst->kslltlvl] /* no out of order latch */
&& (kslpwt > 1 || /* waiting enabled for all latches */
kslldt[l->kslltnum].kslldlng)) /* this is a 'long' latch */
{
/* Add myself to the head of the waiter list. */
KSLBEGIN(kslwlst) /* get latch waiter list latch */
/* If I am still on waiter list of a latch that I am holding I need
* to get off that list before going on another waiter list. Note
* that I don't normally take myself off a waiter list until I free
* the latch to avoid adding extra code path under the latch that
* people are waiting for. This is why I could be on a waiter list
* while I am holding the latch.
*/
if (state->ksllawtr) /* if on waiter list for a latch */
kslwrmv(state); /* take myself off the list */
state->ksllawtr = l; /* latch whose waiter list I am going on */
/* give preference to waiters that are holding another latch */
if (l->kslltwkp /* if someone already on wait list */
&& !other_latch) /* and I am not holding a latch */
{
/* put myself in second slot of wait list in case the person in
* the first slot is holding a latch. This gives him precedence.
*/
/* people after first guy are now after me */
state->ksllanxw = l->kslltwkp->ksllanxw;
l->kslltwkp->ksllanxw = state; /* I am after first guy */
}
else
{
/* put myself at the head of the waiter list */
state->ksllanxw = l->kslltwkp; /* head of list goes after me */
l->kslltwkp = state; /* I go at head of list */
}
KSLEND /* remember I am on the list */
}
state->ksllawat = l; /* set latch we are waiting for */
/* do exponential backoff */
kslewt3(i, max_backoff, (state->ksllawtr ? TRUE : FALSE),
ksllfe, l, l->kslltnum, i);
state->ksllawat = (ksllt *)0; /* clear latch we are waiting for */
ksucfi(); /* Check for any interrupts which are fatal to the instance */
ksecss(&se); /* check for error */
if (i > 7 && ksuicl()) /* if PMON and waited long enough */
{
/* PMON has not been able to get the latch. The latch might be held
* by a dead process so search for dead processes, and free their
* latches. When freeing dead processes latches, PMON must only free
* latches that have a higher level than the highest level latch he
* is currently holding since freeing a latch can cause another
* latch to be gotten which could lead to a conflict with the latches
* PMON already holds.
*/
DISCARD ksuxfl(); /* free dead process' latches */
!!!*** C 13 ***!!!
if (i == 200) /* if waited for a long time */
{
ksupr *pr = kslown(l); /* process that holds the latch */
ksdwrf("PMON unable to acquire latch %lx %s\n", (unsigned long)l,
(char *)kslldt[l->kslltnum].kslldnam);
if (pr)
ksdwrf(" possible holder pid = %d spid=%.*s\n", (int)ksuprp(pr),
(int)ksugpri(pr)->ksuospdl, (char *)ksugpri(pr)->ksuospid);
ksdddt(); /* write time stamp */
ksdfls(); /* flush dump file */
ksdwra("PMON failed to acquire latch, see PMON dump");
}
}
}
}
}
oratypes.h
==========
/* /v71/d2/713/oracore/public/sx.h */
/*
ORACLE, Copyright (c) 1982, 1983, 1986, 1990 ORACLE Corporation
ORACLE Utilities, Copyright (c) 1981, 1982, 1983, 1986, 1990, 1991 ORACLE Corp
Restricted Rights
This program is an unpublished work under the Copyright Act of the
United States and is subject to the terms and conditions stated in
your license agreement with ORACORP including retrictions on
use, duplication, and disclosure.
Certain uncopyrighted ideas and concepts are also contained herein.
These are trade secrets of ORACORP and cannot be used except in
accordance with the written permission of ORACLE Corporation.
*/
/* $Header: sx.h 7.18 94/04/05 18:34:34 tswang Osd
#ifndef ORASTDDEF
# include
# define ORASTDDEF
#endif
#ifndef ORALIMITS
# include
# define ORALIMITS
#endif
#ifndef SX_ORACLE
#define SX_ORACLE
#define SX
#define ORATYPE
#ifndef TRUE
# define TRUE 1
# define FALSE 0
#endif
#ifdef lint
# ifndef mips
# define signed
# endif
#endif
#ifdef ENCORE_88K
# ifndef signed
# define signed
# endif
#endif
#ifdef SYSV_386
# ifndef signed
# define signed
# endif
#endif
#ifndef lint
typedef int eword;
typedef unsigned int uword;
typedef signed int sword;
#else
#define eword int
#define uword unsigned int
#define sword signed int
#endif
#define EWORDMAXVAL ((eword) INT_MAX)
#define EWORDMINVAL ((eword) 0)
#define UWORDMAXVAL ((uword)UINT_MAX)
#define UWORDMINVAL ((uword) 0)
#define SWORDMAXVAL ((sword) INT_MAX)
#define SWORDMINVAL ((sword) INT_MIN)
#define MINEWORDMAXVAL ((eword) 32767)
#define MAXEWORDMINVAL ((eword) 0)
#define MINUWORDMAXVAL ((uword) 65535)
#define MAXUWORDMINVAL ((uword) 0)
#define MINSWORDMAXVAL ((sword) 32767)
#define MAXSWORDMINVAL ((sword) -32767)
#ifndef lint
# ifdef mips
typedef signed char eb1;
# else
typedef char eb1;
# endif
typedef unsigned char ub1;
typedef signed char sb1;
#else
#define eb1 char
#define ub1 unsigned char
#define sb1 signed char
#endif
#define EB1MAXVAL ((eb1)SCHAR_MAX)
#define EB1MINVAL ((eb1) 0)
#if defined(mips)
# ifndef lint
# define UB1MAXVAL (UCHAR_MAX)
# endif
#endif
#ifndef UB1MAXVAL
# ifdef SCO_UNIX
# define UB1MAXVAL (UCHAR_MAX)
# else
# define UB1MAXVAL ((ub1)UCHAR_MAX)
# endif
#endif
#define UB1MINVAL ((ub1) 0)
#define SB1MAXVAL ((sb1)SCHAR_MAX)
#define SB1MINVAL ((sb1)SCHAR_MIN)
#define MINEB1MAXVAL ((eb1) 127)
#define MAXEB1MINVAL ((eb1) 0)
#define MINUB1MAXVAL ((ub1) 255)
#define MAXUB1MINVAL ((ub1) 0)
#define MINSB1MAXVAL ((sb1) 127)
#define MAXSB1MINVAL ((sb1) -127)
#define UB1BITS CHAR_BIT
#define UB1MASK 0xff
typedef unsigned char text;
#ifndef lint
typedef short eb2;
typedef unsigned short ub2;
typedef signed short sb2;
#else
#define eb2 short
#define ub2 unsigned short
#define sb2 signed short
#endif
#define EB2MAXVAL ((eb2) SHRT_MAX)
#define EB2MINVAL ((eb2) 0)
#define UB2MAXVAL ((ub2)USHRT_MAX)
#define UB2MINVAL ((ub2) 0)
#define SB2MAXVAL ((sb2) SHRT_MAX)
#define SB2MINVAL ((sb2) SHRT_MIN)
#define MINEB2MAXVAL ((eb2) 32767)
#define MAXEB2MINVAL ((eb2) 0)
#define MINUB2MAXVAL ((ub2) 65535)
#define MAXUB2MINVAL ((ub2) 0)
#define MINSB2MAXVAL ((sb2) 32767)
#define MAXSB2MINVAL ((sb2)-32767)
#ifndef lint
typedef long eb4;
typedef unsigned long ub4;
typedef signed long sb4;
#else
#define eb4 long
#define ub4 unsigned long
#define sb4 signed long
#endif
#define EB4MAXVAL ((eb4) LONG_MAX)
#define EB4MINVAL ((eb4) 0)
#define UB4MAXVAL ((ub4)ULONG_MAX)
#define UB4MINVAL ((ub4) 0)
#define SB4MAXVAL ((sb4) LONG_MAX)
#define SB4MINVAL ((sb4) LONG_MIN)
#define MINEB4MAXVAL ((eb4) 2147483647)
#define MAXEB4MINVAL ((eb4) 0)
#define MINUB4MAXVAL ((ub4) 4294967295)
#define MAXUB4MINVAL ((ub4) 0)
#define MINSB4MAXVAL ((sb4) 2147483647)
#define MAXSB4MINVAL ((sb4)-2147483647)
#ifndef lint
typedef unsigned long ubig_ora;
typedef signed long sbig_ora;
#else
#define ubig_ora unsigned long
#define sbig_ora signed long
#endif
#define UBIG_ORAMAXVAL ((ubig_ora)ULONG_MAX)
#define UBIG_ORAMINVAL ((ubig_ora) 0)
#define SBIG_ORAMAXVAL ((sbig_ora) LONG_MAX)
#define SBIG_ORAMINVAL ((sbig_ora) LONG_MIN)
#define MINUBIG_ORAMAXVAL ((ubig_ora) 4294967295)
#define MAXUBIG_ORAMINVAL ((ubig_ora) 0)
#define MINSBIG_ORAMAXVAL ((sbig_ora) 2147483647)
#define MAXSBIG_ORAMINVAL ((sbig_ora)-2147483647)
#undef CONST
#ifdef _olint
# define CONST const
#else
#if defined(PMAX) && defined(__STDC__)
# define CONST const
#else
# ifdef M88OPEN
# define CONST const
# else
# ifdef SEQ_PSX_ANSI
# ifdef __STDC__
# define CONST const
# else
# define CONST
# endif
# else
# define CONST
# endif
# endif
#endif
#endif
#ifdef lint
# define dvoid void
#else
# ifdef UTS2
# define dvoid char
# else
# define dvoid void
# endif
#endif
typedef void (*lgenfp_t)(/*_ void _*/);
#include
#define boolean int
#ifdef sparc
# define SIZE_TMAXVAL SB4MAXVAL
#else
# define SIZE_TMAXVAL UB4MAXVAL
#endif
#define MINSIZE_TMAXVAL (size_t)65535
#endif
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/8797129/viewspace-536424/ ,如需转载,请注明出处,否则将追究法律责任。