Fix kernel-mode executive atom implementation (mostly add SEH and tidy up the code...
[reactos.git] / reactos / ntoskrnl / ex / list.c
index a04645c..fd2e678 100644 (file)
-/* $Id: list.c,v 1.3 2001/06/20 19:59:35 ekohl Exp $
+/* $Id$
  *
- * COPYRIGHT:           See COPYING in the top level directory
- * PROJECT:             ReactOS kernel
- * FILE:                ntoskrnl/ex/list.c
- * PURPOSE:             Manages double linked lists, single linked lists and
- *                      sequenced lists
- * PROGRAMMER:          David Welch (welch@mcmail.com)
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ex/list.c
+ * PURPOSE:         Manages double linked lists, single linked lists and
+ *                  sequenced lists
+ *
+ * PROGRAMMERS:     David Welch (welch@mcmail.com)
+ *                  Casper S. Hornstrup (chorns@users.sourceforge.net)
  */
 
 /* INCLUDES *****************************************************************/
 
-#include <ddk/ntddk.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
 /* FUNCTIONS *************************************************************/
 
+/*
+ * @implemented
+ */
+PSLIST_ENTRY
+FASTCALL
+ExInterlockedFlushSList (
+    IN PSLIST_HEADER ListHead
+    )
+{
+    PSLIST_ENTRY Old;
+
+    Old = &ListHead->Next;
+    ListHead->Next.Next = 0;
+
+    return Old;
+}
 
-PLIST_ENTRY STDCALL
-ExInterlockedInsertHeadList (
-       PLIST_ENTRY     ListHead,
-       PLIST_ENTRY     ListEntry,
-       PKSPIN_LOCK     Lock
-       )
+/*
+ * @implemented
+ */
+PLIST_ENTRY
+STDCALL
+ExInterlockedInsertHeadList(PLIST_ENTRY ListHead,
+                           PLIST_ENTRY ListEntry,
+                           PKSPIN_LOCK Lock)
 /*
  * FUNCTION: Inserts an entry at the head of a doubly linked list
  * ARGUMENTS:
- *          ListHead = Points to the head of the list
+ *          ListHead  = Points to the head of the list
  *          ListEntry = Points to the entry to be inserted
- *          Lock = Caller supplied spinlock used to synchronise access
+ *          Lock      = Caller supplied spinlock used to synchronize access
  * RETURNS: The previous head of the list
  */
 {
-   PLIST_ENTRY Old;
-   KIRQL oldlvl;
+  PLIST_ENTRY Old;
+  KIRQL oldlvl;
 
-   KeAcquireSpinLock(Lock,&oldlvl);
-   if (IsListEmpty(ListHead))
-     {
-       Old = NULL;
-     }
-   else
-     {
-       Old = ListHead->Flink;
-     }
-   InsertHeadList(ListHead,ListEntry);
-   KeReleaseSpinLock(Lock,oldlvl);
+  KeAcquireSpinLock(Lock,&oldlvl);
+  if (IsListEmpty(ListHead))
+    {
+      Old = NULL;
+    }
+  else
+    {
+      Old = ListHead->Flink;
+    }
+  InsertHeadList(ListHead,ListEntry);
+  KeReleaseSpinLock(Lock,oldlvl);
 
-   return(Old);
+  return(Old);
 }
 
 
-PLIST_ENTRY STDCALL
-ExInterlockedInsertTailList (
-       PLIST_ENTRY     ListHead,
-       PLIST_ENTRY     ListEntry,
-       PKSPIN_LOCK     Lock
-       )
+/*
+ * @implemented
+ */
+PLIST_ENTRY
+STDCALL
+ExInterlockedInsertTailList(PLIST_ENTRY ListHead,
+                           PLIST_ENTRY ListEntry,
+                           PKSPIN_LOCK Lock)
+/*
+ * FUNCTION: Inserts an entry at the tail of a doubly linked list
+ * ARGUMENTS:
+ *          ListHead  = Points to the head of the list
+ *          ListEntry = Points to the entry to be inserted
+ *          Lock      = Caller supplied spinlock used to synchronize access
+ * RETURNS: The previous head of the list
+ */
 {
-   PLIST_ENTRY Old;
-   KIRQL oldlvl;
+  PLIST_ENTRY Old;
+  KIRQL oldlvl;
 
-   KeAcquireSpinLock(Lock,&oldlvl);
-   if (IsListEmpty(ListHead))
-     {
-       Old = NULL;
-     }
-   else
-     {
-       Old = ListHead->Blink;
-     }
-   InsertTailList(ListHead,ListEntry);
-   KeReleaseSpinLock(Lock,oldlvl);
+  KeAcquireSpinLock(Lock,&oldlvl);
+  if (IsListEmpty(ListHead))
+    {
+      Old = NULL;
+    }
+  else
+    {
+      Old = ListHead->Blink;
+    }
+  InsertTailList(ListHead,ListEntry);
+  KeReleaseSpinLock(Lock,oldlvl);
 
-   return(Old);
+  return(Old);
 }
 
 
-PLIST_ENTRY STDCALL
-ExInterlockedRemoveHeadList (
-       PLIST_ENTRY     Head,
-       PKSPIN_LOCK     Lock
-       )
+/*
+ * @implemented
+ */
+PLIST_ENTRY
+STDCALL
+ExInterlockedRemoveHeadList(PLIST_ENTRY Head,
+                           PKSPIN_LOCK Lock)
 /*
  * FUNCTION: Removes the head of a double linked list
  * ARGUMENTS:
- *          Head = List head
+ *          Head = Points to the head of the list
  *          Lock = Lock for synchronizing access to the list
  * RETURNS: The removed entry
  */
 {
-   PLIST_ENTRY ret;
-   KIRQL oldlvl;
+  PLIST_ENTRY ret;
+  KIRQL oldlvl;
 
-   KeAcquireSpinLock(Lock,&oldlvl);
-   if (IsListEmpty(Head))
-     {
-       ret = NULL;
-     }
-   else
-     {
-       ret = RemoveHeadList(Head);
-     }
-   KeReleaseSpinLock(Lock,oldlvl);
-   return(ret);
+  KeAcquireSpinLock(Lock,&oldlvl);
+  if (IsListEmpty(Head))
+    {
+      ret = NULL;
+    }
+  else
+    {
+      ret = RemoveHeadList(Head);
+    }
+  KeReleaseSpinLock(Lock,oldlvl);
+  return(ret);
 }
 
+
 PLIST_ENTRY
-ExInterlockedRemoveTailList (
-       PLIST_ENTRY     Head,
-       PKSPIN_LOCK     Lock
-       )
+STDCALL
+ExInterlockedRemoveTailList(PLIST_ENTRY Head,
+                           PKSPIN_LOCK Lock)
 /*
  * FUNCTION: Removes the tail of a double linked list
  * ARGUMENTS:
- *          Head = List head
+ *          Head = Points to the head of the list
  *          Lock = Lock for synchronizing access to the list
  * RETURNS: The removed entry
  */
 {
-   PLIST_ENTRY ret;
-   KIRQL oldlvl;
+  PLIST_ENTRY ret;
+  KIRQL oldlvl;
 
-   KeAcquireSpinLock(Lock,&oldlvl);
-   if (IsListEmpty(Head))
-     {
-       ret = NULL;
-     }
-   else
-     {
-       ret = RemoveTailList(Head);
-     }
-   KeReleaseSpinLock(Lock,oldlvl);
-   return(ret);
+  KeAcquireSpinLock(Lock,&oldlvl);
+  if (IsListEmpty(Head))
+    {
+      ret = NULL;
+    }
+  else
+    {
+      ret = RemoveTailList(Head);
+    }
+  KeReleaseSpinLock(Lock,oldlvl);
+  return(ret);
 }
 
 
-PSINGLE_LIST_ENTRY FASTCALL
-ExInterlockedPopEntrySList(PSLIST_HEADER ListHead,
-                          PKSPIN_LOCK Lock)
+#undef ExInterlockedPopEntrySList
+
+/*
+ * @implemented
+ */
+PSINGLE_LIST_ENTRY
+FASTCALL
+ExInterlockedPopEntrySList(IN PSLIST_HEADER ListHead,
+                          IN PKSPIN_LOCK Lock)
+/*
+ * FUNCTION: Removes (pops) an entry from a sequenced list
+ * ARGUMENTS:
+ *          ListHead = Points to the head of the list
+ *          Lock     = Lock for synchronizing access to the list
+ * RETURNS: The removed entry
+ */
 {
-   UNIMPLEMENTED;
+  PSINGLE_LIST_ENTRY ret;
+  KIRQL oldlvl;
+
+  KeAcquireSpinLock(Lock,&oldlvl);
+  ret = PopEntryList(&ListHead->Next);
+  if (ret)
+    {
+      ListHead->Depth--;
+      ListHead->Sequence++;
+    }
+  KeReleaseSpinLock(Lock,oldlvl);
+  return(ret);
 }
 
 
-PSINGLE_LIST_ENTRY FASTCALL
-ExInterlockedPushEntrySList(PSLIST_HEADER ListHead,
-                           PSINGLE_LIST_ENTRY ListEntry,
-                           PKSPIN_LOCK Lock)
+#undef ExInterlockedPushEntrySList
+
+/*
+ * @implemented
+ */
+PSINGLE_LIST_ENTRY
+FASTCALL
+ExInterlockedPushEntrySList(IN PSLIST_HEADER ListHead,
+                           IN PSINGLE_LIST_ENTRY ListEntry,
+                           IN PKSPIN_LOCK Lock)
+/*
+ * FUNCTION: Inserts (pushes) an entry into a sequenced list
+ * ARGUMENTS:
+ *          ListHead  = Points to the head of the list
+ *          ListEntry = Points to the entry to be inserted
+ *          Lock      = Caller supplied spinlock used to synchronize access
+ * RETURNS: The previous head of the list
+ */
 {
-   UNIMPLEMENTED;
+  KIRQL oldlvl;
+  PSINGLE_LIST_ENTRY ret;
+
+  KeAcquireSpinLock(Lock,&oldlvl);
+  ret=ListHead->Next.Next;
+  PushEntryList(&ListHead->Next,ListEntry);
+  ListHead->Depth++;
+  ListHead->Sequence++;
+  KeReleaseSpinLock(Lock,oldlvl);
+  return(ret);
 }
 
 
+/*
+ * @implemented
+ */
 PSINGLE_LIST_ENTRY
 STDCALL
-ExInterlockedPopEntryList (
-       PSINGLE_LIST_ENTRY      ListHead,
-       PKSPIN_LOCK             Lock
-       )
+ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead,
+                         IN PKSPIN_LOCK Lock)
+/*
+ * FUNCTION: Removes (pops) an entry from a singly list
+ * ARGUMENTS:
+ *          ListHead = Points to the head of the list
+ *          Lock     = Lock for synchronizing access to the list
+ * RETURNS: The removed entry
+ */
 {
-   PSINGLE_LIST_ENTRY ret;
-   KIRQL oldlvl;
+  PSINGLE_LIST_ENTRY ret;
+  KIRQL oldlvl;
 
-   KeAcquireSpinLock(Lock,&oldlvl);
-   ret = PopEntryList(ListHead);
-   KeReleaseSpinLock(Lock,oldlvl);
-   return(ret);
+  KeAcquireSpinLock(Lock,&oldlvl);
+  ret = PopEntryList(ListHead);
+  KeReleaseSpinLock(Lock,oldlvl);
+  return(ret);
 }
 
 
