- Fix some small formatting issues.
[reactos.git] / reactos / ntoskrnl / ex / lookas.c
index 1f1fe9d..9958ef8 100644 (file)
@@ -1,15 +1,11 @@
-/* $Id$
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ex/lookas.c
  * PURPOSE:         Lookaside lists
- * PROGRAMMERS:     David Welch (welch@mcmail.com)
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ *                  David Welch (welch@mcmail.com)
  *                  Casper S. Hornstrup (chorns@users.sourceforge.net)
- * TODO:            Use InterlockedXxxEntrySList for binary compatibility
- * UPDATE HISTORY:
- *   22-05-1998 DW  Created
- *   02-07-2001 CSH Implemented lookaside lists
  */
 
 /* INCLUDES *****************************************************************/
 #define NDEBUG
 #include <internal/debug.h>
 
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, ExpInitLookasideLists)
+#endif
+
 /* GLOBALS *******************************************************************/
 
 LIST_ENTRY ExpNonPagedLookasideListHead;
 KSPIN_LOCK ExpNonPagedLookasideListLock;
-
 LIST_ENTRY ExpPagedLookasideListHead;
 KSPIN_LOCK ExpPagedLookasideListLock;
 
-PLOOKASIDE_MINMAX_ROUTINE ExpMinMaxRoutine;
-
-#define LookasideListLock(l)(&(l->Obsoleted))
-
 /* FUNCTIONS *****************************************************************/
 
-static
-inline
-PSINGLE_LIST_ENTRY
- PopEntrySList(
-       PSLIST_HEADER   ListHead
-       )
-{
-       PSINGLE_LIST_ENTRY ListEntry;
-
-       ListEntry = ListHead->Next.Next;
-       if (ListEntry!=NULL)
-       {
-               ListHead->Next.Next = ListEntry->Next;
-    ListHead->Depth++;
-    ListHead->Sequence++;
-  }
-       return ListEntry;
-}
-
-
-static
-inline
 VOID
-PushEntrySList (
-       PSLIST_HEADER   ListHead,
-       PSINGLE_LIST_ENTRY      Entry
-       )
-{
-       Entry->Next = ListHead->Next.Next;
-       ListHead->Next.Next = Entry;
-  ListHead->Depth++;
-  ListHead->Sequence++;
-}
-
-
-VOID ExpDefaultMinMax(
-  POOL_TYPE PoolType,
-  ULONG Size,
-  PUSHORT MinimumDepth,
-  PUSHORT MaximumDepth)
-/*
- * FUNCTION: Determines the minimum and maximum depth of a new lookaside list
- * ARGUMENTS:
- *   Type         = Type of executive pool
- *   Size         = Size in bytes of each element in the new lookaside list
- *   MinimumDepth = Buffer to store minimum depth of the new lookaside list in
- *   MaximumDepth = Buffer to store maximum depth of the new lookaside list in
- */
-{
-  /* FIXME: Could probably do some serious computing here */
-  if ((PoolType == NonPagedPool) ||
-    (PoolType == NonPagedPoolMustSucceed))
-  {
-    *MinimumDepth = 10;
-    *MaximumDepth = 100;
-  }
-  else
-  {
-    *MinimumDepth = 20;
-    *MaximumDepth = 200;
-  }
-}
-
-
-PVOID STDCALL
-ExpDefaultAllocate(POOL_TYPE PoolType,
-                  ULONG NumberOfBytes,
-                  ULONG Tag)
-/*
- * FUNCTION: Default allocate function for lookaside lists
- * ARGUMENTS:
- *   Type          = Type of executive pool
- *   NumberOfBytes = Number of bytes to allocate
- *   Tag           = Tag to use
- * RETURNS:
- *   Pointer to allocated memory, or NULL if there is not enough free resources
- */
+INIT_FUNCTION
+STDCALL
+ExpInitLookasideLists()
 {
-  return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
+    /* Initialize Lock and Listhead */
+    InitializeListHead(&ExpNonPagedLookasideListHead);
+    KeInitializeSpinLock(&ExpNonPagedLookasideListLock);
+    InitializeListHead(&ExpPagedLookasideListHead);
+    KeInitializeSpinLock(&ExpPagedLookasideListLock);
 }
 
-
-VOID STDCALL
-ExpDefaultFree(PVOID Buffer)
 /*
- * FUNCTION: Default free function for lookaside lists
- * ARGUMENTS:
- *   Buffer = Pointer to memory to free
+ * @implemented
  */
