|
|
/***************************************************************************
Copyright (c) 2002 Microsoft Corporation
Module Name:
locklist.H
Abstract:
Private interface for Smartcard Driver Utility Library
Environment:
Kernel Mode Only
Notes:
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
Copyright (c) 2001 Microsoft Corporation. All Rights Reserved.
Revision History:
05/14/2002 : created
Authors:
Randy Aull
****************************************************************************/
#include "pch.h"
#include "irplist.h"
void LockedList_Init( PLOCKED_LIST LockedList, PKSPIN_LOCK ListLock ) /*++
Routine Description: Initializes a LOCKED_LIST structure
Arguments:
LockedList - Pointer to a LOCKED_LIST structure
ListLock - Pointer to a SPIN_LOCK for the locked list
Return Value:
VOID
--*/ { InitializeListHead(&LockedList->ListHead); KeInitializeSpinLock(&LockedList->SpinLock); LockedList->ListLock = ListLock; LockedList->Count = 0; }
void LockedList_EnqueueHead( PLOCKED_LIST LockedList, PLIST_ENTRY ListEntry ) /*++
Routine Description: Enqueue a List entry at the head of the locked list.
Arguments:
LockedList - Pointer to a LOCKED_LIST structure
ListEntry - Pointer to a LIST_ENTRY structure
Return Value:
VOID
--*/ { KIRQL irql;
LL_LOCK(LockedList, &irql); InsertHeadList(&LockedList->ListHead, ListEntry); LockedList->Count++; LL_UNLOCK(LockedList, irql) ; }
void LockedList_EnqueueTail( PLOCKED_LIST LockedList, PLIST_ENTRY ListEntry ) /*++
Routine Description: Enqueue a List entry at the tail of the locked list.
Arguments:
LockedList - Pointer to a LOCKED_LIST structure
ListEntry - Pointer to a LIST_ENTRY structure
Return Value:
VOID
--*/ { KIRQL irql;
LL_LOCK(LockedList, &irql);
InsertTailList(&LockedList->ListHead, ListEntry); LockedList->Count++; LL_UNLOCK(LockedList, irql) ; }
void LockedList_EnqueueAfter( PLOCKED_LIST LockedList, PLIST_ENTRY Entry, PLIST_ENTRY Location ) /*++
Routine Description: Enqueue a List entry at a specific point in the LockedList.
Arguments:
LockedList - Pointer to a LOCKED_LIST structure
Entry - Pointer to a LIST_ENTRY structure Location - Pointer to a LIST_ENTRY already contained in the LockedList
Return Value:
VOID Notes:
It the Location is NULL, the entry is added to the tail of the list
--*/ { if (Location == NULL) { LL_ADD_TAIL(LockedList, Entry); } else { Entry->Flink = Location->Flink; Location->Flink->Blink = Entry;
Location->Flink = Entry; Entry->Blink = Location;
LockedList->Count++; } }
PLIST_ENTRY LockedList_RemoveHead( PLOCKED_LIST LockedList ) /*++
Routine Description: Remove the head LIST_ENTRY from a LockedList.
Arguments:
LockedList - Pointer to a LOCKED_LIST structure
Return Value:
PLIST_ENTRY - Pointer to the head list of the Locked List NULL - if the Locked List is empty --*/ { PLIST_ENTRY ple; KIRQL irql;
ple = NULL;
LL_LOCK(LockedList, &irql);
if (!IsListEmpty(&LockedList->ListHead)) { ple = RemoveHeadList(&LockedList->ListHead); LockedList->Count--; }
LL_UNLOCK(LockedList, irql);
return ple; }
PLIST_ENTRY LockedList_RemoveEntryLocked( PLOCKED_LIST LockedList, PLIST_ENTRY Entry) /*++
Routine Description: Remove a specific entry from the LockedList. Assumes that the caller has acquired the spinlock
Arguments:
LockedList - Pointer to a LOCKED_LIST structure Entry - Pointer to a LIST_ENTRY structure
Return Value:
PLIST_ENTRY - Pointer to the Entry. --*/ {
ASSERT(!IsListEmpty(&LockedList->ListHead)); ASSERT(LockedList->Count > 0);
RemoveEntryList(Entry); LockedList->Count--;
return Entry; }
PLIST_ENTRY LockedList_RemoveEntry( PLOCKED_LIST LockedList, PLIST_ENTRY Entry ) /*++
Routine Description: Remove a specific entry from the LockedList Arguments:
LockedList - Pointer to a LOCKED_LIST structure Entry - Pointer to a LIST_ENTRY structure
Return Value:
PLIST_ENTRY - Pointer to the Entry. --*/ { PLIST_ENTRY ple; KIRQL irql; LL_LOCK(LockedList, &irql); ple = LockedList_RemoveEntryLocked(LockedList, Entry); LL_UNLOCK(LockedList, irql);
return ple; }
LONG LockedList_GetCount( PLOCKED_LIST LockedList ) /*++
Routine Description: Obtains the number of Entries in the LockedList Arguments:
LockedList - Pointer to a LOCKED_LIST structure
Return Value:
LONG - Number of elements in the LockedList --*/ { LONG count; KIRQL irql;
LL_LOCK(LockedList, &irql); count = LockedList->Count; LL_UNLOCK(LockedList, irql) ;
return count; }
LONG LockedList_Drain( PLOCKED_LIST LockedList, PLIST_ENTRY DrainListHead ) /*++
Routine Description: Drains the elements from the LockedList into the DrainListHead and returns the number of elements Arguments:
LockedList - Pointer to a LOCKED_LIST structure DrainListHead - Pointer to a LIST_ENTRY
Return Value:
LONG - Number of elements drained from LockedList into the DrainListHead --*/ { PLIST_ENTRY ple; LONG count; KIRQL irql;
count = 0;
InitializeListHead(DrainListHead);
LL_LOCK(LockedList, &irql);
while (!IsListEmpty(&LockedList->ListHead)) { ple = RemoveHeadList(&LockedList->ListHead); LockedList->Count--;
InsertTailList(DrainListHead, ple); count++; }
ASSERT(LockedList->Count == 0); ASSERT(IsListEmpty(&LockedList->ListHead));
LL_UNLOCK(LockedList, irql) ;
return count; }
BOOLEAN List_Process( PLIST_ENTRY ListHead, PFNLOCKED_LIST_PROCESS Process, PVOID ProcessContext ) /*++
Routine Description:
Iterate over the list, call the process function for each element. Arguments:
ListHead - Pointer to a LIST_ENTRY Process - Callback function for each element in the list. If the callback returns FALSE we break out of the iteration. ProcessContext - Context for the callback, supplied by the caller
Return Value:
TRUE - Walked over the entire list FALSE - Process function returned FALSE and stopped iteration --*/ { PLIST_ENTRY ple; BOOLEAN result;
//
// We return if we iterated over the entire list.
//
result = TRUE;
for (ple = ListHead->Flink; ple != ListHead; ple = ple->Flink) { //
// If the Process callback wants to stop iterating over the list, then
// it will return FALSE.
//
result = Process(ProcessContext, ple); if (result == FALSE) { break; } }
return result; }
BOOLEAN LockedList_ProcessLocked( PLOCKED_LIST LockedList, PFNLOCKED_LIST_PROCESS Process, PVOID ProcessContext ) /*++
Routine Description:
Iterate over the list, call the process function for each element. Assumes the LockedList spinlock is acquired by the caller Arguments:
LockedList - Pointer to the LOCKED_LIST Process - Callback function for each element in the list. If the callback returns FALSE we break out of the iteration. ProcessContext - Context for the callback, supplied by the caller
Return Value:
TRUE - Walked over the entire list FALSE - Process function returned FALSE and stopped iteration --*/ { return List_Process(&LockedList->ListHead, Process, ProcessContext); }
BOOLEAN LockedList_Process( PLOCKED_LIST LockedList, BOOLEAN LockAtPassive, PFNLOCKED_LIST_PROCESS Process, PVOID ProcessContext ) /*++
Routine Description:
Iterate over the list, call the process function for each element. Arguments:
LockedList - Pointer to the LOCKED_LIST
LockAtPassive - If Process - Callback function for each element in the list. If the callback returns FALSE we break out of the iteration. ProcessContext - Context for the callback, supplied by the caller
Return Value:
TRUE - Walked over the entire list FALSE - Process function returned FALSE and stopped iteration --*/ { KIRQL irql; BOOLEAN result;
if (LockAtPassive) { LL_LOCK(LockedList, &irql); } else { LL_LOCK_AT_DPC(LockedList); }
result = List_Process(&LockedList->ListHead, Process, ProcessContext);
if (LockAtPassive) { LL_UNLOCK(LockedList, irql); } else { LL_UNLOCK_FROM_DPC(LockedList); }
return result; }
|