Source code of Windows XP (NT5)
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
ntos\tdi\isn\fwd\rwlock.h
Abstract: Reader-Writer lock macros
Author:
Vadim Eydelman
Revision History:
--*/
#ifndef _IPXFWD_RWLOCK_
#define _IPXFWD_RWLOCK_
typedef volatile LONG VOLCTR, *PVOLCTR; typedef PVOLCTR RWCOOKIE, *PRWCOOKIE;
// Reader- writer lock.
// Allows no-lock access to the tables for readers - they merely
// increment the counter to record their presence upon entrance
// and decrement the same counter as they leave.
// Writers are supposed to be serialized (externally) and their
// actions are limited to ATOMIC insertions of new elements and
// ATOMIC removals/replacements. The removals/replacements MUST
// be followed by a wait for all potential readers who might still
// be using the element that was removed/replaced
typedef struct _RW_LOCK { KEVENT Event; // Event to release waiting writer
VOLCTR Ctr1; // Two alternating
VOLCTR Ctr2; // reader counters
volatile PVOLCTR CurCtr; // Counter currently in use
} RW_LOCK, *PRW_LOCK;
/*++
******************************************************************* I n i t i a l i z e R W L o c k
Routine Description: Initializes RW lock Arguments: lock - pointer to lock to initialize Return Value: None ******************************************************************* --*/ //VOID
//InitializeRWLock (
// PRW_LOCK lock
// );
#define InitializeRWLock(lock) { \
KeInitializeEvent (&(lock)->Event, \ SynchronizationEvent, \ FALSE); \ (lock)->Ctr1 = (lock)->Ctr2 = 0; \ (lock)->CurCtr = &(lock)->Ctr1; \ }
/*++
******************************************************************* A c q u i r e R e a d e r A c c e s s
Routine Description: Acquires reader access to resource protected by the lock Arguments: lock - pointer to lock cookie - pointer to buffer to store lock state for subsequent release operation Return Value: None ******************************************************************* --*/ //VOID
//AcquireReaderAccess (
// IN PRW_LOCK lock,
// OUT RWCOOKIE cookie
// );
#define AcquireReaderAccess(lock,cookie) \
do { \ register LONG local,local1; \ cookie = (lock)->CurCtr; /*Get current counter pointer*/ \ local = *(cookie); /*Copy counter value*/ \ local1 = local + 1; \ if ((local>=0) /*If counter is valid*/ \ /*and it hasn't changed while*/ \ /*we were checking and trying*/ \ /*to increment it,*/ \ && (InterlockedCompareExchange ( \ (PLONG)(cookie), \ local1, \ local) \ ==local)) \ break; /*then we obtained the access*/ \ } while (1) /*otherwise, we have to do it again (possibly with*/\ /*the other counter if writer switched it on us)*/
/*++
******************************************************************* R e l e a s e R e a d e r A c c e s s
Routine Description: Releases reader access to resource protected by the lock Arguments: lock - pointer to lock cookie - lock state for subsequent stored during acquire operation Return Value: None ******************************************************************* --*/ //VOID
//ReleaseReaderAccess (
// IN PRW_LOCK lock,
// IN RWCOOKIE cookie
// );
#define ReleaseReaderAccess(lock,cookie) { \
/*If counter drops below 0, we have to signal the writer*/ \ if (InterlockedDecrement((PLONG)cookie)<0) { \ LONG res; \ ASSERT (*(cookie)==-1); \ res = KeSetEvent (&(lock)->Event, 0, FALSE); \ ASSERT (res==0); \ } \ }
/*++
******************************************************************* W a i t F o r A l l R e a d e r s
Routine Description: Waits for all readers that were accessing the resource prior to the call to exit (New readers are not included) Arguments: lock - pointer to lock Return Value: None ******************************************************************* --*/ //VOID
//WaitForAllReaders (
// PRW_LOCK lock
// );
#define WaitForAllReaders(lock) { \
RWCOOKIE prevCtr = (lock)->CurCtr; \ /*Switch the counter first*/ \ if (prevCtr==&(lock)->Ctr1) { \ (lock)->Ctr2 = 0; \ (lock)->CurCtr = &(lock)->Ctr2; \ } \ else { \ ASSERT (prevCtr==&(lock)->Ctr2); \ (lock)->Ctr1 = 0; \ (lock)->CurCtr = &(lock)->Ctr1; \ } \ /* If not all readers are gone, we'll have to wait for them*/ \ if (InterlockedDecrement((PLONG)prevCtr)>=0) { \ NTSTATUS status \ = KeWaitForSingleObject ( \ &(lock)->Event, \ Executive, \ ExGetPreviousMode(),\ FALSE, \ 0); \ ASSERT (NT_SUCCESS(status)); \ ASSERT (*prevCtr==-1); \ } \ }
#endif
|