patch by Skywing: made existing eventpair code more efficient and added support for...
authorVizzini <vizzini@plasmic.com>
Wed, 10 Sep 2003 06:12:22 +0000 (06:12 +0000)
committerVizzini <vizzini@plasmic.com>
Wed, 10 Sep 2003 06:12:22 +0000 (06:12 +0000)
          threads and signaling them that way

svn path=/trunk/; revision=6031

14 files changed:
reactos/apps/tests/Makefile
reactos/apps/tests/eventpair/eventpair.c [new file with mode: 0644]
reactos/apps/tests/eventpair/makefile [new file with mode: 0644]
reactos/apps/tests/threadwait/makefile [new file with mode: 0644]
reactos/apps/tests/threadwait/threadwait.c [new file with mode: 0644]
reactos/iface/native/sysfuncs.lst
reactos/include/ntos/zw.h
reactos/install-unix.sh
reactos/lib/ntdll/def/ntdll.def
reactos/lib/ntdll/def/ntdll.edf
reactos/ntoskrnl/include/internal/ex.h
reactos/ntoskrnl/nt/evtpair.c
reactos/ntoskrnl/ps/create.c
reactos/ntoskrnl/ps/tinfo.c

index c49506e..e9ade74 100644 (file)
@@ -14,7 +14,7 @@ lineclip linetest lock lpc messagebox mktime mstest multiwin \
 mutex nptest patblt pipe primitives pteb regtest sectest sertest \
 shaptest shm statst statst2 stretchblt suspend tcpsvr terminate \
 txtscale thread thread_msg tokentest vmtest winhello wm_erasebkgnd \
-wm_paint
+wm_paint eventpair threadwait
 
 TEST_MISC = 
 