-{
-  ExFreePool(Buffer);
-}
-
-
-VOID INIT_FUNCTION
-ExpInitLookasideLists()
-{
-  InitializeListHead(&ExpNonPagedLookasideListHead);
-  KeInitializeSpinLock(&ExpNonPagedLookasideListLock);
-
-  InitializeListHead(&ExpPagedLookasideListHead);
-  KeInitializeSpinLock(&ExpPagedLookasideListLock);
-
-  /* FIXME: Possibly configure the algorithm using the registry */
-  ExpMinMaxRoutine = ExpDefaultMinMax;
-}
-
-
 PVOID
-FASTCALL
-ExiAllocateFromPagedLookasideList (
-       PPAGED_LOOKASIDE_LIST   Lookaside
-       )
+STDCALL
+ExiAllocateFromPagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside)
 {
-  PVOID Entry;
-
-  /* Try to obtain an entry from the lookaside list. If that fails, try to
-     allocate a new entry with the allocate method for the lookaside list */
-
-  Lookaside->TotalAllocates++;
-
-//  ExAcquireFastMutex(LookasideListLock(Lookaside));
-
-  Entry = PopEntrySList(&Lookaside->ListHead);
-
-//  ExReleaseFastMutex(LookasideListLock(Lookaside));
-
-  if (Entry)
+    PVOID Entry;
+
+    Lookaside->L.TotalAllocates++;
+    Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
+    if (!Entry) 
+    {
+        Lookaside->L.AllocateMisses++;
+        Entry = (Lookaside->L.Allocate)(Lookaside->L.Type,
+                                        Lookaside->L.Size, 
+                                        Lookaside->L.Tag);
+    }
     return Entry;
-
-  Lookaside->AllocateMisses++;
-
-  Entry = (*Lookaside->Allocate)(Lookaside->Type,
-    Lookaside->Size,
-    Lookaside->Tag);
-
-  return Entry;
 }
 
-
 /*
  * @implemented
  */
 VOID
 STDCALL
-ExDeleteNPagedLookasideList (
-       PNPAGED_LOOKASIDE_LIST  Lookaside
-       )
+ExiFreeToPagedLookasideList(IN PPAGED_LOOKASIDE_LIST  Lookaside,
+                            IN PVOID  Entry)
 {
-  KIRQL OldIrql;
-  PVOID Entry;
-
-  /* Pop all entries off the stack and release the resources allocated
-     for them */
-  while ((Entry = ExInterlockedPopEntrySList(
-    &Lookaside->ListHead,
-    LookasideListLock(Lookaside))) != NULL)
-  {
-    (*Lookaside->Free)(Entry);
-  }
-
-  KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql);
-  RemoveEntryList(&Lookaside->ListEntry);
-  KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
+    Lookaside->L.TotalFrees++;
+    if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) 
+    {
+        Lookaside->L.FreeMisses++;
+        (Lookaside->L.Free)(Entry);
+    }
+    else
+    {
+        InterlockedPushEntrySList(&Lookaside->L.ListHead, (PSLIST_ENTRY)Entry);
+    }
 }
 
-
 /*
  * @implemented
  */
 VOID
 STDCALL
-ExDeletePagedLookasideList (
-       PPAGED_LOOKASIDE_LIST   Lookaside
-       )
+ExDeleteNPagedLookasideList(PNPAGED_LOOKASIDE_LIST Lookaside)
 {
-  KIRQL OldIrql;
-  PVOID Entry;
-
-  /* Pop all entries off the stack and release the resources allocated
-     for them */
-  for (;;)
-  {
-
-//  ExAcquireFastMutex(LookasideListLock(Lookaside));
-
-    Entry = PopEntrySList(&Lookaside->ListHead);
-    if (!Entry)
-      break;
-
-//  ExReleaseFastMutex(LookasideListLock(Lookaside));
-
-    (*Lookaside->Free)(Entry);
-  }
-
-  KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql);
-  RemoveEntryList(&Lookaside->ListEntry);
-  KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
+    KIRQL OldIrql;
+    PVOID Entry;
+
+    /* Pop all entries off the stack and release the resources allocated
+       for them */
+    for (;;)
+    {
+        Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
+        if (!Entry) break;
+        (*Lookaside->L.Free)(Entry);
+    }
+    
+    /* Remove from list */
+    KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql);
+    RemoveEntryList(&Lookaside->L.ListEntry);
+    KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
 }
 
