branch update for HEAD-2003091401
[reactos.git] / ntoskrnl / nt / evtpair.c
index d320bfb..04c02fd 100644 (file)
@@ -7,17 +7,31 @@
  * PROGRAMMER:      David Welch (welch@mcmail.com)
  * UPDATE HISTORY:
  *                  Created 22/05/98
+ *                  Updated 09/08/2003 by Skywing (skywing@valhallalegends.com)
+ *                   to correctly maintain ownership of the dispatcher lock
+ *                   between KeSetEvent and KeWaitForSingleObject calls.
+ *                   Additionally, implemented the thread-eventpair routines.
  */
 
 /* INCLUDES *****************************************************************/
 
-#include <ddk/ntddk.h>
+#define NTOS_MODE_KERNEL
+#include <ntos.h>
 #include <ntos/synch.h>
+#include <internal/ps.h>
 #include <limits.h>
 
 #define NDEBUG
 #include <internal/debug.h>
 
+#ifndef NTSYSAPI
+#define NTSYSAPI
+#endif
+
+#ifndef NTAPI
+#define NTAPI STDCALL
+#endif
+
 
 /* GLOBALS *******************************************************************/
 
@@ -29,6 +43,8 @@ static GENERIC_MAPPING ExEventPairMapping = {
        STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
        EVENT_PAIR_ALL_ACCESS};
 
+static KSPIN_LOCK ExThreadEventPairSpinLock;
+
 /* FUNCTIONS *****************************************************************/
 
 NTSTATUS STDCALL
@@ -71,6 +87,8 @@ VOID NtInitializeEventPairImplementation(VOID)
    ExEventPairObjectType->OkayToClose = NULL;
    ExEventPairObjectType->Create = NtpCreateEventPair;
    ExEventPairObjectType->DuplicationNotify = NULL;
+
+   KeInitializeSpinLock(&ExThreadEventPairSpinLock);
 }
 
 
@@ -83,7 +101,7 @@ NtCreateEventPair(OUT PHANDLE EventPairHandle,
    NTSTATUS Status;
 
    DPRINT("NtCreateEventPair()\n");
-   Status = ObCreateObject(EventPairHandle,
+   Status = ObRosCreateObject(EventPairHandle,
                           DesiredAccess,
                           ObjectAttributes,
                           ExEventPairObjectType,
@@ -171,7 +189,7 @@ NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle)
 
    KeSetEvent(&EventPair->HighEvent,
              EVENT_INCREMENT,
-             FALSE);
+             TRUE);
 
    KeWaitForSingleObject(&EventPair->LowEvent,
                         WrEventPair,
@@ -231,7 +249,7 @@ NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle)
 
    KeSetEvent(&EventPair->LowEvent,
              EVENT_INCREMENT,
-             FALSE);
+             TRUE);
 
    KeWaitForSingleObject(&EventPair->HighEvent,
                         WrEventPair,
@@ -301,4 +319,139 @@ NtWaitHighEventPair(IN HANDLE EventPairHandle)
    return(STATUS_SUCCESS);
 }
 
+/*
+ * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
+ * Note that the eventpair spinlock must be acquired when setting the thread
+ * eventpair via NtSetInformationThread.
+ * @implemented
+ */
+NTSYSAPI
+NTSTATUS
+NTAPI
+NtSetLowWaitHighThread(
+       VOID
+       )
+{
+       PETHREAD Thread;
+       PKEVENT_PAIR EventPair;
+       NTSTATUS Status;
+       KIRQL Irql;
+
+       Thread = PsGetCurrentThread();
+
+       if(!Thread->EventPair)
+               return STATUS_NO_EVENT_PAIR;
+
+       KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
+
+       EventPair = Thread->EventPair;
+
+       if(EventPair)
+               ObReferenceObjectByPointer(EventPair,
+                                          EVENT_PAIR_ALL_ACCESS,
+                                          ExEventPairObjectType,
+                                          UserMode);
+       
+       KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
+
+       if(EventPair == NULL)
+               return STATUS_NO_EVENT_PAIR;
+
+       KeSetEvent(&EventPair->LowEvent,
+               EVENT_INCREMENT,
+               TRUE);
+
+       Status = KeWaitForSingleObject(&EventPair->HighEvent,
+                                      WrEventPair,
+                                      UserMode,
+                                      FALSE,
+                                      NULL);
+
+       ObDereferenceObject(EventPair);
+
+       return Status;
+}
+
+
+/*
+ * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
+ * Note that the eventpair spinlock must be acquired when setting the thread
+ * eventpair via NtSetInformationThread.
+ * @implemented
+ */
+NTSYSAPI
+NTSTATUS
+NTAPI
+NtSetHighWaitLowThread(
+       VOID
+       )
+{
+       PETHREAD Thread;
+       PKEVENT_PAIR EventPair;
+       NTSTATUS Status;
+       KIRQL Irql;
+
+       Thread = PsGetCurrentThread();
+
+       if(!Thread->EventPair)
+               return STATUS_NO_EVENT_PAIR;
+
+       KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
+
+       EventPair = PsGetCurrentThread()->EventPair;
+
+       if(EventPair)
+               ObReferenceObjectByPointer(EventPair,
+                                          EVENT_PAIR_ALL_ACCESS,
+                                          ExEventPairObjectType,
+                                          UserMode);
+       
+       KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
+
+       if(EventPair == NULL)
+               return STATUS_NO_EVENT_PAIR;
+
+       KeSetEvent(&EventPair->HighEvent,
+               EVENT_INCREMENT,
+               TRUE);
+
+       Status = KeWaitForSingleObject(&EventPair->LowEvent,
+                                      WrEventPair,
+                                      UserMode,
+                                      FALSE,
+                                      NULL);
+
+       ObDereferenceObject(EventPair);
+
+       return Status;
+}
+
+/*
+ * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
+ * Note that the eventpair spinlock must be acquired when waiting on the
+ * eventpair via NtSetLow/HighWaitHigh/LowThread.  Additionally, when
+ * deleting a thread object, NtpSwapThreadEventPair(Thread, NULL) should
+ * be called to release any preexisting eventpair object associated with
+ * the thread.  The Microsoft name for this function is not known.
+ */
+VOID
+ExpSwapThreadEventPair(
+       IN PETHREAD Thread,
+       IN PKEVENT_PAIR EventPair
+       )
+{
+       PKEVENT_PAIR OriginalEventPair;
+       KIRQL Irql;
+
+       KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
+
+       OriginalEventPair = Thread->EventPair;
+       Thread->EventPair = EventPair;
+
+       if(OriginalEventPair)
+               ObDereferenceObject(OriginalEventPair);
+
+       KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
+}
+
 /* EOF */