diff --git a/reactos/apps/tests/eventpair/eventpair.c b/reactos/apps/tests/eventpair/eventpair.c
new file mode 100644 (file)
index 0000000..c438421
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Author: Skywing (skywing@valhallalegends.com)
+ * Date: 09/09/2003
+ * Purpose: Test Thread-EventPair functionality.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <ddk/ntddk.h>
+
+#ifndef NTAPI
+#define NTAPI WINAPI
+#endif
+
+HANDLE MakeEventPair()
+{
+       NTSTATUS Status;
+       HANDLE EventPair;
+       OBJECT_ATTRIBUTES Attributes;
+
+       InitializeObjectAttributes(&Attributes, NULL, 0, NULL, NULL);
+       Status = NtCreateEventPair(&EventPair, STANDARD_RIGHTS_ALL, &Attributes);
+       printf("Status %08x creating eventpair\n", Status);
+       return EventPair;
+}
+
+DWORD __stdcall threadfunc(void* eventpair)
+{
+       printf("Thread: Set eventpair status %08x\n", NtSetInformationThread(NtCurrentThread(), ThreadEventPair, &eventpair, sizeof(HANDLE)));
+       Sleep(2500);
+
+       printf("Thread: Setting low and waiting high...\n");
+       printf("Thread: status = %08x\n", NtSetLowWaitHighThread());
+       printf("Thread: status = %08x\n", NtSetHighWaitLowThread());
+       printf("Thread: Terminating...\n");
+       return 0;
+}
+
+int main(int ac, char **av)
+{
+       DWORD id;
+       HANDLE EventPair, Thread;
+
+       printf("Main: NtSetLowWaitHighThread is at %08x\n", NtSetLowWaitHighThread);
+
+       EventPair = MakeEventPair();
+
+       if(!EventPair) {
+               printf("Main: Could not create event pair.\n");
+               return 0;
+       }
+
+       printf("Main: EventPair = %08x\n", EventPair);
+       Thread = CreateThread(0, 0, threadfunc, EventPair, 0, &id);
+       printf("Main: ThreadId for new thread is %08x\n", id);
+       printf("Main: Setting high and waiting low\n");
+       printf("Main: status = %08x\n", NtSetHighWaitLowEventPair(EventPair));
+       Sleep(2500);
+       printf("Main: status = %08x\n", NtSetLowWaitHighEventPair(EventPair));
+       NtClose(EventPair);
+       /* WaitForSingleObject(Thread, INFINITE); FIXME: Waiting on thread handle causes double spinlock acquisition (and subsequent crash) in PsUnblockThread -  ntoskrnl/ps/thread.c */
+       NtClose(Thread);
+       printf("Main: Terminating...\n");
+       return 0;
+}
diff --git a/reactos/apps/tests/eventpair/makefile b/reactos/apps/tests/eventpair/makefile
new file mode 100644 (file)
index 0000000..40c0394
--- /dev/null
@@ -0,0 +1,21 @@
+# $Id: makefile,v 1.1 2003/09/10 06:12:21 vizzini Exp $
+
+PATH_TO_TOP = ../../..
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = eventpair
+
+TARGET_SDKLIBS = ntdll.a
+
+TARGET_OBJECTS = $(TARGET_NAME).o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
diff --git a/reactos/apps/tests/threadwait/makefile b/reactos/apps/tests/threadwait/makefile
new file mode 100644 (file)
index 0000000..398ba46
--- /dev/null
@@ -0,0 +1,21 @@
+# $Id: makefile,v 1.1 2003/09/10 06:12:21 vizzini Exp $
+
+PATH_TO_TOP = ../../..
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = threadwait
+
+TARGET_SDKLIBS = ntdll.a
+
+TARGET_OBJECTS = $(TARGET_NAME).o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
diff --git a/reactos/apps/tests/threadwait/threadwait.c b/reactos/apps/tests/threadwait/threadwait.c
new file mode 100644 (file)
index 0000000..2039119
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Author: Skywing (skywing@valhallalegends.com)
+ * Date: 09/09/2003
+ * Purpose: Probe for PsUnblockThread crash due to double-acquire spin lock.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+
+DWORD __stdcall threadfunc(void* UNREFERENCED)
+{
+       printf("Thread: Initialized\n");
+       Sleep(2500);
+       printf("Thread: Terminating...\n");
+       return 0;
+}
+
+int main(int ac, char **av)
+{
+       DWORD id;
+       HANDLE Thread;
+
+       Thread = CreateThread(0, 0, threadfunc, 0, 0, &id);
+       printf("Main: ThreadId for new thread is %08x\n", id);
+       printf("Main: Waiting on thread...\n");
+       WaitForSingleObject(Thread, INFINITE);
+       printf("Main: OK, somebody fixed the PsUnblockThread spinlock double-acquire crash\n");
+       NtClose(Thread);
+       printf("Main: Terminating...\n");
+       return 0;
+}
index a1a1de9..52e82a3 100644 (file)
@@ -159,6 +159,7 @@ NtSetEaFile                 ZwSetEaFile                       16
 NtSetEvent                     ZwSetEvent                        8           
 NtSetHighEventPair             ZwSetHighEventPair                4           
 NtSetHighWaitLowEventPair      ZwSetHighWaitLowEventPair         4           
+NtSetHighWaitLowThread         ZwSetHighWaitLowThread            0             
 NtSetInformationFile           ZwSetInformationFile              20          
 NtSetInformationKey            ZwSetInformationKey               16          
 NtSetInformationObject         ZwSetInformationObject            16          
@@ -169,6 +170,7 @@ NtSetIntervalProfile                ZwSetIntervalProfile              8
 NtSetLdtEntries                        ZwSetLdtEntries                   24          
 NtSetLowEventPair              ZwSetLowEventPair                 4           
 NtSetLowWaitHighEventPair      ZwSetLowWaitHighEventPair         4           
+NtSetLowWaitHighThread         ZwSetLowWaitHighThread            0
 NtSetSecurityObject            ZwSetSecurityObject               12          
 NtSetSystemEnvironmentValue    ZwSetSystemEnvironmentValue       8           
 NtSetSystemInformation         ZwSetSystemInformation            12          
index 39b72b2..5cb0472 100755 (executable)
@@ -1,5 +1,5 @@
 
-/* $Id: zw.h,v 1.16 2003/09/03 20:14:22 ekohl Exp $
+/* $Id: zw.h,v 1.17 2003/09/10 06:12:21 vizzini Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -12,6 +12,7 @@
  *              04/08/98: Added some documentation (Ariadne)
  *             14/08/98: Added type TIME and change variable type from [1] to [0]
  *              14/09/98: Added for each Nt call a corresponding Zw Call
+ *              09/08/03: Added ThreadEventPair routines
  */
 
 #ifndef __DDK_ZW_H
@@ -3469,6 +3470,41 @@ ZwSetLowWaitHighEventPair(
        HANDLE EventPair
        );
 