-
+/*
+ * @implemented
+ */
 VOID
 STDCALL
-ExiFreeToPagedLookasideList (
-       PPAGED_LOOKASIDE_LIST   Lookaside,
-       PVOID                   Entry
-       )
+ExDeletePagedLookasideList(PPAGED_LOOKASIDE_LIST Lookaside)
 {
-       Lookaside->TotalFrees++;
-
-       if (ExQueryDepthSList(&Lookaside->ListHead) >= Lookaside->Depth)
-       {
-               Lookaside->FreeMisses++;
-               (*Lookaside->Free)(Entry);
-       }
-       else
-       {
-//  ExAcquireFastMutex(LookasideListLock(Lookaside));
-    PushEntrySList(&Lookaside->ListHead, (PSINGLE_LIST_ENTRY)Entry);
-//  ExReleaseFastMutex(LookasideListLock(Lookaside));
-       }
+    KIRQL OldIrql;
+    PVOID Entry;
+
+    /* Pop all entries off the stack and release the resources allocated
+       for them */
+    for (;;)
+    {
+        Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
+        if (!Entry) break;
+        (*Lookaside->L.Free)(Entry);
+    }
+    
+    /* Remove from list */
+    KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql);
+    RemoveEntryList(&Lookaside->L.ListEntry);
+    KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
 }
 
-
 /*
  * @implemented
  */
 VOID
 STDCALL
-ExInitializeNPagedLookasideList (
-       PNPAGED_LOOKASIDE_LIST  Lookaside,
-       PALLOCATE_FUNCTION      Allocate,
-       PFREE_FUNCTION          Free,
-       ULONG                   Flags,
-       ULONG                   Size,
-       ULONG                   Tag,
-       USHORT                  Depth)
+ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST Lookaside,
+                                PALLOCATE_FUNCTION Allocate,
+                                PFREE_FUNCTION Free,
+                                ULONG Flags,
+                                ULONG Size,
+                                ULONG Tag,
+                                USHORT Depth)
 {
-  DPRINT("Initializing nonpaged lookaside list at 0x%X\n", Lookaside);
-
-  Lookaside->TotalAllocates = 0;
-  Lookaside->AllocateMisses = 0;
-  Lookaside->TotalFrees = 0;
-  Lookaside->FreeMisses = 0;
-  Lookaside->Type = NonPagedPool;
-  Lookaside->Tag = Tag;
-
-  /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
-     the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
-  if (Size < sizeof(SINGLE_LIST_ENTRY))
-    Lookaside->Size = sizeof(SINGLE_LIST_ENTRY);
-  else
-    Lookaside->Size = Size;
-
-  if (Allocate)
-    Lookaside->Allocate = Allocate;
-  else
-    Lookaside->Allocate = ExpDefaultAllocate;
-
-  if (Free)
-    Lookaside->Free = Free;
-  else
-    Lookaside->Free = ExpDefaultFree;
-
-  ExInitializeSListHead(&Lookaside->ListHead);
-  KeInitializeSpinLock(LookasideListLock(Lookaside));
-
-  /* Determine minimum and maximum number of entries on the lookaside list
-     using the configured algorithm */
-  (*ExpMinMaxRoutine)(
-    NonPagedPool,
-    Lookaside->Size,
-    &Lookaside->Depth,
-    &Lookaside->MaximumDepth);
-
-  ExInterlockedInsertTailList(
-    &ExpNonPagedLookasideListHead,
-    &Lookaside->ListEntry,
-    &ExpNonPagedLookasideListLock);
+    DPRINT("Initializing nonpaged lookaside list at 0x%p\n", Lookaside);
+
+    /* Initialize the Header */
+    ExInitializeSListHead(&Lookaside->L.ListHead);
+    Lookaside->L.TotalAllocates = 0;
+    Lookaside->L.AllocateMisses = 0;
+    Lookaside->L.TotalFrees = 0;
+    Lookaside->L.FreeMisses = 0;
+    Lookaside->L.Type = NonPagedPool | Flags;
+    Lookaside->L.Tag = Tag;
+    Lookaside->L.Size = Size;
+    Lookaside->L.Depth = 4;
+    Lookaside->L.MaximumDepth = 256;
+    Lookaside->L.LastTotalAllocates = 0;
+    Lookaside->L.LastAllocateMisses = 0;
+
+    /* Set the Allocate/Free Routines */
+    if (Allocate)
+    {
+        Lookaside->L.Allocate = Allocate;
+    }
+    else
+    {
+        Lookaside->L.Allocate = ExAllocatePoolWithTag;
+    }
+
+    if (Free)
+    {
+        Lookaside->L.Free = Free;
+    }
+    else
+    {
+        Lookaside->L.Free = ExFreePool;
+    }
+    
+    /* Insert it into the list */
+    ExInterlockedInsertTailList(&ExpNonPagedLookasideListHead,
+                                &Lookaside->L.ListEntry,
+                                &ExpNonPagedLookasideListLock);
 }
 
