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 =
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+# $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
--- /dev/null
+# $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
--- /dev/null
+/*
+ * 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;
+}
NtSetEvent ZwSetEvent 8
NtSetHighEventPair ZwSetHighEventPair 4
NtSetHighWaitLowEventPair ZwSetHighWaitLowEventPair 4
+NtSetHighWaitLowThread ZwSetHighWaitLowThread 0
NtSetInformationFile ZwSetInformationFile 20
NtSetInformationKey ZwSetInformationKey 16
NtSetInformationObject ZwSetInformationObject 16
NtSetLdtEntries ZwSetLdtEntries 24
NtSetLowEventPair ZwSetLowEventPair 4
NtSetLowWaitHighEventPair ZwSetLowWaitHighEventPair 4
+NtSetLowWaitHighThread ZwSetLowWaitHighThread 0
NtSetSecurityObject ZwSetSecurityObject 12
NtSetSystemEnvironmentValue ZwSetSystemEnvironmentValue 8
NtSetSystemInformation ZwSetSystemInformation 12
-/* $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
* 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
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(
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
-; $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
;
NtSetEvent@8
NtSetHighEventPair@4
NtSetHighWaitLowEventPair@4
+NtSetHighWaitLowThread@0
NtSetInformationFile@20
NtSetInformationKey@16
NtSetInformationObject@16
NtSetLdtEntries@24
NtSetLowEventPair@4
NtSetLowWaitHighEventPair@4
+NtSetLowWaitHighThread@0
NtSetSecurityObject@12
NtSetSystemEnvironmentValue@8
NtSetSystemInformation@12
ZwSetEvent@8
ZwSetHighEventPair@4
ZwSetHighWaitLowEventPair@4
+ZwSetHighWaitLowThread@0
ZwSetInformationFile@20
ZwSetInformationKey@16
ZwSetInformationObject@16
ZwSetLdtEntries@24
ZwSetLowEventPair@4
ZwSetLowWaitHighEventPair@4
+ZwSetLowWaitHighThread@0
ZwSetSecurityObject@12
ZwSetSystemEnvironmentValue@8
ZwSetSystemInformation@12
-; $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
;
NtSetEvent=NtSetEvent@8
NtSetHighEventPair=NtSetHighEventPair@4
NtSetHighWaitLowEventPair=NtSetHighWaitLowEventPair@4
+NtSetHighWaitLowThread=NtSetHighWaitLowThread@0
NtSetInformationFile=NtSetInformationFile@20
NtSetInformationKey=NtSetInformationKey@16
NtSetInformationObject=NtSetInformationObject@16
NtSetLdtEntries=NtSetLdtEntries@24
NtSetLowEventPair=NtSetLowEventPair@4
NtSetLowWaitHighEventPair=NtSetLowWaitHighEventPair@4
+NtSetLowWaitHighThread=NtSetLowWaitHighThread@0
NtSetSecurityObject=NtSetSecurityObject@12
NtSetSystemEnvironmentValue=NtSetSystemEnvironmentValue@8
NtSetSystemInformation=NtSetSystemInformation@12
ZwSetEvent=ZwSetEvent@8
ZwSetHighEventPair=ZwSetHighEventPair@4
ZwSetHighWaitLowEventPair=ZwSetHighWaitLowEventPair@4
+ZwSetHighWaitLowThread=ZwSetHighWaitLowThread@0
ZwSetInformationFile=ZwSetInformationFile@20
ZwSetInformationKey=ZwSetInformationKey@16
ZwSetInformationObject=ZwSetInformationObject@16
ZwSetLdtEntries=ZwSetLdtEntries@24
ZwSetLowEventPair=ZwSetLowEventPair@4
ZwSetLowWaitHighEventPair=ZwSetLowWaitHighEventPair@4
+ZwSetLowWaitHighThread=ZwSetLowWaitHighThread@0
ZwSetSecurityObject=ZwSetSecurityObject@12
ZwSetSystemEnvironmentValue=ZwSetSystemEnvironmentValue@8
ZwSetSystemInformation=ZwSetSystemInformation@12
/* GLOBAL VARIABLES *********************************************************/
TIME_ZONE_INFORMATION SystemTimeZoneInfo;
+extern POBJECT_TYPE ExEventPairObjectType;
+
/* INITIALIZATION FUNCTIONS *************************************************/
VOID
ExpInitLookasideLists(VOID);
+/* OTHER FUNCTIONS **********************************************************/
+
+VOID
+ExpSwapThreadEventPair(
+ IN struct _ETHREAD* Thread,
+ IN struct _KEVENT_PAIR* EventPair
+ );
+
+
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H */
-/* $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
* 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 *******************************************************************/
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
EVENT_PAIR_ALL_ACCESS};
+static KSPIN_LOCK ExThreadEventPairSpinLock;
+
/* FUNCTIONS *****************************************************************/
NTSTATUS STDCALL
ExEventPairObjectType->OkayToClose = NULL;
ExEventPairObjectType->Create = NtpCreateEventPair;
ExEventPairObjectType->DuplicationNotify = NULL;
+
+ KeInitializeSpinLock(&ExThreadEventPairSpinLock);
}
KeSetEvent(&EventPair->HighEvent,
EVENT_INCREMENT,
- FALSE);
+ TRUE);
KeWaitForSingleObject(&EventPair->LowEvent,
WrEventPair,
KeSetEvent(&EventPair->LowEvent,
EVENT_INCREMENT,
- FALSE);
+ TRUE);
ObDereferenceObject(EventPair);
return(STATUS_SUCCESS);
KeSetEvent(&EventPair->LowEvent,
EVENT_INCREMENT,
- FALSE);
+ TRUE);
KeWaitForSingleObject(&EventPair->HighEvent,
WrEventPair,
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 */
-/* $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
* REVISION HISTORY:
* 23/06/98: Created
* 12/10/99: Phillip Susi: Thread priorities, and APC work
+ * 09/08/03: Skywing: ThreadEventPair support (delete)
*/
/*
#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>
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++)
{
-/* $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
* 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>
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))