diff --git a/reactos/include/ddk/iodef.h b/reactos/include/ddk/iodef.h index b7dc36a9cab..59b4c51c9d0 100644 --- a/reactos/include/ddk/iodef.h +++ b/reactos/include/ddk/iodef.h @@ -314,6 +314,7 @@ enum #define IO_SERIAL_INCREMENT 2 #define IO_SOUND_INCREMENT 8 #define IO_VIDEO_INCREMENT 1 +#define MUTANT_INCREMENT 1 #define SEMAPHORE_INCREMENT 1 #define FILE_BYTE_ALIGNMENT 0x00000000 diff --git a/reactos/include/ddk/kefuncs.h b/reactos/include/ddk/kefuncs.h index 266c5187aef..7f6a2736be7 100644 --- a/reactos/include/ddk/kefuncs.h +++ b/reactos/include/ddk/kefuncs.h @@ -266,8 +266,8 @@ LONG STDCALL KeReleaseMutant( IN PKMUTANT Mutant, - ULONG Param2, - ULONG Param3, + IN KPRIORITY Increment, + IN BOOLEAN Abandon, IN BOOLEAN Wait ); diff --git a/reactos/lib/kernel32/synch/wait.c b/reactos/lib/kernel32/synch/wait.c index 7ec2a6d0371..60749a02c34 100644 --- a/reactos/lib/kernel32/synch/wait.c +++ b/reactos/lib/kernel32/synch/wait.c @@ -1,4 +1,4 @@ -/* $Id: wait.c,v 1.14 2001/01/20 12:20:43 ekohl Exp $ +/* $Id: wait.c,v 1.15 2001/11/07 02:17:22 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -16,6 +16,7 @@ #include #include +#define NDEBUG #include /* FUNCTIONS ****************************************************************/ @@ -63,7 +64,7 @@ WaitForSingleObjectEx(HANDLE hHandle, SetLastErrorByStatus (errCode); - return 0xFFFFFFFF; + return(WAIT_FAILED); } @@ -92,6 +93,8 @@ WaitForMultipleObjectsEx(DWORD nCount, LARGE_INTEGER Time; PLARGE_INTEGER TimePtr; + DPRINT("nCount %lu\n", nCount); + if (dwMilliseconds == INFINITE) { TimePtr = NULL; @@ -112,15 +115,18 @@ WaitForMultipleObjectsEx(DWORD nCount, { return WAIT_TIMEOUT; } - else if ((errCode >= WAIT_OBJECT_0) && - (errCode <= WAIT_OBJECT_0 + nCount - 1)) + else if (((errCode >= WAIT_OBJECT_0) && + (errCode <= WAIT_OBJECT_0 + nCount - 1)) || + ((errCode >= WAIT_ABANDONED_0) && + (errCode <= WAIT_ABANDONED_0 + nCount - 1))) { - return errCode; + return(errCode); } + DPRINT("errCode %lx\n", errCode); SetLastErrorByStatus (errCode); - return 0xFFFFFFFF; + return(WAIT_FAILED); } diff --git a/reactos/ntoskrnl/ke/mutex.c b/reactos/ntoskrnl/ke/mutex.c index b2c24cc70e5..81e07278ec9 100644 --- a/reactos/ntoskrnl/ke/mutex.c +++ b/reactos/ntoskrnl/ke/mutex.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: mutex.c,v 1.9 2001/11/04 00:17:24 ekohl Exp $ +/* $Id: mutex.c,v 1.10 2001/11/07 02:14:10 ekohl Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/mutex.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -44,6 +45,8 @@ KeInitializeMutex(IN PKMUTEX Mutex, InternalMutexType, sizeof(KMUTEX) / sizeof(ULONG), 1); + Mutex->MutantListEntry.Flink = NULL; + Mutex->MutantListEntry.Blink = NULL; Mutex->OwnerThread = NULL; Mutex->Abandoned = FALSE; Mutex->ApcDisable = 1; @@ -59,23 +62,31 @@ LONG STDCALL KeReleaseMutex(IN PKMUTEX Mutex, IN BOOLEAN Wait) { - KeAcquireDispatcherDatabaseLock(Wait); - Mutex->Header.SignalState++; - assert(Mutex->Header.SignalState <= 1); - if (Mutex->Header.SignalState == 1) - { - KeDispatcherObjectWake(&Mutex->Header); - } - KeReleaseDispatcherDatabaseLock(Wait); - return(0); + KeAcquireDispatcherDatabaseLock(Wait); + if (Mutex->OwnerThread != KeGetCurrentThread()) + { + DbgPrint("THREAD_NOT_MUTEX_OWNER: Mutex %p\n", Mutex); + KeBugCheck(0); /* THREAD_NOT_MUTEX_OWNER */ + } + Mutex->Header.SignalState++; + assert(Mutex->Header.SignalState <= 1); + if (Mutex->Header.SignalState == 1) + { + Mutex->OwnerThread = NULL; + if (Mutex->MutantListEntry.Flink && Mutex->MutantListEntry.Blink) + RemoveEntryList(&Mutex->MutantListEntry); + KeDispatcherObjectWake(&Mutex->Header); + } + KeReleaseDispatcherDatabaseLock(Wait); + return(0); } NTSTATUS STDCALL -KeWaitForMutexObject(PKMUTEX Mutex, - KWAIT_REASON WaitReason, - KPROCESSOR_MODE WaitMode, - BOOLEAN Alertable, - PLARGE_INTEGER Timeout) +KeWaitForMutexObject(IN PKMUTEX Mutex, + IN KWAIT_REASON WaitReason, + IN KPROCESSOR_MODE WaitMode, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Timeout) { return(KeWaitForSingleObject(Mutex,WaitReason,WaitMode,Alertable,Timeout)); } @@ -85,16 +96,24 @@ VOID STDCALL KeInitializeMutant(IN PKMUTANT Mutant, IN BOOLEAN InitialOwner) { - KeInitializeDispatcherHeader(&Mutant->Header, - InternalMutexType, - sizeof(KMUTANT) / sizeof(ULONG), - 1); if (InitialOwner == TRUE) { + KeInitializeDispatcherHeader(&Mutant->Header, + InternalMutexType, + sizeof(KMUTANT) / sizeof(ULONG), + 0); + InsertTailList(&KeGetCurrentThread()->MutantListHead, + &Mutant->MutantListEntry); Mutant->OwnerThread = KeGetCurrentThread(); } else { + KeInitializeDispatcherHeader(&Mutant->Header, + InternalMutexType, + sizeof(KMUTANT) / sizeof(ULONG), + 1); + Mutant->MutantListEntry.Flink = NULL; + Mutant->MutantListEntry.Blink = NULL; Mutant->OwnerThread = NULL; } Mutant->Abandoned = FALSE; @@ -109,17 +128,40 @@ KeReadStateMutant(IN PKMUTANT Mutant) LONG STDCALL KeReleaseMutant(IN PKMUTANT Mutant, - ULONG Param2, - ULONG Param3, + IN KPRIORITY Increment, + IN BOOLEAN Abandon, IN BOOLEAN Wait) { KeAcquireDispatcherDatabaseLock(Wait); - Mutant->Header.SignalState++; - assert(Mutant->Header.SignalState <= 1); + if (Abandon == FALSE) + { + if (Mutant->OwnerThread != NULL && Mutant->OwnerThread != KeGetCurrentThread()) + { + DbgPrint("THREAD_NOT_MUTEX_OWNER: Mutant->OwnerThread %p CurrentThread %p\n", + Mutant->OwnerThread, + KeGetCurrentThread()); + KeBugCheck(0); /* THREAD_NOT_MUTEX_OWNER */ + } + Mutant->Header.SignalState++; + assert(Mutant->Header.SignalState <= 1); + } + else + { + if (Mutant->OwnerThread != NULL) + { + Mutant->Header.SignalState = 1; + Mutant->Abandoned = TRUE; + } + } + if (Mutant->Header.SignalState == 1) { + Mutant->OwnerThread = NULL; + if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink) + RemoveEntryList(&Mutant->MutantListEntry); KeDispatcherObjectWake(&Mutant->Header); } + KeReleaseDispatcherDatabaseLock(Wait); return(0); } diff --git a/reactos/ntoskrnl/ke/wait.c b/reactos/ntoskrnl/ke/wait.c index dd199a9db4e..3af96c4ed53 100644 --- a/reactos/ntoskrnl/ke/wait.c +++ b/reactos/ntoskrnl/ke/wait.c @@ -125,7 +125,19 @@ VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr, Mutex = CONTAINING_RECORD(hdr, KMUTEX, Header); hdr->SignalState--; assert(hdr->SignalState <= 1); - Mutex->OwnerThread = Thread; + if (hdr->SignalState == 0) + { + if (Thread == NULL) + { + DPRINT1("Thread == NULL!\n") +// KeBugCheck(0); + } + if (Thread != NULL) + InsertTailList(&Thread->MutantListHead, + &Mutex->MutantListEntry); + Mutex->OwnerThread = Thread; + Mutex->Abandoned = FALSE; + } } break; @@ -171,7 +183,7 @@ static BOOLEAN KiIsObjectSignalled(DISPATCHER_HEADER* hdr, } VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus) -{ +{ PKWAIT_BLOCK WaitBlock; BOOLEAN WasWaiting = FALSE; @@ -376,11 +388,12 @@ BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr) } -NTSTATUS STDCALL KeWaitForSingleObject (PVOID Object, - KWAIT_REASON WaitReason, - KPROCESSOR_MODE WaitMode, - BOOLEAN Alertable, - PLARGE_INTEGER Timeout) +NTSTATUS STDCALL +KeWaitForSingleObject(PVOID Object, + KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout) /* * FUNCTION: Puts the current thread into a wait state until the * given dispatcher object is set to signalled @@ -425,13 +438,13 @@ NTSTATUS STDCALL KeWaitForSingleObject (PVOID Object, { KeReleaseDispatcherDatabaseLock(FALSE); return(STATUS_USER_APC); - } + } /* * If the object is signalled */ if (KiIsObjectSignalled(hdr, CurrentThread)) - { + { KeReleaseDispatcherDatabaseLock(FALSE); if (Timeout != NULL) { @@ -445,7 +458,7 @@ NTSTATUS STDCALL KeWaitForSingleObject (PVOID Object, */ if (Timeout != NULL && KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread)) - { + { KeReleaseDispatcherDatabaseLock(FALSE); if (Timeout != NULL) { @@ -459,7 +472,7 @@ NTSTATUS STDCALL KeWaitForSingleObject (PVOID Object, */ CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL; /* Append wait block to the KTHREAD wait block list */ - CurrentThread->WaitBlockList = &CurrentThread->WaitBlock[0]; + CurrentThread->WaitBlockList = &CurrentThread->WaitBlock[0]; CurrentThread->WaitBlock[0].Object = Object; CurrentThread->WaitBlock[0].Thread = CurrentThread; CurrentThread->WaitBlock[0].WaitKey = 0; @@ -500,14 +513,14 @@ NTSTATUS STDCALL KeWaitForSingleObject (PVOID Object, NTSTATUS STDCALL -KeWaitForMultipleObjects (ULONG Count, - PVOID Object[], - WAIT_TYPE WaitType, - KWAIT_REASON WaitReason, - KPROCESSOR_MODE WaitMode, - BOOLEAN Alertable, - PLARGE_INTEGER Timeout, - PKWAIT_BLOCK WaitBlockArray) +KeWaitForMultipleObjects(ULONG Count, + PVOID Object[], + WAIT_TYPE WaitType, + KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout, + PKWAIT_BLOCK WaitBlockArray) { DISPATCHER_HEADER* hdr; PKWAIT_BLOCK blk; @@ -569,7 +582,7 @@ KeWaitForMultipleObjects (ULONG Count, { KeReleaseDispatcherDatabaseLock(FALSE); return(STATUS_USER_APC); - } + } /* * Check if the wait is already satisfied @@ -586,7 +599,7 @@ KeWaitForMultipleObjects (ULONG Count, { KeReleaseDispatcherDatabaseLock(FALSE); DPRINT("One object is already signaled!\n"); - return(STATUS_WAIT_0 + i); + return(STATUS_WAIT_0 + i); } } } @@ -603,7 +616,7 @@ KeWaitForMultipleObjects (ULONG Count, */ if (Timeout != NULL && KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread)) - { + { KeReleaseDispatcherDatabaseLock(FALSE); if (Timeout != NULL) { @@ -654,7 +667,7 @@ KeWaitForMultipleObjects (ULONG Count, CurrentThread->WaitBlock[3].WaitType = WaitAny; CurrentThread->WaitBlock[3].NextWaitBlock = NULL; InsertTailList(&CurrentThread->Timer.Header.WaitListHead, - &CurrentThread->WaitBlock[3].WaitListEntry); + &CurrentThread->WaitBlock[3].WaitListEntry); } PsBlockThread(&Status, Alertable, WaitMode, TRUE, WaitIrql); @@ -664,7 +677,7 @@ KeWaitForMultipleObjects (ULONG Count, { KeCancelTimer(&KeGetCurrentThread()->Timer); } - if (Status == (STATUS_WAIT_63 + 1)) + if (Status == (STATUS_WAIT_0 + Count)) { Status = STATUS_TIMEOUT; } @@ -677,21 +690,22 @@ VOID KeInitializeDispatcher(VOID) KeInitializeSpinLock(&DispatcherDatabaseLock); } -NTSTATUS STDCALL NtWaitForMultipleObjects(IN ULONG Count, - IN HANDLE Object [], - IN CINT WaitType, - IN BOOLEAN Alertable, - IN PLARGE_INTEGER Time) +NTSTATUS STDCALL +NtWaitForMultipleObjects(IN ULONG Count, + IN HANDLE Object [], + IN CINT WaitType, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Time) { - KWAIT_BLOCK WaitBlockArray[EX_MAXIMUM_WAIT_OBJECTS]; - PVOID ObjectPtrArray[EX_MAXIMUM_WAIT_OBJECTS]; + KWAIT_BLOCK WaitBlockArray[EX_MAXIMUM_WAIT_OBJECTS]; + PVOID ObjectPtrArray[EX_MAXIMUM_WAIT_OBJECTS]; NTSTATUS Status; ULONG i, j; DPRINT("NtWaitForMultipleObjects(Count %lu Object[] %x, Alertable %d, " "Time %x)\n", Count,Object,Alertable,Time); - if (Count > EX_MAXIMUM_WAIT_OBJECTS) + if (Count > EX_MAXIMUM_WAIT_OBJECTS) return STATUS_UNSUCCESSFUL; /* reference all objects */ @@ -734,9 +748,10 @@ NTSTATUS STDCALL NtWaitForMultipleObjects(IN ULONG Count, } -NTSTATUS STDCALL NtWaitForSingleObject (IN HANDLE Object, - IN BOOLEAN Alertable, - IN PLARGE_INTEGER Time) +NTSTATUS STDCALL +NtWaitForSingleObject(IN HANDLE Object, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Time) { PVOID ObjectPtr; NTSTATUS Status; diff --git a/reactos/ntoskrnl/nt/mutant.c b/reactos/ntoskrnl/nt/mutant.c index a0726377be8..8661483fb12 100644 --- a/reactos/ntoskrnl/nt/mutant.c +++ b/reactos/ntoskrnl/nt/mutant.c @@ -33,6 +33,7 @@ #include #include +#define NDEBUG #include POBJECT_TYPE ExMutantObjectType = NULL; @@ -52,7 +53,7 @@ NtpCreateMutant(PVOID ObjectBody, PWSTR RemainingPath, POBJECT_ATTRIBUTES ObjectAttributes) { - DPRINT("NtpCreateEvent(ObjectBody %x, Parent %x, RemainingPath %S)\n", + DPRINT("NtpCreateMutant(ObjectBody %x, Parent %x, RemainingPath %S)\n", ObjectBody, Parent, RemainingPath); if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) @@ -71,9 +72,11 @@ NtpCreateMutant(PVOID ObjectBody, VOID STDCALL NtpDeleteMutant(PVOID ObjectBody) { + DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody); + KeReleaseMutant((PKMUTANT)ObjectBody, - 0, - 0, + MUTANT_INCREMENT, + TRUE, FALSE); } @@ -139,7 +142,7 @@ NtOpenMutant(OUT PHANDLE MutantHandle, return(ObOpenObjectByName(ObjectAttributes, ExMutantObjectType, NULL, - UserMode, + ExGetPreviousMode(), DesiredAccess, NULL, MutantHandle)); @@ -168,7 +171,7 @@ NtQueryMutant(IN HANDLE MutantHandle, Status = ObReferenceObjectByHandle(MutantHandle, MUTANT_QUERY_STATE, ExMutantObjectType, - UserMode, + ExGetPreviousMode(), (PVOID*)&Mutant, NULL); if (!NT_SUCCESS(Status)) @@ -197,7 +200,7 @@ NtReleaseMutant(IN HANDLE MutantHandle, Status = ObReferenceObjectByHandle(MutantHandle, MUTANT_ALL_ACCESS, ExMutantObjectType, - UserMode, + ExGetPreviousMode(), (PVOID*)&Mutant, NULL); if (!NT_SUCCESS(Status)) @@ -206,7 +209,7 @@ NtReleaseMutant(IN HANDLE MutantHandle, } Count = KeReleaseMutant(Mutant, - 0, + MUTANT_INCREMENT, 0, FALSE); ObDereferenceObject(Mutant); diff --git a/reactos/ntoskrnl/ps/kill.c b/reactos/ntoskrnl/ps/kill.c index 478919e3f98..9da83a2e140 100644 --- a/reactos/ntoskrnl/ps/kill.c +++ b/reactos/ntoskrnl/ps/kill.c @@ -1,4 +1,4 @@ -/* $Id: kill.c,v 1.47 2001/08/27 01:22:21 ekohl Exp $ +/* $Id: kill.c,v 1.48 2001/11/07 02:16:25 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -129,6 +129,9 @@ PsTerminateCurrentThread(NTSTATUS ExitStatus) { KIRQL oldIrql; PETHREAD CurrentThread; + PKTHREAD Thread; + PLIST_ENTRY current_entry; + PKMUTANT Mutant; CurrentThread = PsGetCurrentThread(); @@ -136,7 +139,22 @@ PsTerminateCurrentThread(NTSTATUS ExitStatus) KeAcquireSpinLock(&PiThreadListLock, &oldIrql); CurrentThread->ExitStatus = ExitStatus; - KeCancelTimer(&KeGetCurrentThread()->Timer); + Thread = KeGetCurrentThread(); + KeCancelTimer(&Thread->Timer); + + /* abandon all owned mutants */ + current_entry = Thread->MutantListHead.Flink; + while (current_entry != &Thread->MutantListHead) + { + Mutant = CONTAINING_RECORD(current_entry, KMUTANT, + MutantListEntry); + KeReleaseMutant(Mutant, + MUTANT_INCREMENT, + TRUE, + FALSE); + current_entry = Thread->MutantListHead.Flink; + } + KeAcquireDispatcherDatabaseLock(FALSE); CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE; KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader);