- 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
This commit is contained in:
Alex Ionescu 2006-07-20 17:44:30 +00:00
parent 82aa6e1250
commit e9600e4c9c
8 changed files with 50 additions and 314 deletions

View file

@ -32,6 +32,17 @@ Author:
#include <potypes.h>
#include <lpctypes.h>
//
// 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

View file

@ -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);
}
}

View file

@ -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

View file

@ -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))
{

View file

@ -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))

View file

@ -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;

View file

@ -138,7 +138,7 @@ PsInitProcessManagment(VOID)
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
ShortPsLockDelay.QuadPart = -100LL;
PsLockTimeout.QuadPart = -10000000LL; /* one second */
/*
* Register the process object type
*/

View file

@ -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! */