/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Microsoft Corporation, 1989                                 */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME = LOCK.H
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION = V2.0
 *
 * DATE
 *
 * DESCRIPTION
 *
 *
 * FUNCTIONS
 *
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/


/*
**			       Tagged Locks
**			       ------------
**
**   When semaphore are used, the debugging process involves analyzing
**   semaphore deadlocks.  While Fast, Safe, Ram semaphores record the
**   pid and tid of the owning thread, they don't record the code location
**   (CS:IP) at which the semaphores were procured.  Tagged locks are
**   an extension to FSRSem's which do record that information.
**
**   To allow for nested uses of a tagged lock by different functions a
**   chain of code reference structures (CodeRef) is maintained for each
**   tagged lock.  That chain is maintained by a set of declaration and
**   use conventions.  For example in the function Foo with locks tlAlpha
**   and tlBeta:
**
**	 ... Foo(...)
**	 {
**	     ... Foo's Local Declarations ...
**
**	     UsesTaggedLock(crAlpha);
**	     UsesTaggedLock(crBeta );
**
**	     ... Code which does not assumes that any locks are held ...
**
**	     ProcureTaggedLock(tlBeta, crBeta);
**
**	     ... Code that assumes Beta is locked ...
**
**	     ProcureTaggedLock(tlAlpha, crAlpha);
**
**	     ... Code that assumes both Beta and Alpha are locked ...
**
**	     ReleaseTaggedLock(tlAlpha);
**
**	     ... Code that assumes Beta is locked ...
**
**	      ReleaseTaggedLock(tlBeta);
**
**	      ... Code which does not assumes that any locks are held ...
**
**	 }
**
**   Note that when tagged locks are used in a function environment, you
**   must append a line of the form:
**
**	     UseTaggedLock(crGamma);
**
**   to the functions declaration header.  This defines a code reference
**   variable that will be used to maintain the reference chain for the
**   lock tlGamma.  Thereafter you may acquire and release the lock Gamma
**   with:
**
**	 ProcureTaggedLock(tlGamma, crGamma);
**   and
**	 ReleaseTaggedLock(tlGamma);
**
**   Assumptions
**   -----------
**   Because the code reference chains are maintained in the stack frames
**   of the client functions, the following coding style rules are assumed
**   and enforced by firewall code:
**
**     --  Within a single function invocation a particular lock is never
**	   procured twice without an intervening release.
**
**     --  If a lock is procured in a function invocation, it will be
**	   released before that particular invocation completes.
**
**   Note that recursive procures are allowed provided they occur in different
**   invocation instances.
**
*/

typedef struct _CodeRef {

		    ULONG  ip_WhereLocked;
		    struct _CodeRef *pcrLinkPrev;

		} CodeRef;

typedef CodeRef * PCodeRef;


/*
**  Fast, Safe RAM Semaphore declarations
*/

typedef struct _FSRSEM {  /* fsrs */
    SHORT Length;
    SHORT Padding;
    SHORT ProcID;
    SHORT ThrdID;
    SHORT Usage;
    SHORT Client;
    ULONG  Timeout;
    ULONG  RAMsem;
} FSRSEM;
typedef FSRSEM *PFSRSEM;

#if DEBUG

typedef struct _TaggedSemaphore  {   /*  tsem */

		    FSRSEM  fsrsem;

		    CodeRef crefCurrent;

		} TaggedSemaphore;

#else

typedef struct _TaggedSemaphore  {   /*  tsem */

		    FSRSEM  fsrsem;

		} TaggedSemaphore;

#endif

typedef TaggedSemaphore  *PTaggedSemaphore;


/* XLATEOFF */

#if DEBUG

  extern VOID  _System TaggedSemEnter(PTaggedSemaphore ptsem,
					 PCodeRef	  pcref
					);
  extern VOID  _System TaggedSemLeave(PTaggedSemaphore ptsem);
  extern VOID  _System TaggedSemExit (PTaggedSemaphore ptsem);

  #define    UsesTaggedLock(crName)	CodeRef crName

  #define ProcureTaggedLock(tlName, crName)			       \
			     TaggedSemEnter((PTaggedSemaphore)&tlName, \
					    (PCodeRef)	      &crName  \
					   )

  #define ReleaseTaggedLock(tlName)				       \
			     TaggedSemLeave((PTaggedSemaphore)&tlName)

#else

  extern LONG  _System TaggedSemEnter(PTaggedSemaphore ptsem);
  extern VOID  _System TaggedSemLeave(PTaggedSemaphore ptsem);
  extern VOID  _System TaggedSemExit (PTaggedSemaphore ptsem);

  #define    UsesTaggedLock(crName)				       \
			   TaggedSemEnter(PTaggedSemaphore ptsem)
  #define ProcureTaggedLock(tlName, crName)			       \
			     TaggedSemEnter((PTaggedSemaphore) &tlName)
  #define ReleaseTaggedLock(tlName)				       \
			     TaggedSemLeave((PTaggedSemaphore) &tlName)
#endif


#if DEBUG

  #define TSEM_NOT_OWNED  { { sizeof(FSRSEM), 0, 0, 0, 0, 0, -1L, 0L}, \
			    { 0, 0, 0L }			       \
			  }
#else

  #define TSEM_NOT_OWNED  { sizeof(FSRSEM), 0, 0, 0, 0, 0, -1L, 0L }

#endif