+/* NtSetLowWaitHighThread effectively invokes NtSetLowWaitHighEventPair on the
+ * event pair of the thread.
+ */
+NTSTATUS
+STDCALL
+NtSetLowWaitHighThread(
+       VOID
+       );
+/* ZwSetLowWaitHighThread effectively invokes ZwSetLowWaitHighEventPair on the
+ * event pair of the thread.
+ */
+NTSTATUS
+STDCALL
+ZwSetLowWaitHighThread(
+       VOID
+       );
+
+/* NtSetHighWaitLowThread effectively invokes NtSetHighWaitLowEventPair on the
+ * event pair of the thread.
+ */
+NTSTATUS
+STDCALL
+NtSetHighWaitLowThread(
+       VOID
+       );
+
+/* ZwSetHighWaitLowThread effectively invokes ZwSetHighWaitLowEventPair on the
+ * event pair of the thread.
+ */
+NTSTATUS
+STDCALL
+ZwSetHighWaitLowThread(
+       VOID
+       );
+
 NTSTATUS
 STDCALL
 NtSetSecurityObject(
index 502e1e1..ebdc4aa 100755 (executable)
@@ -130,6 +130,8 @@ cp apps/tests/nptest/npclient.exe $ROS_INSTALL_TESTS
 cp apps/tests/atomtest/atomtest.exe $ROS_INSTALL_TESTS
 cp apps/tests/mutex/mutex.exe $ROS_INSTALL/bin
 cp apps/tests/winhello/winhello.exe $ROS_INSTALL/bin
+cp apps/tests/eventpair/eventpair.exe $ROS_INSTALL_TESTS
+cp apps/tests/threadwait/threadwait.exe $ROS_INSTALL_TESTS
 cp apps/tests/multiwin/multiwin.exe $ROS_INSTALL/bin
 cp apps/tests/wm_paint/wm_paint.exe $ROS_INSTALL_TESTS
 cp apps/tests/bitblt/lena.bmp $ROS_INSTALL_TESTS
index 6520734..fe1e2a5 100644 (file)
@@ -1,4 +1,4 @@
-; $Id: ntdll.def,v 1.109 2003/09/08 09:56:56 weiden Exp $
+; $Id: ntdll.def,v 1.110 2003/09/10 06:12:21 vizzini Exp $
 ;
 ; ReactOS Operating System
 ;
@@ -222,6 +222,7 @@ NtSetEaFile@16
 NtSetEvent@8
 NtSetHighEventPair@4
 NtSetHighWaitLowEventPair@4
+NtSetHighWaitLowThread@0
 NtSetInformationFile@20
 NtSetInformationKey@16
 NtSetInformationObject@16
@@ -233,6 +234,7 @@ NtSetIoCompletion@20
 NtSetLdtEntries@24
 NtSetLowEventPair@4
 NtSetLowWaitHighEventPair@4
+NtSetLowWaitHighThread@0
 NtSetSecurityObject@12
 NtSetSystemEnvironmentValue@8
 NtSetSystemInformation@12
@@ -776,6 +778,7 @@ ZwSetEaFile@16
 ZwSetEvent@8
 ZwSetHighEventPair@4
 ZwSetHighWaitLowEventPair@4
+ZwSetHighWaitLowThread@0
 ZwSetInformationFile@20
 ZwSetInformationKey@16
 ZwSetInformationObject@16
@@ -787,6 +790,7 @@ ZwSetIoCompletion@20
 ZwSetLdtEntries@24
 ZwSetLowEventPair@4
 ZwSetLowWaitHighEventPair@4
+ZwSetLowWaitHighThread@0
 ZwSetSecurityObject@12
 ZwSetSystemEnvironmentValue@8
 ZwSetSystemInformation@12
index 4a09607..e0ff8ea 100644 (file)
@@ -1,4 +1,4 @@
-; $Id: ntdll.edf,v 1.99 2003/09/08 09:56:57 weiden Exp $
+; $Id: ntdll.edf,v 1.100 2003/09/10 06:12:21 vizzini Exp $
 ;
 ; ReactOS Operating System
 ;
@@ -222,6 +222,7 @@ NtSetEaFile=NtSetEaFile@16
 NtSetEvent=NtSetEvent@8
 NtSetHighEventPair=NtSetHighEventPair@4
 NtSetHighWaitLowEventPair=NtSetHighWaitLowEventPair@4
+NtSetHighWaitLowThread=NtSetHighWaitLowThread@0
 NtSetInformationFile=NtSetInformationFile@20
 NtSetInformationKey=NtSetInformationKey@16
 NtSetInformationObject=NtSetInformationObject@16
@@ -233,6 +234,7 @@ NtSetIoCompletion=NtSetIoCompletion@20
 NtSetLdtEntries=NtSetLdtEntries@24
 NtSetLowEventPair=NtSetLowEventPair@4
 NtSetLowWaitHighEventPair=NtSetLowWaitHighEventPair@4
+NtSetLowWaitHighThread=NtSetLowWaitHighThread@0
 NtSetSecurityObject=NtSetSecurityObject@12
 NtSetSystemEnvironmentValue=NtSetSystemEnvironmentValue@8
 NtSetSystemInformation=NtSetSystemInformation@12
@@ -776,6 +778,7 @@ ZwSetEaFile=ZwSetEaFile@16
 ZwSetEvent=ZwSetEvent@8
 ZwSetHighEventPair=ZwSetHighEventPair@4
 ZwSetHighWaitLowEventPair=ZwSetHighWaitLowEventPair@4
+ZwSetHighWaitLowThread=ZwSetHighWaitLowThread@0
 ZwSetInformationFile=ZwSetInformationFile@20
 ZwSetInformationKey=ZwSetInformationKey@16
 ZwSetInformationObject=ZwSetInformationObject@16
@@ -787,6 +790,7 @@ ZwSetIoCompletion=ZwSetIoCompletion@20
 ZwSetLdtEntries=ZwSetLdtEntries@24
 ZwSetLowEventPair=ZwSetLowEventPair@4
 ZwSetLowWaitHighEventPair=ZwSetLowWaitHighEventPair@4
+ZwSetLowWaitHighThread=ZwSetLowWaitHighThread@0
 ZwSetSecurityObject=ZwSetSecurityObject@12
 ZwSetSystemEnvironmentValue=ZwSetSystemEnvironmentValue@8
 ZwSetSystemInformation=ZwSetSystemInformation@12
index 908b8db..9e7b8ab 100644 (file)
@@ -90,6 +90,8 @@ typedef VOID (*PLOOKASIDE_MINMAX_ROUTINE)(
 /* GLOBAL VARIABLES *********************************************************/
 
 TIME_ZONE_INFORMATION SystemTimeZoneInfo;
+extern POBJECT_TYPE ExEventPairObjectType;
+
 
 /* INITIALIZATION FUNCTIONS *************************************************/
 
@@ -105,4 +107,13 @@ ExInitializeWorkerThreads(VOID);
 VOID
 ExpInitLookasideLists(VOID);
 
+/* OTHER FUNCTIONS **********************************************************/
+
+VOID
+ExpSwapThreadEventPair(
+       IN struct _ETHREAD* Thread,
+       IN struct _KEVENT_PAIR* EventPair
+       );
+
+
 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H */
index 1e4c714..11ee4c2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: evtpair.c,v 1.14 2003/06/07 12:23:14 chorns Exp $
+/* $Id: evtpair.c,v 1.15 2003/09/10 06:12:21 vizzini Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -7,6 +7,10 @@
  * 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 *****************************************************************/
 #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 *******************************************************************/
 
@@ -30,6 +43,8 @@ static GENERIC_MAPPING ExEventPairMapping = {
        STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
        EVENT_PAIR_ALL_ACCESS};
 
+static KSPIN_LOCK ExThreadEventPairSpinLock;
+
 /* FUNCTIONS *****************************************************************/
 
 NTSTATUS STDCALL
@@ -72,6 +87,8 @@ VOID NtInitializeEventPairImplementation(VOID)
    ExEventPairObjectType->OkayToClose = NULL;
    ExEventPairObjectType->Create = NtpCreateEventPair;
    ExEventPairObjectType->DuplicationNotify = NULL;
+
+   KeInitializeSpinLock(&ExThreadEventPairSpinLock);
 }
 
 
@@ -172,7 +189,7 @@ NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle)
 
    KeSetEvent(&EventPair->HighEvent,
              EVENT_INCREMENT,
-             FALSE);
+             TRUE);
 
    KeWaitForSingleObject(&EventPair->LowEvent,
                         WrEventPair,
@@ -205,7 +222,7 @@ NtSetLowEventPair(IN HANDLE EventPairHandle)
 
    KeSetEvent(&EventPair->LowEvent,
              EVENT_INCREMENT,
-             FALSE);
+             TRUE);
 
    ObDereferenceObject(EventPair);
    return(STATUS_SUCCESS);