-
 /*
  * @implemented
  */
 VOID
 STDCALL
-ExInitializePagedLookasideList (
-       PPAGED_LOOKASIDE_LIST   Lookaside,
-       PALLOCATE_FUNCTION      Allocate,
-       PFREE_FUNCTION          Free,
-       ULONG                   Flags,
-       ULONG                   Size,
-       ULONG                   Tag,
-       USHORT                  Depth
-       )
+ExInitializePagedLookasideList (PPAGED_LOOKASIDE_LIST Lookaside,
+                                PALLOCATE_FUNCTION Allocate,
+                                PFREE_FUNCTION Free,
+                                ULONG Flags,
+                                ULONG Size,
+                                ULONG Tag,
+                                USHORT Depth)
 {
-  DPRINT("Initializing paged lookaside list at 0x%X\n", Lookaside);
-
-  Lookaside->TotalAllocates = 0;
-  Lookaside->AllocateMisses = 0;
-  Lookaside->TotalFrees = 0;
-  Lookaside->FreeMisses = 0;
-  Lookaside->Type = PagedPool;
-  Lookaside->Tag = Tag;
-
-  /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
-     the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
-  if (Size < sizeof(SINGLE_LIST_ENTRY))
-    Lookaside->Size = sizeof(SINGLE_LIST_ENTRY);
-  else
-    Lookaside->Size = Size;
-
-  if (Allocate)
-    Lookaside->Allocate = Allocate;
-  else
-    Lookaside->Allocate = ExpDefaultAllocate;
-
-  if (Free)
-    Lookaside->Free = Free;
-  else
-    Lookaside->Free = ExpDefaultFree;
-
-  ExInitializeSListHead(&Lookaside->ListHead);
-  //ExInitializeFastMutex(LookasideListLock(Lookaside));
-
-  /* Determine minimum and maximum number of entries on the lookaside list
-     using the configured algorithm */
-  (*ExpMinMaxRoutine)(
-    PagedPool,
-    Lookaside->Size,
-    &Lookaside->Depth,
-    &Lookaside->MaximumDepth);
-
-  ExInterlockedInsertTailList(
-    &ExpPagedLookasideListHead,
-    &Lookaside->ListEntry,
-    &ExpPagedLookasideListLock);
+    DPRINT("Initializing paged lookaside list at 0x%p\n", Lookaside);
+
+    /* Initialize the Header */
+    ExInitializeSListHead(&Lookaside->L.ListHead);
+    Lookaside->L.TotalAllocates = 0;
+    Lookaside->L.AllocateMisses = 0;
+    Lookaside->L.TotalFrees = 0;
+    Lookaside->L.FreeMisses = 0;
+    Lookaside->L.Type = PagedPool | Flags;
+    Lookaside->L.Tag = Tag;
+    Lookaside->L.Size = Size;
+    Lookaside->L.Depth = 4;
+    Lookaside->L.MaximumDepth = 256;
+    Lookaside->L.LastTotalAllocates = 0;
+    Lookaside->L.LastAllocateMisses = 0;
+
+    /* Set the Allocate/Free Routines */
+    if (Allocate)
+    {
+        Lookaside->L.Allocate = Allocate;
+    }
+    else
+    {
+        Lookaside->L.Allocate = ExAllocatePoolWithTag;
+    }
+
+    if (Free)
+    {
+        Lookaside->L.Free = Free;
+    }
+    else
+    {
+        Lookaside->L.Free = ExFreePool;
+    }
+    
+    /* Insert it into the list */
+    ExInterlockedInsertTailList(&ExpNonPagedLookasideListHead,
+                                &Lookaside->L.ListEntry,
+                                &ExpNonPagedLookasideListLock);
 }
 
 /* EOF */