From e9600e4c9cb7b820f73c85b4ea89c8e6be3be19c Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Thu, 20 Jul 2006 17:44:30 +0000 Subject: [PATCH] - Add Pushlock support for GCC (Thanks Thomas!) - Remove a bunch of deprecated crap from ps.h - Get rid of PsLockProcess, PsUnlockProcess. Use the process pushlock instead. - When assigning the job, only acquiring rundown protection is enough. - Use interlocked intrinsics for setting the ExceptionPort instead of locking the entire process object. - Disable locking in ProcessSessionInformation for NtSetInformationProcess. The whole API seems wrong anyway, on my XP machine calling it does not change the session or change any token data. To verify later... svn path=/trunk/; revision=23197 --- reactos/include/ndk/extypes.h | 15 +- reactos/ntoskrnl/include/internal/ex.h | 7 +- reactos/ntoskrnl/include/internal/ps.h | 192 +------------------------ reactos/ntoskrnl/ps/job.c | 4 +- reactos/ntoskrnl/ps/kill.c | 16 ++- reactos/ntoskrnl/ps/process.c | 96 +------------ reactos/ntoskrnl/ps/psmgr.c | 2 +- reactos/ntoskrnl/ps/query.c | 32 ++--- 8 files changed, 50 insertions(+), 314 deletions(-) diff --git a/reactos/include/ndk/extypes.h b/reactos/include/ndk/extypes.h index 20603aa5932..8656815f4fb 100644 --- a/reactos/include/ndk/extypes.h +++ b/reactos/include/ndk/extypes.h @@ -32,6 +32,17 @@ Author: #include #include +// +// GCC compatibility +// +#if defined(__GNUC__) +#define __ALIGNED(n) __attribute__((aligned (n))) +#elif defined(_MSC_VER) +#define __ALIGNED(n) __declspec(align(n)) +#else +#error __ALIGNED not defined for your compiler! +#endif + // // Atom and Language IDs // @@ -411,9 +422,7 @@ typedef struct _EX_PUSH_LOCK // // Executive Pushlock Wait Block // -#ifndef __GNUC__ // WARNING! PUSHLOCKS WILL NOT WORK IN GCC FOR NOW!!! -__declspec(align(16)) -#endif +__ALIGNED(16) typedef struct _EX_PUSH_LOCK_WAIT_BLOCK { union diff --git a/reactos/ntoskrnl/include/internal/ex.h b/reactos/ntoskrnl/include/internal/ex.h index 056543af025..213c31fbcf8 100644 --- a/reactos/ntoskrnl/include/internal/ex.h +++ b/reactos/ntoskrnl/include/internal/ex.h @@ -466,6 +466,7 @@ ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock) if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V)) { /* Someone changed it, use the slow path */ + DbgPrint("%s - Contention!\n", __FUNCTION__); ExfAcquirePushLockExclusive(PushLock); } @@ -500,9 +501,10 @@ ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock) /* Try acquiring the lock */ NewValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC; - if (!InterlockedCompareExchangePointer(PushLock, NewValue.Ptr, 0)) + if (InterlockedCompareExchangePointer(PushLock, NewValue.Ptr, 0)) { /* Someone changed it, use the slow path */ + DbgPrint("%s - Contention!\n", __FUNCTION__); ExfAcquirePushLockShared(PushLock); } @@ -575,6 +577,7 @@ ExReleasePushLockShared(PEX_PUSH_LOCK PushLock) OldValue.Ptr) { /* There are still other people waiting on it */ + DbgPrint("%s - Contention!\n", __FUNCTION__); ExfReleasePushLockShared(PushLock); } } @@ -621,6 +624,7 @@ ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock) if ((OldValue.Waiting) && !(OldValue.Waking)) { /* Wake it up */ + DbgPrint("%s - Contention!\n", __FUNCTION__); ExfTryToWakePushLock(PushLock); } } @@ -672,6 +676,7 @@ ExReleasePushLock(PEX_PUSH_LOCK PushLock) OldValue.Ptr)) { /* We have waiters, use the long path */ + DbgPrint("%s - Contention!\n", __FUNCTION__); ExfReleasePushLock(PushLock); } } diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h index 3cf057a4076..5f0b2d6f7c6 100644 --- a/reactos/ntoskrnl/include/internal/ps.h +++ b/reactos/ntoskrnl/include/internal/ps.h @@ -19,10 +19,6 @@ struct _EJOB; #define PSP_MAX_LOAD_IMAGE_NOTIFY 8 #define PSP_MAX_CREATE_PROCESS_NOTIFY 8 -VOID -NTAPI -PiInitProcessManager(VOID); - VOID NTAPI PspShutdownProcessManager(VOID); @@ -31,6 +27,11 @@ VOID NTAPI PsInitThreadManagment(VOID); +VOID +INIT_FUNCTION +NTAPI +PiInitProcessManager(VOID); + VOID NTAPI PsInitProcessManagment(VOID); @@ -39,80 +40,6 @@ VOID NTAPI PsInitIdleThread(VOID); -VOID -NTAPI -PiTerminateProcessThreads( - PEPROCESS Process, - NTSTATUS ExitStatus -); - -VOID -NTAPI -PsTerminateCurrentThread(NTSTATUS ExitStatus); - -VOID -NTAPI -PsTerminateOtherThread( - PETHREAD Thread, - NTSTATUS ExitStatus -); - -VOID -NTAPI -PsReleaseThread(PETHREAD Thread); - -VOID -NTAPI -PsBeginThread( - PKSTART_ROUTINE StartRoutine, - PVOID StartContext -); - -VOID -NTAPI -PsBeginThreadWithContextInternal(VOID); - -VOID -NTAPI -PiKillMostProcesses(VOID); - -NTSTATUS -STDCALL -PiTerminateProcess( - PEPROCESS Process, - NTSTATUS ExitStatus -); - -VOID -NTAPI -PiInitApcManagement(VOID); - -VOID -STDCALL -PiDeleteThread(PVOID ObjectBody); - -VOID -NTAPI -PsReapThreads(VOID); - -VOID -NTAPI -PsInitializeThreadReaper(VOID); - -VOID -NTAPI -PsQueueThreadReap(PETHREAD Thread); - -NTSTATUS -NTAPI -PsInitializeThread( - PEPROCESS Process, - PETHREAD* ThreadPtr, - POBJECT_ATTRIBUTES ObjectAttributes, - KPROCESSOR_MODE AccessMode, - BOOLEAN First -); - PACCESS_TOKEN STDCALL PsReferenceEffectiveToken( @@ -129,27 +56,6 @@ PsOpenTokenOfProcess( PACCESS_TOKEN* Token ); -VOID -STDCALL -PspTerminateProcessThreads( - PEPROCESS Process, - NTSTATUS ExitStatus -); - -NTSTATUS -NTAPI -PsSuspendThread( - PETHREAD Thread, - PULONG PreviousCount -); - -NTSTATUS -NTAPI -PsResumeThread( - PETHREAD Thread, - PULONG PreviousCount -); - NTSTATUS STDCALL PspAssignPrimaryToken( @@ -198,10 +104,6 @@ PsInitializeIdleOrFirstThread( BOOLEAN First ); -VOID -STDCALL -PiDeleteProcess(PVOID ObjectBody); - VOID STDCALL PspReapRoutine(PVOID Context); @@ -218,68 +120,14 @@ PspTerminateThreadByPointer( BOOLEAN bSelf ); -NTSTATUS -NTAPI -PsUnfreezeOtherThread(PETHREAD Thread); - -VOID -NTAPI -PsFreezeOtherThread(PETHREAD Thread); - -VOID -NTAPI -PsFreezeProcessThreads(PEPROCESS Process); - -VOID -NTAPI -PsUnfreezeProcessThreads(PEPROCESS Process); - -ULONG -NTAPI -PsEnumThreadsByProcess(PEPROCESS Process); - PEPROCESS STDCALL PsGetNextProcess(PEPROCESS OldProcess); -VOID -NTAPI -PsApplicationProcessorInit(VOID); - -VOID -NTAPI -PsPrepareForApplicationProcessorInit(ULONG Id); - VOID STDCALL PsIdleThreadMain(PVOID Context); -VOID -STDCALL -PiSuspendThreadRundownRoutine(PKAPC Apc); - -VOID -STDCALL -PiSuspendThreadKernelRoutine( - PKAPC Apc, - PKNORMAL_ROUTINE* NormalRoutine, - PVOID* NormalContext, - PVOID* SystemArgument1, - PVOID* SystemArguemnt2 -); - -VOID -STDCALL -PiSuspendThreadNormalRoutine( - PVOID NormalContext, - PVOID SystemArgument1, - PVOID SystemArgument2 -); - -VOID -NTAPI -PsInitialiseSuspendImplementation(VOID); - VOID STDCALL PspExitProcess(BOOLEAN LastThread, @@ -293,23 +141,6 @@ VOID STDCALL PspDeleteThread(PVOID ObjectBody); - -NTSTATUS -NTAPI -PsInitWin32Thread(PETHREAD Thread); - -VOID -NTAPI -PsTerminateWin32Process(PEPROCESS Process); - -VOID -NTAPI -PsTerminateWin32Thread(PETHREAD Thread); - -VOID -NTAPI -PsInitialiseW32Call(VOID); - VOID NTAPI INIT_FUNCTION @@ -341,17 +172,6 @@ NTSTATUS STDCALL PspGetSystemDllEntryPoints(VOID); -NTSTATUS -NTAPI -PsLockProcess( - PEPROCESS Process, - BOOLEAN Timeout -); - -VOID -NTAPI -PsUnlockProcess(PEPROCESS Process); - VOID NTAPI PspRemoveProcessFromJob( @@ -391,7 +211,7 @@ extern PEPROCESS PsInitialSystemProcess; extern PEPROCESS PsIdleProcess; extern LIST_ENTRY PsActiveProcessHead; extern KGUARDED_MUTEX PspActiveProcessMutex; -extern LARGE_INTEGER ShortPsLockDelay, PsLockTimeout; +extern LARGE_INTEGER ShortPsLockDelay; extern EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock; extern PHANDLE_TABLE PspCidTable; extern PCREATE_THREAD_NOTIFY_ROUTINE diff --git a/reactos/ntoskrnl/ps/job.c b/reactos/ntoskrnl/ps/job.c index fe53a04962c..f4112b58b86 100644 --- a/reactos/ntoskrnl/ps/job.c +++ b/reactos/ntoskrnl/ps/job.c @@ -169,7 +169,7 @@ NtAssignProcessToJobObject ( /* lock the process so we can safely assign the process. Note that in the meanwhile another thread could have assigned this process to a job! */ - Status = PsLockProcess(Process, FALSE); + ExAcquireRundownProtection(&Process->RundownProtect); if(NT_SUCCESS(Status)) { if(Process->Job == NULL && Process->Session == Job->SessionId) @@ -185,7 +185,7 @@ NtAssignProcessToJobObject ( /* process is already assigned to a job or session id differs! */ Status = STATUS_ACCESS_DENIED; } - PsUnlockProcess(Process); + ExReleaseRundownProtection(&Process->RundownProtect); if(NT_SUCCESS(Status)) { diff --git a/reactos/ntoskrnl/ps/kill.c b/reactos/ntoskrnl/ps/kill.c index e9559c2d9da..5c5fe93d924 100644 --- a/reactos/ntoskrnl/ps/kill.c +++ b/reactos/ntoskrnl/ps/kill.c @@ -296,13 +296,15 @@ PspDeleteThread(IN PVOID ObjectBody) if (Thread->ThreadListEntry.Flink) { /* Lock the thread's process */ - PsLockProcess(Process, FALSE); + KeEnterCriticalRegion(); + ExAcquirePushLockExclusive(&Process->ProcessLock); /* Remove us from the list */ RemoveEntryList(&Thread->ThreadListEntry); /* Release the lock */ - PsUnlockProcess(Process); + ExReleasePushLockExclusive(&Process->ProcessLock); + KeLeaveCriticalRegion(); } /* Dereference the Process */ @@ -385,10 +387,11 @@ PspExitThread(IN NTSTATUS ExitStatus) PspRunCreateThreadNotifyRoutines(Thread, FALSE); /* Lock the Process before we modify its thread entries */ - PsLockProcess(CurrentProcess, FALSE); + KeEnterCriticalRegion(); + ExAcquirePushLockExclusive(&CurrentProcess->ProcessLock); - /* Wake up the thread so we don't deadlock on PsLockProcess */ - KeForceResumeThread(&Thread->Tcb); + /* Wake up the thread so we don't deadlock on lock */ + //KeForceResumeThread(&Thread->Tcb); /* Decrease the active thread count, and check if it's 0 */ if (!(--CurrentProcess->ActiveThreads)) @@ -425,7 +428,8 @@ PspExitThread(IN NTSTATUS ExitStatus) } /* Unlock the Process */ - PsUnlockProcess(CurrentProcess); + ExReleasePushLockExclusive(&CurrentProcess->ProcessLock); + KeLeaveCriticalRegion(); /* Check if the process has a debug port and if this is a user thread */ if ((CurrentProcess->DebugPort) && !(Thread->SystemThread)) diff --git a/reactos/ntoskrnl/ps/process.c b/reactos/ntoskrnl/ps/process.c index 96d905c2165..f201c93ba54 100644 --- a/reactos/ntoskrnl/ps/process.c +++ b/reactos/ntoskrnl/ps/process.c @@ -25,87 +25,7 @@ ULONG PsMinimumWorkingSet, PsMaximumWorkingSet; LIST_ENTRY PsActiveProcessHead; KGUARDED_MUTEX PspActiveProcessMutex; -#if 1 -LARGE_INTEGER ShortPsLockDelay, PsLockTimeout; -#define LockEvent Spare0[0] -#define LockCount Spare0[1] -#define LockOwner Spare0[2] -NTSTATUS -NTAPI -PsLockProcess(PEPROCESS Process, BOOLEAN Timeout) -{ - ULONG Attempts = 0; - PKTHREAD PrevLockOwner; - NTSTATUS Status = STATUS_UNSUCCESSFUL; - PLARGE_INTEGER Delay = (Timeout ? &PsLockTimeout : NULL); - PKTHREAD CallingThread = KeGetCurrentThread(); - - PAGED_CODE(); - - KeEnterCriticalRegion(); - - for(;;) - { - PrevLockOwner = (PKTHREAD)InterlockedCompareExchangePointer( - &Process->LockOwner, CallingThread, NULL); - if(PrevLockOwner == NULL || PrevLockOwner == CallingThread) - { - /* we got the lock or already locked it */ - if(InterlockedIncrementUL(&Process->LockCount) == 1) - { - KeClearEvent(Process->LockEvent); - } - - return STATUS_SUCCESS; - } - else - { - if(++Attempts > 2) - { - Status = KeWaitForSingleObject(Process->LockEvent, - Executive, - KernelMode, - FALSE, - Delay); - if(!NT_SUCCESS(Status) || Status == STATUS_TIMEOUT) - { -#ifndef NDEBUG - if(Status == STATUS_TIMEOUT) - { - DPRINT1("PsLockProcess(0x%x) timed out!\n", Process); - } -#endif - KeLeaveCriticalRegion(); - break; - } - } - else - { - KeDelayExecutionThread(KernelMode, FALSE, &ShortPsLockDelay); - } - } - } - - return Status; -} - -VOID -NTAPI -PsUnlockProcess(PEPROCESS Process) -{ - PAGED_CODE(); - - ASSERT(Process->LockOwner == KeGetCurrentThread()); - - if(InterlockedDecrementUL(&Process->LockCount) == 0) - { - (void)InterlockedExchangePointer(&Process->LockOwner, NULL); - KeSetEvent(Process->LockEvent, IO_NO_INCREMENT, FALSE); - } - - KeLeaveCriticalRegion(); -} -#endif +LARGE_INTEGER ShortPsLockDelay; /* PRIVATE FUNCTIONS *********************************************************/ @@ -135,7 +55,8 @@ PsGetNextProcessThread(IN PEPROCESS Process, PAGED_CODE(); /* Lock the process */ - PsLockProcess(Process, FALSE); + KeEnterCriticalRegion(); + ExAcquirePushLockShared(&Process->ProcessLock); /* Check if we're already starting somewhere */ if (Thread) @@ -162,7 +83,8 @@ PsGetNextProcessThread(IN PEPROCESS Process, } /* Unlock the process */ - PsUnlockProcess(Process); + ExReleasePushLockShared(&Process->ProcessLock); + KeLeaveCriticalRegion(); /* Check if we had a starting thread, and dereference it */ if (Thread) ObDereferenceObject(Thread); @@ -422,14 +344,6 @@ PspCreateProcess(OUT PHANDLE ProcessHandle, /* Save the pointer to the section object */ Process->SectionObject = SectionObject; - /* Setup the Lock Event */ -#if 1 - Process->LockEvent = ExAllocatePoolWithTag(PagedPool, - sizeof(KEVENT), - TAG('P', 's', 'L', 'k')); - KeInitializeEvent(Process->LockEvent, SynchronizationEvent, FALSE); -#endif - /* Set default exit code */ Process->ExitStatus = STATUS_TIMEOUT; diff --git a/reactos/ntoskrnl/ps/psmgr.c b/reactos/ntoskrnl/ps/psmgr.c index c2655164b80..d95f057adc0 100644 --- a/reactos/ntoskrnl/ps/psmgr.c +++ b/reactos/ntoskrnl/ps/psmgr.c @@ -138,7 +138,7 @@ PsInitProcessManagment(VOID) OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; ShortPsLockDelay.QuadPart = -100LL; - PsLockTimeout.QuadPart = -10000000LL; /* one second */ + /* * Register the process object type */ diff --git a/reactos/ntoskrnl/ps/query.c b/reactos/ntoskrnl/ps/query.c index 0cb1fca3511..aab9bf4d652 100644 --- a/reactos/ntoskrnl/ps/query.c +++ b/reactos/ntoskrnl/ps/query.c @@ -551,30 +551,14 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, NULL); if (!NT_SUCCESS(Status)) break; - /* Lock the process to be thread-safe! */ - Status = PsLockProcess(Process, FALSE); - if(NT_SUCCESS(Status)) + /* Change the pointer */ + if (InterlockedCompareExchangePointer(&Process->ExceptionPort, + ExceptionPort, + NULL)) { - /* Make sure we don't already have a port */ - if (!Process->ExceptionPort) - { - /* Save the exception port */ - Process->ExceptionPort = ExceptionPort; - } - else - { - /* We already have one, fail */ - ObDereferenceObject(ExceptionPort); - Status = STATUS_PORT_ALREADY_SET; - } - - /* Unlock the process */ - PsUnlockProcess(Process); - } - else - { - /* Locking failed, dereference the port */ + /* We already had one, fail */ ObDereferenceObject(ExceptionPort); + Status = STATUS_PORT_ALREADY_SET; } break; @@ -644,7 +628,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, } /* FIXME - update the session id for the process token */ - Status = PsLockProcess(Process, FALSE); + //Status = PsLockProcess(Process, FALSE); if (!NT_SUCCESS(Status)) break; /* Write the session ID in the EPROCESS */ @@ -677,7 +661,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, } /* Unlock the process */ - PsUnlockProcess(Process); + //PsUnlockProcess(Process); break; /* Priority class: HACK! */