Leaked source code of windows server 2003
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.
 
 
 
 
 
 

800 lines
15 KiB

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
serialst.cxx
Abstract:
Functions to deal with a serialized list. These are replaced by macros in
the retail version, except for functions no longer inlined due to critsec
wrapper
Contents:
[InitializeSerializedList]
[TerminateSerializedList]
[LockSerializedList]
[UnlockSerializedList]
[InsertAtHeadOfSerializedList]
[InsertAtTailOfSerializedList]
[RemoveFromSerializedList]
[IsSerializedListEmpty]
[HeadOfSerializedList]
[TailOfSerializedList]
[CheckEntryOnSerializedList]
[(CheckEntryOnList)]
SlDequeueHead
SlDequeueTail
IsOnSerializedList
Author:
Richard L Firth (rfirth) 16-Feb-1995
Environment:
Win-32 user level
Revision History:
16-Feb-1995 rfirth
Created
--*/
#include <wininetp.h>
#if INET_DEBUG
//
// manifests
//
#define SERIALIZED_LIST_SIGNATURE 'tslS'
//
// private prototypes
//
PRIVATE
DEBUG_FUNCTION
BOOL
CheckEntryOnList(
IN PLIST_ENTRY List,
IN PLIST_ENTRY Entry,
IN BOOL ExpectedResult
);
//
// data
//
BOOL fCheckEntryOnList = FALSE;
BOOL ReportCheckEntryOnListErrors = FALSE;
//
// functions
//
DEBUG_FUNCTION
BOOL
InitializeSerializedList(
IN LPSERIALIZED_LIST SerializedList
)
/*++
Routine Description:
initializes a serialized list
Arguments:
SerializedList - pointer to SERIALIZED_LIST
Return Value:
None.
--*/
{
INET_ASSERT(SerializedList != NULL);
SerializedList->Signature = SERIALIZED_LIST_SIGNATURE;
SerializedList->LockCount = 0;
INITIALIZE_RESOURCE_INFO(&SerializedList->ResourceInfo);
InitializeListHead(&SerializedList->List);
SerializedList->ElementCount = 0;
return SerializedList->Lock.Init();
}
DEBUG_FUNCTION
VOID
TerminateSerializedList(
IN LPSERIALIZED_LIST SerializedList
)
/*++
Routine Description:
Undoes InitializeSerializeList
Arguments:
SerializedList - pointer to serialized list to terminate
Return Value:
None.
--*/
{
INET_ASSERT(SerializedList != NULL);
INET_ASSERT(SerializedList->Signature == SERIALIZED_LIST_SIGNATURE);
INET_ASSERT(SerializedList->ElementCount == 0);
if (SerializedList->ElementCount != 0) {
DEBUG_PRINT(SERIALST,
ERROR,
("list @ %#x has %d elements, first is %#x\n",
SerializedList,
SerializedList->ElementCount,
SerializedList->List.Flink
));
} else {
INET_ASSERT(IsListEmpty(&SerializedList->List));
}
SerializedList->Lock.FreeLock();
}
DEBUG_FUNCTION
BOOL
LockSerializedList(
IN LPSERIALIZED_LIST SerializedList
)
/*++
Routine Description:
Acquires a serialized list locks
Arguments:
SerializedList - SERIALIZED_LIST to lock
Return Value:
Success if able to acquire a lock.
--*/
{
INET_ASSERT(SerializedList->Signature == SERIALIZED_LIST_SIGNATURE);
INET_ASSERT(SerializedList->LockCount >= 0);
if ((!SerializedList->Lock.IsInitialized() && !SerializedList->Lock.Init()) ||
!SerializedList->Lock.Lock())
{
return FALSE;
}
else
{
if (SerializedList->LockCount != 0)
{
INET_ASSERT(SerializedList->ResourceInfo.Tid == GetCurrentThreadId());
}
}
++SerializedList->LockCount;
SerializedList->ResourceInfo.Tid = GetCurrentThreadId();
return TRUE;
}
DEBUG_FUNCTION
VOID
UnlockSerializedList(
IN LPSERIALIZED_LIST SerializedList
)
/*++
Routine Description:
Releases a serialized list lock
Arguments:
SerializedList - SERIALIZED_LIST to unlock
Return Value:
None.
--*/
{
INET_ASSERT(SerializedList->Signature == SERIALIZED_LIST_SIGNATURE);
INET_ASSERT(SerializedList->ResourceInfo.Tid == GetCurrentThreadId());
INET_ASSERT(SerializedList->LockCount > 0);
--SerializedList->LockCount;
SerializedList->Lock.Unlock();
}
DEBUG_FUNCTION
BOOL
InsertAtHeadOfSerializedList(
IN LPSERIALIZED_LIST SerializedList,
IN PLIST_ENTRY Entry
)
/*++
Routine Description:
Adds an item to the head of a serialized list
Arguments:
SerializedList - SERIALIZED_LIST to update
Entry - thing to update it with
Return Value:
FALSE - only if unable to acquire the lock
--*/
{
INET_ASSERT(Entry != &SerializedList->List);
if (LockSerializedList(SerializedList))
{
if (fCheckEntryOnList)
{
CheckEntryOnList(&SerializedList->List, Entry, FALSE);
}
InsertHeadList(&SerializedList->List, Entry);
++SerializedList->ElementCount;
INET_ASSERT(SerializedList->ElementCount > 0);
UnlockSerializedList(SerializedList);
return TRUE;
}
else
{
return FALSE;
}
}
DEBUG_FUNCTION
BOOL
InsertAtTailOfSerializedList(
IN LPSERIALIZED_LIST SerializedList,
IN PLIST_ENTRY Entry
)
/*++
Routine Description:
Adds an item to the head of a serialized list
Arguments:
SerializedList - SERIALIZED_LIST to update
Entry - thing to update it with
Return Value:
FALSE - only if not enough memory was available to insert an item.
--*/
{
INET_ASSERT(Entry != &SerializedList->List);
if (LockSerializedList(SerializedList))
{
if (fCheckEntryOnList) {
CheckEntryOnList(&SerializedList->List, Entry, FALSE);
}
InsertTailList(&SerializedList->List, Entry);
++SerializedList->ElementCount;
INET_ASSERT(SerializedList->ElementCount > 0);
UnlockSerializedList(SerializedList);
return TRUE;
}
return FALSE;
}
BOOL
DEBUG_FUNCTION
RemoveFromSerializedList(
IN LPSERIALIZED_LIST SerializedList,
IN PLIST_ENTRY Entry
)
/*++
Routine Description:
Removes the entry from a serialized list
Arguments:
SerializedList - SERIALIZED_LIST to remove entry from
Entry - pointer to entry to remove
Return Value:
FALSE if unable sycnhronize access to the list due to low-memory.
--*/
{
INET_ASSERT((Entry->Flink != NULL) && (Entry->Blink != NULL));
if (LockSerializedList(SerializedList))
{
if (fCheckEntryOnList)
{
CheckEntryOnList(&SerializedList->List, Entry, TRUE);
}
INET_ASSERT(SerializedList->ElementCount > 0);
RemoveEntryList(Entry);
--SerializedList->ElementCount;
Entry->Flink = NULL;
Entry->Blink = NULL;
UnlockSerializedList(SerializedList);
return TRUE;
}
else
{
return FALSE;
}
}
DEBUG_FUNCTION
BOOL
IsSerializedListEmpty(
IN LPSERIALIZED_LIST SerializedList
)
/*++
Routine Description:
Checks if a serialized list contains any elements
Arguments:
SerializedList - pointer to list to check
Return Value:
BOOL
--*/
{
// For simplicity, don't worry about returning additional status.
// Due to this always being tied to additional manipulation,
// the lock has already been acquired in all current cases.
if (!LockSerializedList(SerializedList))
return TRUE;
INET_ASSERT(SerializedList->Signature == SERIALIZED_LIST_SIGNATURE);
BOOL empty;
if (IsListEmpty(&SerializedList->List)) {
INET_ASSERT(SerializedList->ElementCount == 0);
empty = TRUE;
} else {
INET_ASSERT(SerializedList->ElementCount != 0);
empty = FALSE;
}
UnlockSerializedList(SerializedList);
return empty;
}
DEBUG_FUNCTION
PLIST_ENTRY
HeadOfSerializedList(
IN LPSERIALIZED_LIST SerializedList
)
/*++
Routine Description:
Returns the element at the tail of the list, without taking the lock
Arguments:
SerializedList - pointer to SERIALIZED_LIST
Return Value:
PLIST_ENTRY
pointer to element at tail of list
--*/
{
INET_ASSERT(SerializedList->Signature == SERIALIZED_LIST_SIGNATURE);
return SerializedList->List.Flink;
}
DEBUG_FUNCTION
PLIST_ENTRY
TailOfSerializedList(
IN LPSERIALIZED_LIST SerializedList
)
/*++
Routine Description:
Returns the element at the tail of the list, without taking the lock
Arguments:
SerializedList - pointer to SERIALIZED_LIST
Return Value:
PLIST_ENTRY
pointer to element at tail of list
--*/
{
INET_ASSERT(SerializedList->Signature == SERIALIZED_LIST_SIGNATURE);
return SerializedList->List.Blink;
}
DEBUG_FUNCTION
BOOL
CheckEntryOnSerializedList(
IN LPSERIALIZED_LIST SerializedList,
IN PLIST_ENTRY Entry,
IN BOOL ExpectedResult
)
/*++
Routine Description:
Checks an entry exists (or doesn't exist) on a list
Arguments:
SerializedList - pointer to serialized list
Entry - pointer to entry
ExpectedResult - TRUE if expected on list, else FALSE
Return Value:
BOOL
TRUE - expected result
FALSE - unexpected result
--*/
{
INET_ASSERT(SerializedList->Signature == SERIALIZED_LIST_SIGNATURE);
if (!LockSerializedList(SerializedList))
return FALSE;
BOOL result;
__try {
result = CheckEntryOnList(&SerializedList->List, Entry, ExpectedResult);
} __except(EXCEPTION_EXECUTE_HANDLER) {
DEBUG_PRINT(SERIALST,
FATAL,
("List @ %#x (%d elements) is bad\n",
SerializedList,
SerializedList->ElementCount
));
result = FALSE;
}
ENDEXCEPT
UnlockSerializedList(SerializedList);
return result;
}
PRIVATE
DEBUG_FUNCTION
BOOL
CheckEntryOnList(
IN PLIST_ENTRY List,
IN PLIST_ENTRY Entry,
IN BOOL ExpectedResult
)
{
BOOLEAN found = FALSE;
PLIST_ENTRY p;
if (!IsListEmpty(List)) {
for (p = List->Flink; p != List; p = p->Flink) {
if (p == Entry) {
found = TRUE;
break;
}
}
}
if (found != ExpectedResult) {
if (ReportCheckEntryOnListErrors) {
LPSTR description;
description = found
? "Entry %#x already on list %#x\n"
: "Entry %#x not found on list %#x\n"
;
DEBUG_PRINT(SERIALST,
ERROR,
(description,
Entry,
List
));
DEBUG_BREAK(SERIALST);
}
return FALSE;
}
return TRUE;
}
#else // else !INET_DEBUG
BOOL
InitializeSerializedList(LPSERIALIZED_LIST pList)
{
InitializeListHead(&(pList)->List);
(pList)->ElementCount = 0;
return (pList->Lock).Init();
}
BOOL
InsertAtHeadOfSerializedList(LPSERIALIZED_LIST list, PLIST_ENTRY entry)
{
if (LockSerializedList(list))
{
InsertHeadList(&(list)->List, entry);
++(list)->ElementCount;
UnlockSerializedList(list);
return TRUE;
}
else
{
return FALSE;
}
}
BOOL
InsertAtTailOfSerializedList(LPSERIALIZED_LIST list, PLIST_ENTRY entry)
{
if (LockSerializedList(list))
{
InsertTailList(&(list)->List, entry);
++(list)->ElementCount;
UnlockSerializedList(list);
return TRUE;
}
else
{
return FALSE;
}
}
BOOL
RemoveFromSerializedList(LPSERIALIZED_LIST list, PLIST_ENTRY entry)
{
if (LockSerializedList(list))
{
RemoveEntryList(entry);
--(list)->ElementCount;
UnlockSerializedList(list);
return TRUE;
}
else
{
return FALSE;
}
}
#endif // INET_DEBUG
//
// functions that are always functions
//
LPVOID
SlDequeueHead(
IN LPSERIALIZED_LIST SerializedList
)
/*++
Routine Description:
Dequeues the element at the head of the queue and returns its address or
NULL if the queue is empty
Arguments:
SerializedList - pointer to SERIALIZED_LIST to dequeue from
Return Value:
LPVOID
--*/
{
LPVOID entry = NULL;
if (!IsSerializedListEmpty(SerializedList)) {
if (LockSerializedList(SerializedList)) {
if (!IsSerializedListEmpty(SerializedList)) {
entry = (LPVOID)HeadOfSerializedList(SerializedList);
if (!RemoveFromSerializedList(SerializedList, (PLIST_ENTRY)entry))
entry = NULL;
}
UnlockSerializedList(SerializedList);
}
}
return entry;
}
LPVOID
SlDequeueTail(
IN LPSERIALIZED_LIST SerializedList
)
/*++
Routine Description:
Dequeues the element at the tail of the queue and returns its address or
NULL if the queue is empty
Arguments:
SerializedList - pointer to SERIALIZED_LIST to dequeue from
Return Value:
LPVOID
--*/
{
LPVOID entry = NULL;
if (!IsSerializedListEmpty(SerializedList)) {
if (LockSerializedList(SerializedList)) {
if (!IsSerializedListEmpty(SerializedList)) {
entry = (LPVOID)TailOfSerializedList(SerializedList);
if (!RemoveFromSerializedList(SerializedList, (PLIST_ENTRY)entry))
entry = NULL;
}
UnlockSerializedList(SerializedList);
}
} else {
entry = NULL;
}
return entry;
}
BOOL
IsOnSerializedList(
IN LPSERIALIZED_LIST SerializedList,
IN PLIST_ENTRY Entry
)
/*++
Routine Description:
Checks if an entry is on a serialized list. Useful to call before
RemoveFromSerializedList() if multiple threads can remove the element
Arguments:
SerializedList - pointer to SERIALIZED_LIST
Entry - pointer to element to check
Return Value:
BOOL
TRUE - Entry is on SerializedList
FALSE - " " not on "
--*/
{
BOOL onList = FALSE;
LPVOID entry;
if (!IsSerializedListEmpty(SerializedList)) {
if (LockSerializedList(SerializedList)) {
if (!IsSerializedListEmpty(SerializedList)) {
for (PLIST_ENTRY entry = HeadOfSerializedList(SerializedList);
entry != (PLIST_ENTRY)SlSelf(SerializedList);
entry = entry->Flink) {
if (entry == Entry) {
onList = TRUE;
break;
}
}
}
UnlockSerializedList(SerializedList);
}
}
return onList;
}