@@ -232,7 +249,7 @@ NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle)
 
    KeSetEvent(&EventPair->LowEvent,
              EVENT_INCREMENT,
-             FALSE);
+             TRUE);
 
    KeWaitForSingleObject(&EventPair->HighEvent,
                         WrEventPair,
@@ -302,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 */
index 7ad1706..bade8cc 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: create.c,v 1.64 2003/07/21 21:53:53 royce Exp $
+/* $Id: create.c,v 1.65 2003/09/10 06:12:22 vizzini Exp $
  *
  * COPYRIGHT:              See COPYING in the top level directory
  * PROJECT:                ReactOS kernel
@@ -8,6 +8,7 @@
  * REVISION HISTORY: 
  *               23/06/98: Created
  *               12/10/99: Phillip Susi:  Thread priorities, and APC work
+ *               09/08/03: Skywing:       ThreadEventPair support (delete)
  */
 
 /*
@@ -25,6 +26,7 @@
 #include <internal/ke.h>
 #include <internal/ob.h>
 #include <internal/ps.h>
+#include <internal/ex.h>
 #include <internal/se.h>
 #include <internal/id.h>
 #include <internal/dbg.h>
@@ -310,6 +312,7 @@ PiDeleteThread(PVOID ObjectBody)
   PiNrThreads--;
   RemoveEntryList(&Thread->Tcb.ThreadListEntry);
   KeReleaseSpinLock(&PiThreadListLock, oldIrql);
+  ExpSwapThreadEventPair(Thread, NULL); /* Release the associated eventpair object, if there was one */
 
   for (i = 0; i < NotifyRoutineCount; i++)
   {
index 06e338e..b3de6f5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: tinfo.c,v 1.21 2003/07/11 01:23:15 royce Exp $
+/* $Id: tinfo.c,v 1.22 2003/09/10 06:12:22 vizzini Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -7,12 +7,15 @@
  * PROGRAMMER:      David Welch (welch@mcmail.com)
  * UPDATE HISTORY:
  *                  Created 22/05/98
+ *                  Updated 09/08/2003 by Skywing (skywing@valhallalegends.com)
+ *                   to suppport thread-eventpairs.
  */
 
 /* INCLUDES *****************************************************************/
 
 #include <ddk/ntddk.h>
 #include <internal/ps.h>
+#include <internal/ex.h>
 #include <internal/safe.h>
 
 #include <internal/debug.h>
@@ -106,8 +109,38 @@ NtSetInformationThread(HANDLE              ThreadHandle,
        break;
        
       case ThreadEventPair:
-       Status = STATUS_NOT_IMPLEMENTED;
-       break;
+       {
+         PKEVENT_PAIR EventPair;
+
+         if (ThreadInformationLength != sizeof(HANDLE))
+           {
+             Status = STATUS_INFO_LENGTH_MISMATCH;
+             break;
+           }
+
+         if (ExGetPreviousMode() == UserMode) /* FIXME: Validate this for all infoclasses and system services */
+           {
+             DPRINT("NtSetInformationThread:ThreadEventPair: Checking user pointer %08x...\n", ThreadInformation);
+             ProbeForRead(ThreadInformation, sizeof(HANDLE), sizeof(HANDLE)); /* FIXME: This entire function should be
+              * wrapped in an SEH frame... return (NTSTATUS)GetExceptionCode() on exception */
+           }
+
+         Status = ObReferenceObjectByHandle(*(PHANDLE)ThreadInformation,
+                                            STANDARD_RIGHTS_ALL,
+                                            ExEventPairObjectType,
+                                            ExGetPreviousMode(),
+                                            (PVOID*)&EventPair,
+                                            NULL);
+
+         if (!NT_SUCCESS(Status))
+           {
+             break;
+           }
+
+         ExpSwapThreadEventPair(Thread, EventPair); /* Note that the extra reference is kept intentionally */
+         Status = STATUS_SUCCESS;
+         break;
+       }
        
       case ThreadQuerySetWin32StartAddress:
        if (ThreadInformationLength != sizeof(ULONG))