+/*
+ * @implemented
+ */
 PSINGLE_LIST_ENTRY
 STDCALL
-ExInterlockedPushEntryList (
-       PSINGLE_LIST_ENTRY      ListHead,
-       PSINGLE_LIST_ENTRY      ListEntry,
-       PKSPIN_LOCK             Lock
-       )
-{
-   KIRQL oldlvl;
-   PSINGLE_LIST_ENTRY ret;
-
-   KeAcquireSpinLock(Lock,&oldlvl);
-   ret=ListHead->Next;
-   PushEntryList(ListHead,ListEntry);
-   KeReleaseSpinLock(Lock,oldlvl);
-   return(ret);
+ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead,
+                          IN PSINGLE_LIST_ENTRY ListEntry,
+                          IN PKSPIN_LOCK Lock)
+/*
+ * FUNCTION: Inserts (pushes) an entry into a singly linked list
+ * ARGUMENTS:
+ *          ListHead  = Points to the head of the list
+ *          ListEntry = Points to the entry to be inserted
+ *          Lock      = Caller supplied spinlock used to synchronize access
+ * RETURNS: The previous head of the list
+ */
+{
+  KIRQL oldlvl;
+  PSINGLE_LIST_ENTRY ret;
+
+  KeAcquireSpinLock(Lock,&oldlvl);
+  ret=ListHead->Next;
+  PushEntryList(ListHead,ListEntry);
+  KeReleaseSpinLock(Lock,oldlvl);
+  return(ret);
+}
+
+
+/*
+ * @implemented
+ */
+PLIST_ENTRY FASTCALL
+ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead,
+                            IN PLIST_ENTRY ListEntry,
+                            IN PKSPIN_LOCK Lock)
+/*
+ * FUNCTION: Inserts an entry at the head of a doubly linked list
+ * ARGUMENTS:
+ *          ListHead  = Points to the head of the list
+ *          ListEntry = Points to the entry to be inserted
+ *          Lock      = Caller supplied spinlock used to synchronize access
+ * RETURNS: The previous head of the list
+ */
+{
+  PLIST_ENTRY Old;
+  KIRQL oldlvl;
+
+  KeAcquireSpinLock(Lock,&oldlvl);
+  if (IsListEmpty(ListHead))
+    {
+      Old = NULL;
+    }
+  else
+    {
+      Old = ListHead->Flink;
+     }
+  InsertHeadList(ListHead,ListEntry);
+  KeReleaseSpinLock(Lock,oldlvl);
+
+  return(Old);
+}
+
+
+/*
+ * @implemented
+ */
+PLIST_ENTRY FASTCALL
+ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead,
+                            IN PLIST_ENTRY ListEntry,
+                            IN PKSPIN_LOCK Lock)
+/*
+ * FUNCTION: Inserts an entry at the tail of a doubly linked list
+ * ARGUMENTS:
+ *          ListHead  = Points to the head of the list
+ *          ListEntry = Points to the entry to be inserted
+ *          Lock      = Caller supplied spinlock used to synchronize access
+ * RETURNS: The previous head of the list
+ */
+{
+  PLIST_ENTRY Old;
+  KIRQL oldlvl;
+
+  KeAcquireSpinLock(Lock,&oldlvl);
+  if (IsListEmpty(ListHead))
+    {
+      Old = NULL;
+    }
+  else
+    {
+      Old = ListHead->Blink;
+    }
+  InsertTailList(ListHead,ListEntry);
+  KeReleaseSpinLock(Lock,oldlvl);
+
+  return(Old);
+}
+
+
+/*
+ * @implemented
+ */
+PSINGLE_LIST_ENTRY FASTCALL
+ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead,
+                          IN PKSPIN_LOCK Lock)
+/*
+ * FUNCTION: Removes (pops) an entry from a singly list
+ * ARGUMENTS:
+ *          ListHead = Points to the head of the list
+ *          Lock     = Lock for synchronizing access to the list
+ * RETURNS: The removed entry
+ */
+{
+  PSINGLE_LIST_ENTRY ret;
+  KIRQL oldlvl;
+
+  KeAcquireSpinLock(Lock,&oldlvl);
+  ret = PopEntryList(ListHead);
+  KeReleaseSpinLock(Lock,oldlvl);
+  return(ret);
+}
+
+
+/*
+ * @implemented
+ */
+PSINGLE_LIST_ENTRY FASTCALL
+ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead,
+                           IN PSINGLE_LIST_ENTRY ListEntry,
+                           IN PKSPIN_LOCK Lock)
+/*
+ * FUNCTION: Inserts (pushes) an entry into a singly linked list
+ * ARGUMENTS:
+ *          ListHead  = Points to the head of the list
+ *          ListEntry = Points to the entry to be inserted
+ *          Lock      = Caller supplied spinlock used to synchronize access
+ * RETURNS: The previous head of the list
+ */
+{
+  KIRQL oldlvl;
+  PSINGLE_LIST_ENTRY ret;
+
+  KeAcquireSpinLock(Lock,&oldlvl);
+  ret=ListHead->Next;
+  PushEntryList(ListHead,ListEntry);
+  KeReleaseSpinLock(Lock,oldlvl);
+  return(ret);
+}
+
+
+/*
+ * @implemented
+ */
+PLIST_ENTRY FASTCALL
+ExfInterlockedRemoveHeadList(IN PLIST_ENTRY Head,
+                            IN PKSPIN_LOCK Lock)
+/*
+ * FUNCTION: Removes the head of a double linked list
+ * ARGUMENTS:
+ *          Head = Points to the head of the list
+ *          Lock = Lock for synchronizing access to the list
+ * RETURNS: The removed entry
+ */
+{
+  PLIST_ENTRY ret;
+  KIRQL oldlvl;
+
+  KeAcquireSpinLock(Lock,&oldlvl);
+  if (IsListEmpty(Head))
+    {
+      ret = NULL;
+    }
+  else
+    {
+      ret = RemoveHeadList(Head);
+    }
+  KeReleaseSpinLock(Lock,oldlvl);
+  return(ret);
+}
+
+
+/*
+ * @implemented
+ */
+PSLIST_ENTRY
+FASTCALL
+InterlockedPopEntrySList(IN PSLIST_HEADER ListHead)
+{
+  SLIST_HEADER newslh, oldslh;
+  PSLIST_ENTRY le;
+
+  do
+  {
+    oldslh = *(volatile SLIST_HEADER *)ListHead;
+    le = oldslh.Next.Next;
+    if(le == NULL)
+    {
+      /* nothing to do */
+      return NULL;
+    }
+    newslh.Sequence = oldslh.Sequence + 1;
+    newslh.Depth = oldslh.Depth - 1;
+    newslh.Next.Next = MmSafeReadPtr(&le->Next);
+  } while(ExfInterlockedCompareExchange64((PLONGLONG)&ListHead->Alignment,
+                                          (PLONGLONG)&newslh.Alignment,
+                                          (PLONGLONG)&oldslh.Alignment) != (LONGLONG)oldslh.Alignment);
+
+  return le;
+}
+
+
+/*
+ * @implemented
+ */
+PSLIST_ENTRY
+FASTCALL
+InterlockedPushEntrySList(IN PSLIST_HEADER ListHead,
+                          IN PSLIST_ENTRY ListEntry)
+{
+  SLIST_HEADER newslh, oldslh;
+
+  newslh.Next.Next = ListEntry;
+
+  do
+  {
+    oldslh = *(volatile SLIST_HEADER *)ListHead;
+    newslh.Depth = oldslh.Depth + 1;
+    newslh.Sequence = oldslh.Sequence + 1;
+    ListEntry->Next = oldslh.Next.Next;
+  } while(ExfInterlockedCompareExchange64((PLONGLONG)&ListHead->Alignment,
+                                          (PLONGLONG)&newslh.Alignment,
+                                          (PLONGLONG)&oldslh.Alignment) != (LONGLONG)oldslh.Alignment);
+
+  return oldslh.Next.Next;
 }
 
 /* EOF */