2010-02-26 11:43:19 +00:00
|
|
|
#pragma once
|
1999-08-11 23:29:26 +00:00
|
|
|
|
2021-03-26 08:32:34 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
|
1999-08-11 23:29:26 +00:00
|
|
|
/* GLOBAL VARIABLES *********************************************************/
|
|
|
|
|
2018-05-31 15:48:29 +00:00
|
|
|
extern RTL_TIME_ZONE_INFORMATION ExpTimeZoneInfo;
|
2004-11-06 16:05:49 +00:00
|
|
|
extern LARGE_INTEGER ExpTimeZoneBias;
|
|
|
|
extern ULONG ExpTimeZoneId;
|
2006-10-02 15:52:58 +00:00
|
|
|
extern ULONG ExpTickCountMultiplier;
|
2006-10-08 04:05:27 +00:00
|
|
|
extern ULONG ExpLastTimeZoneBias;
|
2003-09-10 06:12:22 +00:00
|
|
|
extern POBJECT_TYPE ExEventPairObjectType;
|
2006-10-09 05:59:18 +00:00
|
|
|
extern POBJECT_TYPE _ExEventObjectType, _ExSemaphoreObjectType;
|
2006-10-02 13:23:03 +00:00
|
|
|
extern FAST_MUTEX ExpEnvironmentLock;
|
|
|
|
extern ERESOURCE ExpFirmwareTableResource;
|
2022-08-09 13:48:48 +00:00
|
|
|
extern ERESOURCE ExpTimeRefreshLock;
|
2006-10-02 13:23:03 +00:00
|
|
|
extern LIST_ENTRY ExpFirmwareTableProviderListHead;
|
2006-10-06 19:29:25 +00:00
|
|
|
extern BOOLEAN ExpIsWinPEMode;
|
2021-11-07 00:17:32 +00:00
|
|
|
extern ULONG ExpResourceTimeoutCount;
|
2007-02-19 18:52:23 +00:00
|
|
|
extern LIST_ENTRY ExpSystemResourcesList;
|
2009-10-18 18:52:56 +00:00
|
|
|
extern ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
|
|
|
|
extern ULONG ExpUnicodeCaseTableDataOffset;
|
|
|
|
extern PVOID ExpNlsSectionPointer;
|
- Fix KiDispatchException to unmask KI_EXCEPTION_INTERNAL when setting the exception code, so that usermode/SEH filters get proper exception codes again.
- Fixes and compatible merges from KD Branch:
- Add stubs for KdSave, KdRestore, KdDebuggerInitialize0, KdSendPacket, KdReceivePacket to kdcom.dll
- Implement and export KeTryToAcquireSpinLockAtDpcLevel.
- Add EXCEPTION_RECORD64 and LIST_ENTRY64, KeTryToAcquireSpinLockAtDpcLevel, BREAKPOINT_COMMAND_STRING, Ke386SetCr2, Ke386SetDr3, Ke386SetDr6.
- Remove non-kernel routines from kdfuncs.h and remove deprecated routines from ke.h.
- Implement KiRestoreProcessorControlState, KeFreezeExecution, KeThawExecution, ExAcquireTimeRefreshLock, ExReleaseTimeRefreshLock.
- Rename ModuleLoadList to PsLoadedModuleList. Add PsNtosImageBase and set value in it.
- Add skeleton wdbgexts.h with what's needed until now, this is a PSDK header.
- Add kddll.h for KDCOM/1394/USB2.DLL prototypes.
- Add windbgkd.h with KD protocol definitions. Used to be an NT5 DDK header, but was removed, so this goes into include\reactos.
- Fix KiDebugService to load EDX from KTRAP_FRAME_EDX, not KTRAP_FRAME_EAX!.
- Fix CommonDispatchException to check for the argument count in ECX, not EAX. Previously we were ignoring parameter counts and never filling out exception records!
- Add KdDebuggerInitialize1 and enable call to it.
- Fix KD_SYMBOLS_INFO definition and DbgLoadImageSymbols prototype.
- Implement DbgUnLoadImageSymbols.
- Fix some small bugs in KeBugCheckWithTf and add various debugger calls/checks where needed.
- Fix bugcheck recursion code which was incorrect.
- Only save/restore CR4 if KeFeatureBits indicates CR4 support exists.
- Export KdDebuggerNotPresent since KDCOM needs it.
- Add KCONTINUE_STATUS.
- Add DBGKD_ANY_CONTROL_SET and X86/IA64/AMD64 control sets.
- Add DBGKD_MANIPULATE_STATE64 and all sub-structures (READ_MEMORY, WRITE_MEMORY, etc).
- Create GCC_ULONG64 type to hack around a bug in GCC which is incapable of creating entries for externals at compile-time for 64-bit pointers.
- Rename NameSpaceRoot to ObpRootDirectoryObject, IopLogListHead to IopErrorLogListHead, BugcheckCallbackListHead to KeBugcheckCallbackListHead, BugcheckReasonCallbackListHead to KeBugcheckReasonCallbackListHead, ObTypeObjectType to ObpTypeObjectType.
- Create ntverp.h and common.ver files. These are the standard files used by the NT/DDK build systems and we should try to support them as well instead of re-defining everything our own way (especially if we want to build ddk-compatible drivers later on).
- Made init.c use version data from ntverp.h instead of hard-coding.
- Defined NT 5.2.3790.1830 as the version we report.
- Fixed up .rc file to be correct and match DDK-sytnax/style.
- For now only the kernel uses this new versionning scheme, but we should change the build system later to use this for every component.
- Fix KiSaveProcessorControlState and KiRestoreProcessorControlSate. The latter doesn't freeze the CPU anymore so it's enabled, and the former doesn't cause WinDBG to panic anymore and display weird data.
- KPROCESSOR_STATE is not 4-byte aligned.
- Use DR_MASK and DR7_OVERRIDE_V in KiUpdateDr7, KiRecordDr7 instead of DR_ACTIVE_MASK.
- Add ExceptionRecord32To64.
- Fix generation of driver name for symbol load.
svn path=/trunk/; revision=25937
2007-03-01 19:51:20 +00:00
|
|
|
extern ULONG NtGlobalFlag;
|
2015-03-16 03:14:16 +00:00
|
|
|
extern UNICODE_STRING NtSystemRoot;
|
2007-02-22 18:02:53 +00:00
|
|
|
extern ULONG ExpInitializationPhase;
|
2007-05-08 21:35:10 +00:00
|
|
|
extern ULONG ExpAltTimeZoneBias;
|
2008-04-01 18:14:01 +00:00
|
|
|
extern LIST_ENTRY ExSystemLookasideListHead;
|
2010-03-08 20:37:24 +00:00
|
|
|
extern PCALLBACK_OBJECT PowerStateCallback;
|
2014-02-16 09:27:01 +00:00
|
|
|
extern LIST_ENTRY ExPoolLookasideListHead;
|
|
|
|
extern LIST_ENTRY ExpNonPagedLookasideListHead;
|
|
|
|
extern LIST_ENTRY ExpPagedLookasideListHead;
|
|
|
|
extern KSPIN_LOCK ExpNonPagedLookasideListLock;
|
|
|
|
extern KSPIN_LOCK ExpPagedLookasideListLock;
|
2018-02-07 16:51:35 +00:00
|
|
|
extern ULONG ExCriticalWorkerThreads;
|
|
|
|
extern ULONG ExDelayedWorkerThreads;
|
1999-08-11 23:29:26 +00:00
|
|
|
|
2018-03-31 20:12:44 +00:00
|
|
|
extern PVOID ExpDefaultErrorPort;
|
|
|
|
extern PEPROCESS ExpDefaultErrorPortProcess;
|
|
|
|
|
2015-03-16 03:14:16 +00:00
|
|
|
/*
|
|
|
|
* NT/Cm Version Info variables
|
|
|
|
*/
|
|
|
|
extern ULONG NtMajorVersion;
|
|
|
|
extern ULONG NtMinorVersion;
|
|
|
|
extern ULONG NtBuildNumber;
|
|
|
|
extern ULONG CmNtSpBuildNumber;
|
|
|
|
extern ULONG CmNtCSDVersion;
|
|
|
|
extern ULONG CmNtCSDReleaseType;
|
|
|
|
extern UNICODE_STRING CmVersionString;
|
|
|
|
extern UNICODE_STRING CmCSDVersionString;
|
|
|
|
extern CHAR NtBuildLab[];
|
|
|
|
|
2015-08-29 02:03:56 +00:00
|
|
|
/*
|
2015-08-29 12:53:08 +00:00
|
|
|
* WinDBG Debugger Worker State Machine data (see dbgctrl.c)
|
2015-08-29 02:03:56 +00:00
|
|
|
*/
|
|
|
|
typedef enum _WINKD_WORKER_STATE
|
|
|
|
{
|
2015-08-29 12:53:08 +00:00
|
|
|
WinKdWorkerReady = 0,
|
|
|
|
WinKdWorkerStart,
|
2015-08-29 02:03:56 +00:00
|
|
|
WinKdWorkerInitialized
|
|
|
|
} WINKD_WORKER_STATE;
|
|
|
|
|
|
|
|
extern WORK_QUEUE_ITEM ExpDebuggerWorkItem;
|
|
|
|
extern WINKD_WORKER_STATE ExpDebuggerWork;
|
|
|
|
extern PEPROCESS ExpDebuggerProcessAttach;
|
|
|
|
extern PEPROCESS ExpDebuggerProcessKill;
|
|
|
|
extern ULONG_PTR ExpDebuggerPageIn;
|
2018-03-31 20:12:44 +00:00
|
|
|
|
2015-08-29 02:03:56 +00:00
|
|
|
VOID NTAPI ExpDebuggerWorker(IN PVOID Context);
|
|
|
|
|
2014-04-13 16:45:58 +00:00
|
|
|
#ifdef _WIN64
|
2021-11-07 03:21:40 +00:00
|
|
|
#define HANDLE_LOW_BITS (PAGE_SHIFT - 4)
|
|
|
|
#define HANDLE_HIGH_BITS (PAGE_SHIFT - 3)
|
2014-04-13 16:45:58 +00:00
|
|
|
#else
|
2021-11-07 03:21:40 +00:00
|
|
|
#define HANDLE_LOW_BITS (PAGE_SHIFT - 3)
|
|
|
|
#define HANDLE_HIGH_BITS (PAGE_SHIFT - 2)
|
2014-04-13 16:45:58 +00:00
|
|
|
#endif
|
2021-11-07 03:21:40 +00:00
|
|
|
#define HANDLE_TAG_BITS (2)
|
|
|
|
#define HANDLE_INDEX_BITS (HANDLE_LOW_BITS + 2*HANDLE_HIGH_BITS)
|
|
|
|
#define KERNEL_FLAG_BITS (sizeof(PVOID)*8 - HANDLE_INDEX_BITS - HANDLE_TAG_BITS)
|
2014-04-13 16:45:58 +00:00
|
|
|
|
|
|
|
typedef union _EXHANDLE
|
2007-01-22 08:15:17 +00:00
|
|
|
{
|
2021-11-07 03:21:40 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
ULONG_PTR TagBits: HANDLE_TAG_BITS;
|
|
|
|
ULONG_PTR Index: HANDLE_INDEX_BITS;
|
|
|
|
ULONG_PTR KernelFlag: KERNEL_FLAG_BITS;
|
|
|
|
};
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
ULONG_PTR TagBits2: HANDLE_TAG_BITS;
|
|
|
|
ULONG_PTR LowIndex: HANDLE_LOW_BITS;
|
|
|
|
ULONG_PTR MidIndex: HANDLE_HIGH_BITS;
|
|
|
|
ULONG_PTR HighIndex: HANDLE_HIGH_BITS;
|
|
|
|
ULONG_PTR KernelFlag2: KERNEL_FLAG_BITS;
|
|
|
|
};
|
|
|
|
HANDLE GenericHandleOverlay;
|
|
|
|
ULONG_PTR Value;
|
|
|
|
ULONG AsULONG;
|
2007-01-22 08:15:17 +00:00
|
|
|
} EXHANDLE, *PEXHANDLE;
|
|
|
|
|
2007-01-15 07:33:42 +00:00
|
|
|
typedef struct _ETIMER
|
|
|
|
{
|
|
|
|
KTIMER KeTimer;
|
|
|
|
KAPC TimerApc;
|
|
|
|
KDPC TimerDpc;
|
|
|
|
LIST_ENTRY ActiveTimerListEntry;
|
|
|
|
KSPIN_LOCK Lock;
|
|
|
|
LONG Period;
|
|
|
|
BOOLEAN ApcAssociated;
|
|
|
|
BOOLEAN WakeTimer;
|
|
|
|
LIST_ENTRY WakeTimerListEntry;
|
|
|
|
} ETIMER, *PETIMER;
|
|
|
|
|
2007-01-16 04:16:31 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
PCALLBACK_OBJECT *CallbackObject;
|
|
|
|
PWSTR Name;
|
|
|
|
} SYSTEM_CALLBACKS;
|
|
|
|
|
2011-09-29 06:48:19 +00:00
|
|
|
typedef struct _HARDERROR_USER_PARAMETERS
|
|
|
|
{
|
|
|
|
ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS];
|
|
|
|
UNICODE_STRING Strings[MAXIMUM_HARDERROR_PARAMETERS];
|
|
|
|
WCHAR Buffer[ANYSIZE_ARRAY];
|
|
|
|
} HARDERROR_USER_PARAMETERS, *PHARDERROR_USER_PARAMETERS;
|
|
|
|
|
2006-07-11 15:36:44 +00:00
|
|
|
#define MAX_FAST_REFS 7
|
|
|
|
|
2021-11-07 03:21:40 +00:00
|
|
|
#define ExAcquireRundownProtection _ExAcquireRundownProtection
|
|
|
|
#define ExReleaseRundownProtection _ExReleaseRundownProtection
|
|
|
|
#define ExInitializeRundownProtection _ExInitializeRundownProtection
|
|
|
|
#define ExWaitForRundownProtectionRelease _ExWaitForRundownProtectionRelease
|
|
|
|
#define ExRundownCompleted _ExRundownCompleted
|
|
|
|
#define ExGetPreviousMode KeGetPreviousMode
|
2006-09-07 05:07:34 +00:00
|
|
|
|
2007-01-22 08:15:17 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Various bits tagged on the handle or handle table
|
|
|
|
//
|
|
|
|
#define EXHANDLE_TABLE_ENTRY_LOCK_BIT 1
|
|
|
|
#define FREE_HANDLE_MASK -1
|
|
|
|
|
|
|
|
//
|
|
|
|
// Number of entries in each table level
|
|
|
|
//
|
|
|
|
#define LOW_LEVEL_ENTRIES (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY))
|
|
|
|
#define MID_LEVEL_ENTRIES (PAGE_SIZE / sizeof(PHANDLE_TABLE_ENTRY))
|
2007-03-02 07:23:19 +00:00
|
|
|
#define HIGH_LEVEL_ENTRIES (16777216 / (LOW_LEVEL_ENTRIES * MID_LEVEL_ENTRIES))
|
2007-01-22 08:15:17 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Maximum index in each table level before we need another table
|
|
|
|
//
|
|
|
|
#define MAX_LOW_INDEX LOW_LEVEL_ENTRIES
|
|
|
|
#define MAX_MID_INDEX (MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
|
|
|
|
#define MAX_HIGH_INDEX (MID_LEVEL_ENTRIES * MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
|
|
|
|
|
2021-11-07 03:21:40 +00:00
|
|
|
#define ExpChangeRundown(x, y, z) (ULONG_PTR)InterlockedCompareExchangePointer(&x->Ptr, (PVOID)y, (PVOID)z)
|
|
|
|
#define ExpChangePushlock(x, y, z) InterlockedCompareExchangePointer((PVOID*)x, (PVOID)y, (PVOID)z)
|
|
|
|
#define ExpSetRundown(x, y) InterlockedExchangePointer(&x->Ptr, (PVOID)y)
|
2009-03-03 20:24:10 +00:00
|
|
|
|
2012-02-25 23:14:37 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ExGetPoolTagInfo(
|
|
|
|
IN PSYSTEM_POOLTAG_INFORMATION SystemInformation,
|
|
|
|
IN ULONG SystemInformationLength,
|
|
|
|
IN OUT PULONG ReturnLength OPTIONAL
|
|
|
|
);
|
2012-04-20 19:31:07 +00:00
|
|
|
|
2019-02-27 08:02:30 +00:00
|
|
|
typedef struct _UUID_CACHED_VALUES_STRUCT
|
|
|
|
{
|
|
|
|
ULONGLONG Time;
|
|
|
|
LONG AllocatedCount;
|
2020-09-09 01:46:56 +00:00
|
|
|
union
|
|
|
|
{
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
UCHAR ClockSeqHiAndReserved;
|
|
|
|
UCHAR ClockSeqLow;
|
|
|
|
UCHAR NodeId[6 /*SEED_BUFFER_SIZE*/];
|
|
|
|
};
|
|
|
|
UCHAR GuidInit[8]; /* Match GUID.Data4 */
|
|
|
|
};
|
2019-02-27 08:02:30 +00:00
|
|
|
} UUID_CACHED_VALUES_STRUCT, *PUUID_CACHED_VALUES_STRUCT;
|
|
|
|
|
2020-11-05 18:03:30 +00:00
|
|
|
C_ASSERT(RTL_FIELD_SIZE(UUID_CACHED_VALUES_STRUCT, GuidInit) == RTL_FIELD_SIZE(UUID, Data4));
|
|
|
|
|
1999-08-11 23:29:26 +00:00
|
|
|
/* INITIALIZATION FUNCTIONS *************************************************/
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2012-09-03 01:12:58 +00:00
|
|
|
BOOLEAN
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2001-06-12 17:51:51 +00:00
|
|
|
ExpWin32kInit(VOID);
|
|
|
|
|
2003-11-16 15:17:46 +00:00
|
|
|
VOID
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2004-11-05 17:42:20 +00:00
|
|
|
ExInit2(VOID);
|
2005-06-25 17:01:17 +00:00
|
|
|
|
2006-09-17 05:20:24 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
2007-01-25 01:13:09 +00:00
|
|
|
Phase1Initialization(
|
2006-09-17 05:20:24 +00:00
|
|
|
IN PVOID Context
|
|
|
|
);
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2006-10-05 15:13:59 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ExpInitializePushLocks(VOID);
|
|
|
|
|
2006-10-08 04:05:27 +00:00
|
|
|
BOOLEAN
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2006-10-08 04:05:27 +00:00
|
|
|
ExRefreshTimeZoneInformation(
|
|
|
|
IN PLARGE_INTEGER SystemBootTime
|
|
|
|
);
|
2005-06-25 17:01:17 +00:00
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2004-11-05 17:42:20 +00:00
|
|
|
VOID
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
Dispatching & Queue Rewrite II:
- Rewrote wait code. It is now cleaner, more optimized and faster. All waiting
functions are now clearly differentiated instead of sharing code. These functions
are called up to a dozen times a second, so having dedicated code for each of
them is a real boost in speed.
- Fixed several queue issues, made a dedicated queue wait/wake function (you are not
supposed to use KeWaitFor on a queue, and this is also a speed boost), and make it
compatible with new wait code.
- Optimized Work Queue code to be much smaller and better organized, by using an
array instead of hard-coded multiple static variables. Also, add support for the
real NT structures and implementation, paving the road for Dynamic Work Items, which
also have timeouts, and deadlock dection + debug info.
- Simplified PsBlockThread and made it compatible with wait code.
- Added support for priority boosting when unwaiting a thread; will use later, as well
as put proper boosting for dispatch objects.
- Inlined all dispatcher lock functions and header initialization for speed.
- Moved executive wait code into ob.
svn path=/trunk/; revision=14047
2005-03-14 05:54:32 +00:00
|
|
|
ExpInitializeWorkerThreads(VOID);
|
2005-06-25 17:01:17 +00:00
|
|
|
|
2010-03-08 20:37:24 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ExSwapinWorkerThreads(IN BOOLEAN AllowSwap);
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2001-07-04 20:40:24 +00:00
|
|
|
VOID
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2001-07-04 20:40:24 +00:00
|
|
|
ExpInitLookasideLists(VOID);
|
2005-06-25 17:01:17 +00:00
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2006-10-02 13:23:03 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ExInitializeSystemLookasideList(
|
|
|
|
IN PGENERAL_LOOKASIDE List,
|
|
|
|
IN POOL_TYPE Type,
|
|
|
|
IN ULONG Size,
|
|
|
|
IN ULONG Tag,
|
|
|
|
IN USHORT MaximumDepth,
|
|
|
|
IN PLIST_ENTRY ListHead
|
|
|
|
);
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2007-01-16 04:16:31 +00:00
|
|
|
BOOLEAN
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2004-06-19 08:48:01 +00:00
|
|
|
ExpInitializeCallbacks(VOID);
|
2005-06-25 17:01:17 +00:00
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2019-02-27 20:12:32 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
ExpUuidInitialization(VOID);
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2019-02-27 20:12:32 +00:00
|
|
|
BOOLEAN
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2019-02-27 20:12:32 +00:00
|
|
|
ExLuidInitialization(VOID);
|
2005-06-25 17:01:17 +00:00
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2005-03-12 21:08:29 +00:00
|
|
|
VOID
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2006-10-01 18:01:38 +00:00
|
|
|
ExpInitializeExecutive(
|
|
|
|
IN ULONG Cpu,
|
|
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
|
|
);
|
1999-08-11 23:29:26 +00:00
|
|
|
|
2018-03-31 20:12:44 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ExShutdownSystem(VOID);
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2012-09-03 01:12:58 +00:00
|
|
|
BOOLEAN
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2005-06-25 17:01:17 +00:00
|
|
|
ExpInitializeEventImplementation(VOID);
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2012-09-03 01:12:58 +00:00
|
|
|
BOOLEAN
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2012-04-20 19:31:07 +00:00
|
|
|
ExpInitializeKeyedEventImplementation(VOID);
|
2005-06-25 17:01:17 +00:00
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2012-09-03 01:12:58 +00:00
|
|
|
BOOLEAN
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2005-06-25 17:01:17 +00:00
|
|
|
ExpInitializeEventPairImplementation(VOID);
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2012-09-03 01:12:58 +00:00
|
|
|
BOOLEAN
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2005-06-25 17:01:17 +00:00
|
|
|
ExpInitializeSemaphoreImplementation(VOID);
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2012-09-03 01:12:58 +00:00
|
|
|
BOOLEAN
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2005-06-25 17:01:17 +00:00
|
|
|
ExpInitializeMutantImplementation(VOID);
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2012-09-03 01:12:58 +00:00
|
|
|
BOOLEAN
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2005-06-25 17:01:17 +00:00
|
|
|
ExpInitializeTimerImplementation(VOID);
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2012-09-03 01:12:58 +00:00
|
|
|
BOOLEAN
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2005-06-25 17:01:17 +00:00
|
|
|
ExpInitializeProfileImplementation(VOID);
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2006-01-05 16:24:32 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ExpResourceInitialization(VOID);
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2006-10-01 18:01:38 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ExInitPoolLookasidePointers(VOID);
|
|
|
|
|
2006-10-06 19:29:25 +00:00
|
|
|
/* Callback Functions ********************************************************/
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ExInitializeCallBack(
|
2007-01-16 15:09:53 +00:00
|
|
|
IN OUT PEX_CALLBACK Callback
|
|
|
|
);
|
|
|
|
|
|
|
|
PEX_CALLBACK_ROUTINE_BLOCK
|
|
|
|
NTAPI
|
|
|
|
ExAllocateCallBack(
|
|
|
|
IN PEX_CALLBACK_FUNCTION Function,
|
|
|
|
IN PVOID Context
|
|
|
|
);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ExFreeCallBack(
|
|
|
|
IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
|
|
|
|
);
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
ExCompareExchangeCallBack (
|
|
|
|
IN OUT PEX_CALLBACK CallBack,
|
|
|
|
IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock,
|
|
|
|
IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock
|
|
|
|
);
|
|
|
|
|
|
|
|
PEX_CALLBACK_ROUTINE_BLOCK
|
|
|
|
NTAPI
|
|
|
|
ExReferenceCallBackBlock(
|
|
|
|
IN OUT PEX_CALLBACK CallBack
|
|
|
|
);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ExDereferenceCallBackBlock(
|
|
|
|
IN OUT PEX_CALLBACK CallBack,
|
|
|
|
IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
|
|
|
|
);
|
|
|
|
|
|
|
|
PEX_CALLBACK_FUNCTION
|
|
|
|
NTAPI
|
|
|
|
ExGetCallBackBlockRoutine(
|
|
|
|
IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
|
|
|
|
);
|
|
|
|
|
|
|
|
PVOID
|
|
|
|
NTAPI
|
|
|
|
ExGetCallBackBlockContext(
|
|
|
|
IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
|
|
|
|
);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ExWaitForCallBacks(
|
|
|
|
IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
|
2006-10-06 19:29:25 +00:00
|
|
|
);
|
|
|
|
|
2005-12-29 19:12:09 +00:00
|
|
|
/* Rundown Functions ********************************************************/
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
|
|
|
ExfInitializeRundownProtection(
|
|
|
|
OUT PEX_RUNDOWN_REF RunRef
|
|
|
|
);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
|
|
|
ExfReInitializeRundownProtection(
|
|
|
|
OUT PEX_RUNDOWN_REF RunRef
|
|
|
|
);
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
FASTCALL
|
|
|
|
ExfAcquireRundownProtection(
|
|
|
|
IN OUT PEX_RUNDOWN_REF RunRef
|
|
|
|
);
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
FASTCALL
|
|
|
|
ExfAcquireRundownProtectionEx(
|
|
|
|
IN OUT PEX_RUNDOWN_REF RunRef,
|
|
|
|
IN ULONG Count
|
|
|
|
);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
|
|
|
ExfReleaseRundownProtection(
|
|
|
|
IN OUT PEX_RUNDOWN_REF RunRef
|
|
|
|
);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
|
|
|
ExfReleaseRundownProtectionEx(
|
|
|
|
IN OUT PEX_RUNDOWN_REF RunRef,
|
|
|
|
IN ULONG Count
|
|
|
|
);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
|
|
|
ExfRundownCompleted(
|
|
|
|
OUT PEX_RUNDOWN_REF RunRef
|
|
|
|
);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
|
|
|
ExfWaitForRundownProtectionRelease(
|
|
|
|
IN OUT PEX_RUNDOWN_REF RunRef
|
|
|
|
);
|
|
|
|
|
2005-03-13 14:21:47 +00:00
|
|
|
/* HANDLE TABLE FUNCTIONS ***************************************************/
|
|
|
|
|
2007-02-14 17:51:48 +00:00
|
|
|
typedef BOOLEAN
|
2007-01-22 08:15:17 +00:00
|
|
|
(NTAPI *PEX_SWEEP_HANDLE_CALLBACK)(
|
2006-06-10 00:41:16 +00:00
|
|
|
PHANDLE_TABLE_ENTRY HandleTableEntry,
|
2007-01-22 08:15:17 +00:00
|
|
|
HANDLE Handle,
|
2005-06-25 17:01:17 +00:00
|
|
|
PVOID Context
|
|
|
|
);
|
|
|
|
|
2007-01-22 08:15:17 +00:00
|
|
|
typedef BOOLEAN
|
|
|
|
(NTAPI *PEX_DUPLICATE_HANDLE_CALLBACK)(
|
|
|
|
IN PEPROCESS Process,
|
|
|
|
IN PHANDLE_TABLE HandleTable,
|
|
|
|
IN PHANDLE_TABLE_ENTRY HandleTableEntry,
|
|
|
|
IN PHANDLE_TABLE_ENTRY NewEntry
|
2005-06-25 17:01:17 +00:00
|
|
|
);
|
2005-03-13 14:21:47 +00:00
|
|
|
|
2007-01-22 08:15:17 +00:00
|
|
|
typedef BOOLEAN
|
|
|
|
(NTAPI *PEX_CHANGE_HANDLE_CALLBACK)(
|
|
|
|
PHANDLE_TABLE_ENTRY HandleTableEntry,
|
|
|
|
ULONG_PTR Context
|
2005-12-07 17:06:48 +00:00
|
|
|
);
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2005-12-07 17:06:48 +00:00
|
|
|
VOID
|
2007-01-22 08:15:17 +00:00
|
|
|
NTAPI
|
|
|
|
ExpInitializeHandleTables(
|
|
|
|
VOID
|
2005-06-25 17:01:17 +00:00
|
|
|
);
|
|
|
|
|
2005-03-13 14:21:47 +00:00
|
|
|
PHANDLE_TABLE
|
2007-01-22 08:15:17 +00:00
|
|
|
NTAPI
|
|
|
|
ExCreateHandleTable(
|
|
|
|
IN PEPROCESS Process OPTIONAL
|
2005-06-25 17:01:17 +00:00
|
|
|
);
|
|
|
|
|
2005-03-13 14:21:47 +00:00
|
|
|
VOID
|
2007-01-22 08:15:17 +00:00
|
|
|
NTAPI
|
2005-06-25 17:01:17 +00:00
|
|
|
ExUnlockHandleTableEntry(
|
|
|
|
IN PHANDLE_TABLE HandleTable,
|
2007-01-22 08:15:17 +00:00
|
|
|
IN PHANDLE_TABLE_ENTRY HandleTableEntry
|
2005-06-25 17:01:17 +00:00
|
|
|
);
|
|
|
|
|
2005-08-07 23:43:58 +00:00
|
|
|
HANDLE
|
2007-01-22 08:15:17 +00:00
|
|
|
NTAPI
|
2005-06-25 17:01:17 +00:00
|
|
|
ExCreateHandle(
|
|
|
|
IN PHANDLE_TABLE HandleTable,
|
2007-01-22 08:15:17 +00:00
|
|
|
IN PHANDLE_TABLE_ENTRY HandleTableEntry
|
2005-06-25 17:01:17 +00:00
|
|
|
);
|
|
|
|
|
2007-01-22 08:15:17 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ExDestroyHandleTable(
|
2005-06-25 17:01:17 +00:00
|
|
|
IN PHANDLE_TABLE HandleTable,
|
2007-01-22 08:15:17 +00:00
|
|
|
IN PVOID DestroyHandleProcedure OPTIONAL
|
2005-06-25 17:01:17 +00:00
|
|
|
);
|
|
|
|
|
2007-01-22 08:15:17 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
ExDestroyHandle(
|
2005-06-25 17:01:17 +00:00
|
|
|
IN PHANDLE_TABLE HandleTable,
|
2007-01-22 08:15:17 +00:00
|
|
|
IN HANDLE Handle,
|
|
|
|
IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL
|
2005-06-25 17:01:17 +00:00
|
|
|
);
|
|
|
|
|
2005-03-13 14:21:47 +00:00
|
|
|
PHANDLE_TABLE_ENTRY
|
2007-01-22 08:15:17 +00:00
|
|
|
NTAPI
|
2005-06-25 17:01:17 +00:00
|
|
|
ExMapHandleToPointer(
|
|
|
|
IN PHANDLE_TABLE HandleTable,
|
2005-08-07 23:43:58 +00:00
|
|
|
IN HANDLE Handle
|
2005-06-25 17:01:17 +00:00
|
|
|
);
|
2005-03-13 14:21:47 +00:00
|
|
|
|
2007-01-22 08:15:17 +00:00
|
|
|
PHANDLE_TABLE
|
|
|
|
NTAPI
|
|
|
|
ExDupHandleTable(
|
|
|
|
IN PEPROCESS Process,
|
|
|
|
IN PHANDLE_TABLE HandleTable,
|
|
|
|
IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure,
|
|
|
|
IN ULONG_PTR Mask
|
|
|
|
);
|
|
|
|
|
2005-03-13 14:21:47 +00:00
|
|
|
BOOLEAN
|
2007-01-22 08:15:17 +00:00
|
|
|
NTAPI
|
2005-06-25 17:01:17 +00:00
|
|
|
ExChangeHandle(
|
|
|
|
IN PHANDLE_TABLE HandleTable,
|
2005-08-07 23:43:58 +00:00
|
|
|
IN HANDLE Handle,
|
2007-01-22 08:15:17 +00:00
|
|
|
IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine,
|
|
|
|
IN ULONG_PTR Context
|
|
|
|
);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ExSweepHandleTable(
|
|
|
|
IN PHANDLE_TABLE HandleTable,
|
|
|
|
IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure,
|
2005-06-25 17:01:17 +00:00
|
|
|
IN PVOID Context
|
|
|
|
);
|
2005-03-13 14:21:47 +00:00
|
|
|
|
2016-08-28 19:18:28 +00:00
|
|
|
PHANDLE_TABLE_ENTRY
|
|
|
|
NTAPI
|
|
|
|
ExpLookupHandleTableEntry(
|
|
|
|
IN PHANDLE_TABLE HandleTable,
|
|
|
|
IN EXHANDLE Handle
|
|
|
|
);
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
ExpLockHandleTableEntry(
|
|
|
|
IN PHANDLE_TABLE HandleTable,
|
|
|
|
IN PHANDLE_TABLE_ENTRY HandleTableEntry
|
|
|
|
);
|
|
|
|
|
2005-05-06 22:25:30 +00:00
|
|
|
/* PSEH EXCEPTION HANDLING **************************************************/
|
|
|
|
|
|
|
|
LONG
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2005-05-06 22:25:30 +00:00
|
|
|
ExSystemExceptionFilter(VOID);
|
|
|
|
|
2007-01-16 15:09:53 +00:00
|
|
|
/* CALLBACKS *****************************************************************/
|
|
|
|
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
VOID
|
2007-01-16 15:09:53 +00:00
|
|
|
ExDoCallBack(IN OUT PEX_CALLBACK Callback,
|
|
|
|
IN PVOID Context,
|
|
|
|
IN PVOID Argument1,
|
|
|
|
IN PVOID Argument2)
|
|
|
|
{
|
2009-03-03 20:24:10 +00:00
|
|
|
PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock;
|
2007-01-16 15:09:53 +00:00
|
|
|
PEX_CALLBACK_FUNCTION Function;
|
|
|
|
|
|
|
|
/* Reference the block */
|
2009-03-03 20:24:10 +00:00
|
|
|
CallbackBlock = ExReferenceCallBackBlock(Callback);
|
|
|
|
if (CallbackBlock)
|
2007-01-16 15:09:53 +00:00
|
|
|
{
|
|
|
|
/* Get the function */
|
2009-03-03 20:24:10 +00:00
|
|
|
Function = ExGetCallBackBlockRoutine(CallbackBlock);
|
2007-01-16 15:09:53 +00:00
|
|
|
|
|
|
|
/* Do the callback */
|
|
|
|
Function(Context, Argument1, Argument2);
|
|
|
|
|
|
|
|
/* Now dereference it */
|
2009-03-03 20:24:10 +00:00
|
|
|
ExDereferenceCallBackBlock(Callback, CallbackBlock);
|
2007-01-16 15:09:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* FAST REFS ******************************************************************/
|
2005-12-29 19:12:09 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
FORCEINLINE
|
|
|
|
PVOID
|
|
|
|
ExGetObjectFastReference(IN EX_FAST_REF FastRef)
|
|
|
|
{
|
|
|
|
/* Return the unbiased pointer */
|
|
|
|
return (PVOID)(FastRef.Value & ~MAX_FAST_REFS);
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
ULONG
|
|
|
|
ExGetCountFastReference(IN EX_FAST_REF FastRef)
|
|
|
|
{
|
|
|
|
/* Return the reference count */
|
2011-06-06 19:08:39 +00:00
|
|
|
return (ULONG)FastRef.RefCnt;
|
2009-03-03 20:24:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
VOID
|
|
|
|
ExInitializeFastReference(OUT PEX_FAST_REF FastRef,
|
|
|
|
IN OPTIONAL PVOID Object)
|
|
|
|
{
|
|
|
|
/* Sanity check */
|
|
|
|
ASSERT((((ULONG_PTR)Object) & MAX_FAST_REFS) == 0);
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Check if an object is being set */
|
|
|
|
if (!Object)
|
|
|
|
{
|
|
|
|
/* Clear the field */
|
|
|
|
FastRef->Object = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Otherwise, we assume the object was referenced and is ready */
|
|
|
|
FastRef->Value = (ULONG_PTR)Object | MAX_FAST_REFS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
EX_FAST_REF
|
|
|
|
ExAcquireFastReference(IN OUT PEX_FAST_REF FastRef)
|
|
|
|
{
|
|
|
|
EX_FAST_REF OldValue, NewValue;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Start reference loop */
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
/* Get the current reference count */
|
|
|
|
OldValue = *FastRef;
|
|
|
|
if (OldValue.RefCnt)
|
|
|
|
{
|
|
|
|
/* Increase the reference count */
|
|
|
|
NewValue.Value = OldValue.Value - 1;
|
|
|
|
NewValue.Object = ExpChangePushlock(&FastRef->Object,
|
|
|
|
NewValue.Object,
|
|
|
|
OldValue.Object);
|
|
|
|
if (NewValue.Object != OldValue.Object) continue;
|
|
|
|
}
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* We are done */
|
|
|
|
break;
|
|
|
|
}
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Return the old value */
|
|
|
|
return OldValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
BOOLEAN
|
|
|
|
ExInsertFastReference(IN OUT PEX_FAST_REF FastRef,
|
|
|
|
IN PVOID Object)
|
|
|
|
{
|
|
|
|
EX_FAST_REF OldValue, NewValue;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Sanity checks */
|
|
|
|
ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Start update loop */
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
/* Get the current reference count */
|
|
|
|
OldValue = *FastRef;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Check if the current count is too high or if the pointer changed */
|
|
|
|
if (((OldValue.RefCnt + MAX_FAST_REFS) > MAX_FAST_REFS) ||
|
|
|
|
((OldValue.Value &~ MAX_FAST_REFS) != (ULONG_PTR)Object))
|
|
|
|
{
|
|
|
|
/* Fail */
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Update the reference count */
|
|
|
|
NewValue.Value = OldValue.Value + MAX_FAST_REFS;
|
|
|
|
NewValue.Object = ExpChangePushlock(&FastRef->Object,
|
|
|
|
NewValue.Object,
|
|
|
|
OldValue.Object);
|
|
|
|
if (NewValue.Object != OldValue.Object) continue;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* We are done */
|
|
|
|
break;
|
|
|
|
}
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Return success */
|
2010-12-26 22:25:47 +00:00
|
|
|
return TRUE;
|
2009-03-03 20:24:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
2009-06-22 13:37:49 +00:00
|
|
|
BOOLEAN
|
2009-03-03 20:24:10 +00:00
|
|
|
ExReleaseFastReference(IN PEX_FAST_REF FastRef,
|
|
|
|
IN PVOID Object)
|
|
|
|
{
|
|
|
|
EX_FAST_REF OldValue, NewValue;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Sanity checks */
|
|
|
|
ASSERT(Object != NULL);
|
|
|
|
ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Start reference loop */
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
/* Get the current reference count */
|
|
|
|
OldValue = *FastRef;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Check if we're full if if the pointer changed */
|
|
|
|
if ((OldValue.Value ^ (ULONG_PTR)Object) >= MAX_FAST_REFS) return FALSE;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Decrease the reference count */
|
|
|
|
NewValue.Value = OldValue.Value + 1;
|
|
|
|
NewValue.Object = ExpChangePushlock(&FastRef->Object,
|
|
|
|
NewValue.Object,
|
|
|
|
OldValue.Object);
|
|
|
|
if (NewValue.Object != OldValue.Object) continue;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* We are done */
|
|
|
|
break;
|
|
|
|
}
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Return success */
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
2009-06-22 13:37:49 +00:00
|
|
|
EX_FAST_REF
|
2009-03-03 20:24:10 +00:00
|
|
|
ExSwapFastReference(IN PEX_FAST_REF FastRef,
|
|
|
|
IN PVOID Object)
|
|
|
|
{
|
|
|
|
EX_FAST_REF NewValue, OldValue;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Sanity check */
|
|
|
|
ASSERT((((ULONG_PTR)Object) & MAX_FAST_REFS) == 0);
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Check if an object is being set */
|
|
|
|
if (!Object)
|
|
|
|
{
|
|
|
|
/* Clear the field */
|
|
|
|
NewValue.Object = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Otherwise, we assume the object was referenced and is ready */
|
|
|
|
NewValue.Value = (ULONG_PTR)Object | MAX_FAST_REFS;
|
|
|
|
}
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Update the object */
|
|
|
|
OldValue.Object = InterlockedExchangePointer(&FastRef->Object, NewValue.Object);
|
|
|
|
return OldValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
2009-06-22 13:37:49 +00:00
|
|
|
EX_FAST_REF
|
2009-03-03 20:24:10 +00:00
|
|
|
ExCompareSwapFastReference(IN PEX_FAST_REF FastRef,
|
|
|
|
IN PVOID Object,
|
|
|
|
IN PVOID OldObject)
|
|
|
|
{
|
|
|
|
EX_FAST_REF OldValue, NewValue;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Sanity check and start swap loop */
|
|
|
|
ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
/* Get the current value */
|
|
|
|
OldValue = *FastRef;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Make sure there's enough references to swap */
|
|
|
|
if (!((OldValue.Value ^ (ULONG_PTR)OldObject) <= MAX_FAST_REFS)) break;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Check if we have an object to swap */
|
|
|
|
if (Object)
|
|
|
|
{
|
|
|
|
/* Set up the value with maximum fast references */
|
|
|
|
NewValue.Value = (ULONG_PTR)Object | MAX_FAST_REFS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Write the object address itself (which is empty) */
|
|
|
|
NewValue.Value = (ULONG_PTR)Object;
|
|
|
|
}
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Do the actual compare exchange */
|
|
|
|
NewValue.Object = ExpChangePushlock(&FastRef->Object,
|
|
|
|
NewValue.Object,
|
|
|
|
OldValue.Object);
|
|
|
|
if (NewValue.Object != OldValue.Object) continue;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* All done */
|
|
|
|
break;
|
|
|
|
}
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-03-03 20:24:10 +00:00
|
|
|
/* Return the old value */
|
|
|
|
return OldValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* RUNDOWN *******************************************************************/
|
2005-12-29 19:12:09 +00:00
|
|
|
|
2018-11-17 15:33:22 +00:00
|
|
|
FORCEINLINE
|
|
|
|
PEX_RUNDOWN_REF
|
|
|
|
ExGetRunRefForGivenProcessor(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware,
|
|
|
|
IN ULONG ProcNumber)
|
|
|
|
{
|
|
|
|
return (PEX_RUNDOWN_REF)((ULONG_PTR)RunRefCacheAware->RunRefs +
|
|
|
|
RunRefCacheAware->RunRefSize *
|
|
|
|
(ProcNumber % RunRefCacheAware->Number));
|
|
|
|
}
|
|
|
|
|
2005-12-29 19:12:09 +00:00
|
|
|
/*++
|
|
|
|
* @name ExfAcquireRundownProtection
|
|
|
|
* INTERNAL MACRO
|
|
|
|
*
|
|
|
|
* The ExfAcquireRundownProtection routine acquires rundown protection for
|
|
|
|
* the specified descriptor.
|
|
|
|
*
|
|
|
|
* @param RunRef
|
|
|
|
* Pointer to a rundown reference descriptor.
|
|
|
|
*
|
|
|
|
* @return TRUE if access to the protected structure was granted, FALSE otherwise.
|
|
|
|
*
|
|
|
|
* @remarks This is the internal macro for system use only.In case the rundown
|
|
|
|
* was active, then the slow-path will be called through the exported
|
|
|
|
* function.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
BOOLEAN
|
2006-09-07 05:07:34 +00:00
|
|
|
_ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef)
|
2005-12-29 19:12:09 +00:00
|
|
|
{
|
2007-01-15 21:12:32 +00:00
|
|
|
ULONG_PTR Value, NewValue;
|
2005-12-29 19:12:09 +00:00
|
|
|
|
|
|
|
/* Get the current value and mask the active bit */
|
|
|
|
Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
|
|
|
|
|
|
|
|
/* Add a reference */
|
|
|
|
NewValue = Value + EX_RUNDOWN_COUNT_INC;
|
|
|
|
|
|
|
|
/* Change the value */
|
2007-01-15 21:12:32 +00:00
|
|
|
NewValue = ExpChangeRundown(RunRef, NewValue, Value);
|
|
|
|
if (NewValue != Value)
|
2005-12-29 19:12:09 +00:00
|
|
|
{
|
|
|
|
/* Rundown was active, use long path */
|
|
|
|
return ExfAcquireRundownProtection(RunRef);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Success */
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
* @name ExReleaseRundownProtection
|
|
|
|
* INTERNAL MACRO
|
|
|
|
*
|
|
|
|
* The ExReleaseRundownProtection routine releases rundown protection for
|
|
|
|
* the specified descriptor.
|
|
|
|
*
|
|
|
|
* @param RunRef
|
|
|
|
* Pointer to a rundown reference descriptor.
|
|
|
|
*
|
|
|
|
* @return TRUE if access to the protected structure was granted, FALSE otherwise.
|
|
|
|
*
|
|
|
|
* @remarks This is the internal macro for system use only.In case the rundown
|
|
|
|
* was active, then the slow-path will be called through the exported
|
|
|
|
* function.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
VOID
|
2006-09-07 05:07:34 +00:00
|
|
|
_ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef)
|
2005-12-29 19:12:09 +00:00
|
|
|
{
|
2007-01-15 21:12:32 +00:00
|
|
|
ULONG_PTR Value, NewValue;
|
2005-12-29 19:12:09 +00:00
|
|
|
|
|
|
|
/* Get the current value and mask the active bit */
|
|
|
|
Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
|
|
|
|
|
|
|
|
/* Remove a reference */
|
|
|
|
NewValue = Value - EX_RUNDOWN_COUNT_INC;
|
|
|
|
|
|
|
|
/* Change the value */
|
2007-01-15 21:12:32 +00:00
|
|
|
NewValue = ExpChangeRundown(RunRef, NewValue, Value);
|
2005-12-29 19:12:09 +00:00
|
|
|
|
|
|
|
/* Check if the rundown was active */
|
2007-01-15 21:12:32 +00:00
|
|
|
if (NewValue != Value)
|
2005-12-29 19:12:09 +00:00
|
|
|
{
|
|
|
|
/* Rundown was active, use long path */
|
|
|
|
ExfReleaseRundownProtection(RunRef);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Sanity check */
|
|
|
|
ASSERT((Value >= EX_RUNDOWN_COUNT_INC) || (KeNumberProcessors > 1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
* @name ExInitializeRundownProtection
|
|
|
|
* INTERNAL MACRO
|
|
|
|
*
|
|
|
|
* The ExInitializeRundownProtection routine initializes a rundown
|
|
|
|
* protection descriptor.
|
|
|
|
*
|
|
|
|
* @param RunRef
|
|
|
|
* Pointer to a rundown reference descriptor.
|
|
|
|
*
|
|
|
|
* @return None.
|
|
|
|
*
|
|
|
|
* @remarks This is the internal macro for system use only.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
VOID
|
2006-09-07 05:07:34 +00:00
|
|
|
_ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef)
|
2005-12-29 19:12:09 +00:00
|
|
|
{
|
|
|
|
/* Set the count to zero */
|
|
|
|
RunRef->Count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
* @name ExWaitForRundownProtectionRelease
|
|
|
|
* INTERNAL MACRO
|
|
|
|
*
|
|
|
|
* The ExWaitForRundownProtectionRelease routine waits until the specified
|
|
|
|
* rundown descriptor has been released.
|
|
|
|
*
|
|
|
|
* @param RunRef
|
|
|
|
* Pointer to a rundown reference descriptor.
|
|
|
|
*
|
|
|
|
* @return None.
|
|
|
|
*
|
|
|
|
* @remarks This is the internal macro for system use only. If a wait is actually
|
|
|
|
* necessary, then the slow path is taken through the exported function.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
VOID
|
2006-09-07 05:07:34 +00:00
|
|
|
_ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef)
|
2005-12-29 19:12:09 +00:00
|
|
|
{
|
|
|
|
ULONG_PTR Value;
|
|
|
|
|
|
|
|
/* Set the active bit */
|
|
|
|
Value = ExpChangeRundown(RunRef, EX_RUNDOWN_ACTIVE, 0);
|
2007-01-15 21:12:32 +00:00
|
|
|
if ((Value) && (Value != EX_RUNDOWN_ACTIVE))
|
2005-12-29 19:12:09 +00:00
|
|
|
{
|
|
|
|
/* If the the rundown wasn't already active, then take the long path */
|
|
|
|
ExfWaitForRundownProtectionRelease(RunRef);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
* @name ExRundownCompleted
|
|
|
|
* INTERNAL MACRO
|
|
|
|
*
|
|
|
|
* The ExRundownCompleted routine completes the rundown of the specified
|
|
|
|
* descriptor by setting the active bit.
|
|
|
|
*
|
|
|
|
* @param RunRef
|
|
|
|
* Pointer to a rundown reference descriptor.
|
|
|
|
*
|
|
|
|
* @return None.
|
|
|
|
*
|
|
|
|
* @remarks This is the internal macro for system use only.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
VOID
|
2006-09-07 05:07:34 +00:00
|
|
|
_ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef)
|
2005-12-29 19:12:09 +00:00
|
|
|
{
|
|
|
|
/* Sanity check */
|
|
|
|
ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0);
|
|
|
|
|
|
|
|
/* Mark the counter as active */
|
2010-12-26 22:25:47 +00:00
|
|
|
ExpSetRundown(RunRef, EX_RUNDOWN_ACTIVE);
|
2005-12-29 19:12:09 +00:00
|
|
|
}
|
|
|
|
|
2006-01-03 23:36:05 +00:00
|
|
|
/* PUSHLOCKS *****************************************************************/
|
2005-12-29 19:12:09 +00:00
|
|
|
|
2007-01-22 06:47:44 +00:00
|
|
|
/* FIXME: VERIFY THESE! */
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
2007-01-22 22:16:13 +00:00
|
|
|
ExBlockPushLock(
|
|
|
|
IN PEX_PUSH_LOCK PushLock,
|
|
|
|
IN PVOID WaitBlock
|
|
|
|
);
|
2007-01-22 06:47:44 +00:00
|
|
|
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
2007-01-22 22:16:13 +00:00
|
|
|
ExfUnblockPushLock(
|
|
|
|
IN PEX_PUSH_LOCK PushLock,
|
|
|
|
IN PVOID CurrentWaitBlock
|
|
|
|
);
|
2007-01-22 06:47:44 +00:00
|
|
|
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
2007-01-22 22:16:13 +00:00
|
|
|
ExWaitForUnblockPushLock(
|
|
|
|
IN PEX_PUSH_LOCK PushLock,
|
|
|
|
IN PVOID WaitBlock
|
|
|
|
);
|
2007-01-22 06:47:44 +00:00
|
|
|
|
2006-10-06 19:29:25 +00:00
|
|
|
/*++
|
2010-03-12 16:28:04 +00:00
|
|
|
* @name _ExInitializePushLock
|
2006-10-06 19:29:25 +00:00
|
|
|
* INTERNAL MACRO
|
|
|
|
*
|
2010-03-12 16:28:04 +00:00
|
|
|
* The _ExInitializePushLock macro initializes a PushLock.
|
2006-10-06 19:29:25 +00:00
|
|
|
*
|
|
|
|
* @params PushLock
|
|
|
|
* Pointer to the pushlock which is to be initialized.
|
|
|
|
*
|
|
|
|
* @return None.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
VOID
|
2011-04-08 12:30:33 +00:00
|
|
|
_ExInitializePushLock(OUT PEX_PUSH_LOCK PushLock)
|
2006-10-06 19:29:25 +00:00
|
|
|
{
|
|
|
|
/* Set the value to 0 */
|
2011-04-08 12:30:33 +00:00
|
|
|
PushLock->Ptr = 0;
|
2006-10-06 19:29:25 +00:00
|
|
|
}
|
2010-03-12 16:28:04 +00:00
|
|
|
#define ExInitializePushLock _ExInitializePushLock
|
2006-10-06 19:29:25 +00:00
|
|
|
|
2006-01-03 23:36:05 +00:00
|
|
|
/*++
|
|
|
|
* @name ExAcquirePushLockExclusive
|
|
|
|
* INTERNAL MACRO
|
|
|
|
*
|
|
|
|
* The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
|
|
|
|
*
|
|
|
|
* @params PushLock
|
|
|
|
* Pointer to the pushlock which is to be acquired.
|
|
|
|
*
|
|
|
|
* @return None.
|
|
|
|
*
|
|
|
|
* @remarks The function attempts the quickest route to acquire the lock, which is
|
|
|
|
* to simply set the lock bit.
|
|
|
|
* However, if the pushlock is already shared, the slower path is taken.
|
|
|
|
*
|
|
|
|
* Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
|
|
|
|
* This macro should usually be paired up with KeAcquireCriticalRegion.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
VOID
|
2006-01-03 23:36:05 +00:00
|
|
|
ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
|
|
|
|
{
|
|
|
|
/* Try acquiring the lock */
|
|
|
|
if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V))
|
|
|
|
{
|
|
|
|
/* Someone changed it, use the slow path */
|
|
|
|
ExfAcquirePushLockExclusive(PushLock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sanity check */
|
|
|
|
ASSERT(PushLock->Locked);
|
|
|
|
}
|
|
|
|
|
- Okay so...listen up. First off: When you acquire a lock such as a fast mutex, you should never acquire it recursively.
For example, when you handle a page fault in a section, then page fault while handling that page fault (which is perfectly okay),
you shouldn't be trying to re-acquire the address space lock that you're already holding. After this fix, this scenario works
and countless others. Apps like QTInfo now work and load, and PictureViewer doesn't BSOD the system anymore. I've fixed this by changing
the lock to a pushlock. It not only increases speed inside the memory manager significantly (such as during page fault handling), but
does allow recursive acquisition without any problems.
- Now if that wasn't bad enough, here's a couple more tips. Fast Mutexes actually require APC_LEVEL to be effective. If you're going
to be using a Fast Mutex and calling it with the "Unsafe" version, then don't expect anything to work. Also, using functions like
"CcTryToAcquireBrokenMutex" where correct code is duplicated then hacked to work isn't a big help either. And that's not all. Fast Mutex
disables kernel APCs by setting the KernelApcDisable flag on, and it's expected that the count inside the fast mutex will match the count
inside the thread. In other words, LOCK ACQUISITION AND RELEASE MUST BE ORDERED. You can't acquire LOCK A and B, and then release lock A
and B, because that leads to deadlocks and other issues. So of course, the Cache Manager acquired a view lock, then acquired a segment lock,
then released the view lock, then released the segment lock, then re-acquired the view lock. Uh, no, that won't work. You know what else
doesn't work so well? Disabling APCs about 6-9 times to acquire a single lock, and using spinlocks in the same code path as well. Just how
paranoid are you about thread safety, but still manage to get it wrong? Okay, so we've got recursion, out-of-order lock acquision and
release, made-up "broken" acquire functions, and using a lock that depends on APC_LEVEL at PASSIVE_LEVEL. The best part is when Cc builds
an array of cache segments, and locks each of them... then during release, the list gets parsed head-first, so the first acquired locks
get released first. So locks a, b, c, d get acquired, then a, b, c, d get released. Great! Sounds about right for ReactOS's Cache Manager
design. I've changed the view lock to a guarded mutex -- which actually properly disables APCs and works at PASSIVE_LEVEL, and changed the
segment locks to be push locks. First it'll be 10 times faster then acquiring a bazillion fast mutexes, especially since APCs have already
been disabled at this point, and it also allows you to do most of the stupid things the Cache Manager does. Out-of-order release is still
not going to work well, so eventually on a multi-processor machine the code will completely die -- but at least it'll work on UP for now.
In the end, this makes things like the Inkscape installer and Quicktime Installer to work, and probably countless other things that generated
ASSERTS in the fast mutex code.
-- Alex Ionescu
svn path=/trunk/; revision=30401
2007-11-12 19:00:26 +00:00
|
|
|
/*++
|
|
|
|
* @name ExTryToAcquirePushLockExclusive
|
|
|
|
* INTERNAL MACRO
|
|
|
|
*
|
|
|
|
* The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
|
|
|
|
*
|
|
|
|
* @params PushLock
|
|
|
|
* Pointer to the pushlock which is to be acquired.
|
|
|
|
*
|
|
|
|
* @return None.
|
|
|
|
*
|
|
|
|
* @remarks The function attempts the quickest route to acquire the lock, which is
|
|
|
|
* to simply set the lock bit.
|
|
|
|
* However, if the pushlock is already shared, the slower path is taken.
|
|
|
|
*
|
|
|
|
* Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
|
|
|
|
* This macro should usually be paired up with KeAcquireCriticalRegion.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
BOOLEAN
|
- Okay so...listen up. First off: When you acquire a lock such as a fast mutex, you should never acquire it recursively.
For example, when you handle a page fault in a section, then page fault while handling that page fault (which is perfectly okay),
you shouldn't be trying to re-acquire the address space lock that you're already holding. After this fix, this scenario works
and countless others. Apps like QTInfo now work and load, and PictureViewer doesn't BSOD the system anymore. I've fixed this by changing
the lock to a pushlock. It not only increases speed inside the memory manager significantly (such as during page fault handling), but
does allow recursive acquisition without any problems.
- Now if that wasn't bad enough, here's a couple more tips. Fast Mutexes actually require APC_LEVEL to be effective. If you're going
to be using a Fast Mutex and calling it with the "Unsafe" version, then don't expect anything to work. Also, using functions like
"CcTryToAcquireBrokenMutex" where correct code is duplicated then hacked to work isn't a big help either. And that's not all. Fast Mutex
disables kernel APCs by setting the KernelApcDisable flag on, and it's expected that the count inside the fast mutex will match the count
inside the thread. In other words, LOCK ACQUISITION AND RELEASE MUST BE ORDERED. You can't acquire LOCK A and B, and then release lock A
and B, because that leads to deadlocks and other issues. So of course, the Cache Manager acquired a view lock, then acquired a segment lock,
then released the view lock, then released the segment lock, then re-acquired the view lock. Uh, no, that won't work. You know what else
doesn't work so well? Disabling APCs about 6-9 times to acquire a single lock, and using spinlocks in the same code path as well. Just how
paranoid are you about thread safety, but still manage to get it wrong? Okay, so we've got recursion, out-of-order lock acquision and
release, made-up "broken" acquire functions, and using a lock that depends on APC_LEVEL at PASSIVE_LEVEL. The best part is when Cc builds
an array of cache segments, and locks each of them... then during release, the list gets parsed head-first, so the first acquired locks
get released first. So locks a, b, c, d get acquired, then a, b, c, d get released. Great! Sounds about right for ReactOS's Cache Manager
design. I've changed the view lock to a guarded mutex -- which actually properly disables APCs and works at PASSIVE_LEVEL, and changed the
segment locks to be push locks. First it'll be 10 times faster then acquiring a bazillion fast mutexes, especially since APCs have already
been disabled at this point, and it also allows you to do most of the stupid things the Cache Manager does. Out-of-order release is still
not going to work well, so eventually on a multi-processor machine the code will completely die -- but at least it'll work on UP for now.
In the end, this makes things like the Inkscape installer and Quicktime Installer to work, and probably countless other things that generated
ASSERTS in the fast mutex code.
-- Alex Ionescu
svn path=/trunk/; revision=30401
2007-11-12 19:00:26 +00:00
|
|
|
ExTryToAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
|
|
|
|
{
|
|
|
|
/* Try acquiring the lock */
|
|
|
|
if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V))
|
|
|
|
{
|
|
|
|
/* Can't acquire */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Got acquired */
|
2008-04-01 18:14:01 +00:00
|
|
|
ASSERT (PushLock->Locked);
|
- Okay so...listen up. First off: When you acquire a lock such as a fast mutex, you should never acquire it recursively.
For example, when you handle a page fault in a section, then page fault while handling that page fault (which is perfectly okay),
you shouldn't be trying to re-acquire the address space lock that you're already holding. After this fix, this scenario works
and countless others. Apps like QTInfo now work and load, and PictureViewer doesn't BSOD the system anymore. I've fixed this by changing
the lock to a pushlock. It not only increases speed inside the memory manager significantly (such as during page fault handling), but
does allow recursive acquisition without any problems.
- Now if that wasn't bad enough, here's a couple more tips. Fast Mutexes actually require APC_LEVEL to be effective. If you're going
to be using a Fast Mutex and calling it with the "Unsafe" version, then don't expect anything to work. Also, using functions like
"CcTryToAcquireBrokenMutex" where correct code is duplicated then hacked to work isn't a big help either. And that's not all. Fast Mutex
disables kernel APCs by setting the KernelApcDisable flag on, and it's expected that the count inside the fast mutex will match the count
inside the thread. In other words, LOCK ACQUISITION AND RELEASE MUST BE ORDERED. You can't acquire LOCK A and B, and then release lock A
and B, because that leads to deadlocks and other issues. So of course, the Cache Manager acquired a view lock, then acquired a segment lock,
then released the view lock, then released the segment lock, then re-acquired the view lock. Uh, no, that won't work. You know what else
doesn't work so well? Disabling APCs about 6-9 times to acquire a single lock, and using spinlocks in the same code path as well. Just how
paranoid are you about thread safety, but still manage to get it wrong? Okay, so we've got recursion, out-of-order lock acquision and
release, made-up "broken" acquire functions, and using a lock that depends on APC_LEVEL at PASSIVE_LEVEL. The best part is when Cc builds
an array of cache segments, and locks each of them... then during release, the list gets parsed head-first, so the first acquired locks
get released first. So locks a, b, c, d get acquired, then a, b, c, d get released. Great! Sounds about right for ReactOS's Cache Manager
design. I've changed the view lock to a guarded mutex -- which actually properly disables APCs and works at PASSIVE_LEVEL, and changed the
segment locks to be push locks. First it'll be 10 times faster then acquiring a bazillion fast mutexes, especially since APCs have already
been disabled at this point, and it also allows you to do most of the stupid things the Cache Manager does. Out-of-order release is still
not going to work well, so eventually on a multi-processor machine the code will completely die -- but at least it'll work on UP for now.
In the end, this makes things like the Inkscape installer and Quicktime Installer to work, and probably countless other things that generated
ASSERTS in the fast mutex code.
-- Alex Ionescu
svn path=/trunk/; revision=30401
2007-11-12 19:00:26 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2006-01-03 23:36:05 +00:00
|
|
|
/*++
|
|
|
|
* @name ExAcquirePushLockShared
|
|
|
|
* INTERNAL MACRO
|
|
|
|
*
|
|
|
|
* The ExAcquirePushLockShared macro acquires a shared PushLock.
|
|
|
|
*
|
|
|
|
* @params PushLock
|
|
|
|
* Pointer to the pushlock which is to be acquired.
|
|
|
|
*
|
|
|
|
* @return None.
|
|
|
|
*
|
|
|
|
* @remarks The function attempts the quickest route to acquire the lock, which is
|
|
|
|
* to simply set the lock bit and set the share count to one.
|
|
|
|
* However, if the pushlock is already shared, the slower path is taken.
|
|
|
|
*
|
|
|
|
* Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
|
|
|
|
* This macro should usually be paired up with KeAcquireCriticalRegion.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
VOID
|
2006-01-03 23:36:05 +00:00
|
|
|
ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
|
|
|
|
{
|
|
|
|
EX_PUSH_LOCK NewValue;
|
|
|
|
|
|
|
|
/* Try acquiring the lock */
|
|
|
|
NewValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
|
2006-10-06 19:29:25 +00:00
|
|
|
if (ExpChangePushlock(PushLock, NewValue.Ptr, 0))
|
2006-01-03 23:36:05 +00:00
|
|
|
{
|
|
|
|
/* Someone changed it, use the slow path */
|
|
|
|
ExfAcquirePushLockShared(PushLock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sanity checks */
|
|
|
|
ASSERT(PushLock->Locked);
|
|
|
|
}
|
|
|
|
|
2006-10-06 19:29:25 +00:00
|
|
|
/*++
|
|
|
|
* @name ExConvertPushLockSharedToExclusive
|
|
|
|
* INTERNAL MACRO
|
|
|
|
*
|
|
|
|
* The ExConvertPushLockSharedToExclusive macro converts an exclusive
|
|
|
|
* pushlock to a shared pushlock.
|
|
|
|
*
|
|
|
|
* @params PushLock
|
|
|
|
* Pointer to the pushlock which is to be converted.
|
|
|
|
*
|
|
|
|
* @return FALSE if conversion failed, TRUE otherwise.
|
|
|
|
*
|
|
|
|
* @remarks The function attempts the quickest route to convert the lock, which is
|
|
|
|
* to simply set the lock bit and remove any other bits.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
BOOLEAN
|
2006-10-06 19:29:25 +00:00
|
|
|
ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock)
|
|
|
|
{
|
|
|
|
EX_PUSH_LOCK OldValue;
|
|
|
|
|
|
|
|
/* Set the expected old value */
|
|
|
|
OldValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
|
|
|
|
|
|
|
|
/* Try converting the lock */
|
|
|
|
if (ExpChangePushlock(PushLock, EX_PUSH_LOCK_LOCK, OldValue.Value) !=
|
|
|
|
OldValue.Ptr)
|
|
|
|
{
|
|
|
|
/* Conversion failed */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sanity check */
|
|
|
|
ASSERT(PushLock->Locked);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2006-01-03 23:36:05 +00:00
|
|
|
/*++
|
|
|
|
* @name ExWaitOnPushLock
|
|
|
|
* INTERNAL MACRO
|
|
|
|
*
|
|
|
|
* The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
|
|
|
|
*
|
|
|
|
* @params PushLock
|
|
|
|
* Pointer to a pushlock.
|
|
|
|
*
|
|
|
|
* @return None.
|
|
|
|
*
|
|
|
|
* @remarks The function attempts to get any exclusive waiters out of their slow
|
|
|
|
* path by forcing an instant acquire/release operation.
|
|
|
|
*
|
|
|
|
* Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
VOID
|
2006-01-03 23:36:05 +00:00
|
|
|
ExWaitOnPushLock(PEX_PUSH_LOCK PushLock)
|
2007-10-19 23:21:45 +00:00
|
|
|
{
|
2007-01-22 06:47:44 +00:00
|
|
|
/* Check if we're locked */
|
|
|
|
if (PushLock->Locked)
|
|
|
|
{
|
|
|
|
/* Acquire the lock */
|
|
|
|
ExfAcquirePushLockExclusive(PushLock);
|
|
|
|
ASSERT(PushLock->Locked);
|
2006-01-03 23:36:05 +00:00
|
|
|
|
2007-01-22 06:47:44 +00:00
|
|
|
/* Release it */
|
|
|
|
ExfReleasePushLockExclusive(PushLock);
|
|
|
|
}
|
2006-01-03 23:36:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
* @name ExReleasePushLockShared
|
|
|
|
* INTERNAL MACRO
|
|
|
|
*
|
|
|
|
* The ExReleasePushLockShared macro releases a previously acquired PushLock.
|
|
|
|
*
|
|
|
|
* @params PushLock
|
|
|
|
* Pointer to a previously acquired pushlock.
|
|
|
|
*
|
|
|
|
* @return None.
|
|
|
|
*
|
2007-10-19 23:21:45 +00:00
|
|
|
* @remarks The function attempts the quickest route to release the lock, which is
|
2006-01-03 23:36:05 +00:00
|
|
|
* to simply decrease the share count and remove the lock bit.
|
|
|
|
* However, if the pushlock is being waited on then the long path is taken.
|
|
|
|
*
|
|
|
|
* Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
|
|
|
|
* This macro should usually be paired up with KeLeaveCriticalRegion.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
VOID
|
2006-01-03 23:36:05 +00:00
|
|
|
ExReleasePushLockShared(PEX_PUSH_LOCK PushLock)
|
|
|
|
{
|
|
|
|
EX_PUSH_LOCK OldValue;
|
|
|
|
|
|
|
|
/* Sanity checks */
|
|
|
|
ASSERT(PushLock->Locked);
|
|
|
|
|
|
|
|
/* Try to clear the pushlock */
|
|
|
|
OldValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
|
2006-10-06 19:29:25 +00:00
|
|
|
if (ExpChangePushlock(PushLock, 0, OldValue.Ptr) != OldValue.Ptr)
|
2006-01-03 23:36:05 +00:00
|
|
|
{
|
|
|
|
/* There are still other people waiting on it */
|
|
|
|
ExfReleasePushLockShared(PushLock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
* @name ExReleasePushLockExclusive
|
|
|
|
* INTERNAL MACRO
|
|
|
|
*
|
|
|
|
* The ExReleasePushLockExclusive macro releases a previously
|
|
|
|
* exclusively acquired PushLock.
|
|
|
|
*
|
|
|
|
* @params PushLock
|
|
|
|
* Pointer to a previously acquired pushlock.
|
|
|
|
*
|
|
|
|
* @return None.
|
|
|
|
*
|
|
|
|
* @remarks The function attempts the quickest route to release the lock, which is
|
|
|
|
* to simply clear the locked bit.
|
|
|
|
* However, if the pushlock is being waited on, the slow path is taken
|
|
|
|
* in an attempt to wake up the lock.
|
|
|
|
*
|
|
|
|
* Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
|
|
|
|
* This macro should usually be paired up with KeLeaveCriticalRegion.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
VOID
|
2006-01-03 23:36:05 +00:00
|
|
|
ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
|
|
|
|
{
|
|
|
|
EX_PUSH_LOCK OldValue;
|
|
|
|
|
|
|
|
/* Sanity checks */
|
|
|
|
ASSERT(PushLock->Locked);
|
|
|
|
|
|
|
|
/* Unlock the pushlock */
|
2009-03-18 17:03:58 +00:00
|
|
|
OldValue.Value = InterlockedExchangeAddSizeT((PSIZE_T)PushLock,
|
2011-02-10 13:01:39 +00:00
|
|
|
-(SSIZE_T)EX_PUSH_LOCK_LOCK);
|
2006-01-03 23:36:05 +00:00
|
|
|
|
|
|
|
/* Sanity checks */
|
|
|
|
ASSERT(OldValue.Locked);
|
|
|
|
ASSERT(OldValue.Waiting || OldValue.Shared == 0);
|
|
|
|
|
|
|
|
/* Check if anyone is waiting on it and it's not already waking*/
|
|
|
|
if ((OldValue.Waiting) && !(OldValue.Waking))
|
|
|
|
{
|
|
|
|
/* Wake it up */
|
|
|
|
ExfTryToWakePushLock(PushLock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
* @name ExReleasePushLock
|
|
|
|
* INTERNAL MACRO
|
|
|
|
*
|
|
|
|
* The ExReleasePushLock macro releases a previously acquired PushLock.
|
|
|
|
*
|
|
|
|
* @params PushLock
|
|
|
|
* Pointer to a previously acquired pushlock.
|
|
|
|
*
|
|
|
|
* @return None.
|
|
|
|
*
|
2007-10-19 23:21:45 +00:00
|
|
|
* @remarks The function attempts the quickest route to release the lock, which is
|
2006-01-03 23:36:05 +00:00
|
|
|
* to simply clear all the fields and decrease the share count if required.
|
|
|
|
* However, if the pushlock is being waited on then the long path is taken.
|
|
|
|
*
|
|
|
|
* Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL.
|
|
|
|
* This macro should usually be paired up with KeLeaveCriticalRegion.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:33 +00:00
|
|
|
VOID
|
2006-01-03 23:36:05 +00:00
|
|
|
ExReleasePushLock(PEX_PUSH_LOCK PushLock)
|
|
|
|
{
|
|
|
|
EX_PUSH_LOCK OldValue = *PushLock;
|
|
|
|
EX_PUSH_LOCK NewValue;
|
|
|
|
|
|
|
|
/* Sanity checks */
|
|
|
|
ASSERT(OldValue.Locked);
|
|
|
|
|
|
|
|
/* Check if the pushlock is shared */
|
|
|
|
if (OldValue.Shared > 1)
|
|
|
|
{
|
|
|
|
/* Decrease the share count */
|
2007-04-11 08:43:34 +00:00
|
|
|
NewValue.Value = OldValue.Value - EX_PUSH_LOCK_SHARE_INC;
|
2006-01-03 23:36:05 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Clear the pushlock entirely */
|
|
|
|
NewValue.Value = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if nobody is waiting on us and try clearing the lock here */
|
|
|
|
if ((OldValue.Waiting) ||
|
2007-01-08 07:43:49 +00:00
|
|
|
(ExpChangePushlock(PushLock, NewValue.Ptr, OldValue.Ptr) !=
|
2006-01-03 23:36:05 +00:00
|
|
|
OldValue.Ptr))
|
|
|
|
{
|
|
|
|
/* We have waiters, use the long path */
|
|
|
|
ExfReleasePushLock(PushLock);
|
|
|
|
}
|
|
|
|
}
|
2005-12-29 19:12:09 +00:00
|
|
|
|
2009-01-30 16:45:17 +00:00
|
|
|
/* FAST MUTEX INLINES *********************************************************/
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
VOID
|
|
|
|
_ExAcquireFastMutexUnsafe(IN PFAST_MUTEX FastMutex)
|
|
|
|
{
|
|
|
|
PKTHREAD Thread = KeGetCurrentThread();
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-01-30 16:45:17 +00:00
|
|
|
/* Sanity check */
|
|
|
|
ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
|
|
|
|
(Thread->CombinedApcDisable != 0) ||
|
|
|
|
(Thread->Teb == NULL) ||
|
|
|
|
(Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
|
|
|
|
ASSERT(FastMutex->Owner != Thread);
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-01-30 16:45:17 +00:00
|
|
|
/* Decrease the count */
|
|
|
|
if (InterlockedDecrement(&FastMutex->Count))
|
|
|
|
{
|
|
|
|
/* Someone is still holding it, use slow path */
|
|
|
|
KiAcquireFastMutex(FastMutex);
|
|
|
|
}
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-01-30 16:45:17 +00:00
|
|
|
/* Set the owner */
|
|
|
|
FastMutex->Owner = Thread;
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
VOID
|
|
|
|
_ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
|
|
|
|
{
|
|
|
|
ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
|
|
|
|
(KeGetCurrentThread()->CombinedApcDisable != 0) ||
|
|
|
|
(KeGetCurrentThread()->Teb == NULL) ||
|
|
|
|
(KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
|
|
|
|
ASSERT(FastMutex->Owner == KeGetCurrentThread());
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-01-30 16:45:17 +00:00
|
|
|
/* Erase the owner */
|
|
|
|
FastMutex->Owner = NULL;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-01-30 16:45:17 +00:00
|
|
|
/* Increase the count */
|
|
|
|
if (InterlockedIncrement(&FastMutex->Count) <= 0)
|
|
|
|
{
|
|
|
|
/* Someone was waiting for it, signal the waiter */
|
2010-03-03 16:03:14 +00:00
|
|
|
KeSetEventBoostPriority(&FastMutex->Event, NULL);
|
2009-01-30 16:45:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
VOID
|
|
|
|
_ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
|
|
|
|
{
|
|
|
|
KIRQL OldIrql;
|
|
|
|
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-01-30 16:45:17 +00:00
|
|
|
/* Raise IRQL to APC */
|
|
|
|
KeRaiseIrql(APC_LEVEL, &OldIrql);
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-01-30 16:45:17 +00:00
|
|
|
/* Decrease the count */
|
|
|
|
if (InterlockedDecrement(&FastMutex->Count))
|
|
|
|
{
|
|
|
|
/* Someone is still holding it, use slow path */
|
|
|
|
KiAcquireFastMutex(FastMutex);
|
|
|
|
}
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-01-30 16:45:17 +00:00
|
|
|
/* Set the owner and IRQL */
|
|
|
|
FastMutex->Owner = KeGetCurrentThread();
|
|
|
|
FastMutex->OldIrql = OldIrql;
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
VOID
|
|
|
|
_ExReleaseFastMutex(IN OUT PFAST_MUTEX FastMutex)
|
|
|
|
{
|
|
|
|
KIRQL OldIrql;
|
|
|
|
ASSERT(KeGetCurrentIrql() == APC_LEVEL);
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-01-30 16:45:17 +00:00
|
|
|
/* Erase the owner */
|
|
|
|
FastMutex->Owner = NULL;
|
|
|
|
OldIrql = (KIRQL)FastMutex->OldIrql;
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-01-30 16:45:17 +00:00
|
|
|
/* Increase the count */
|
|
|
|
if (InterlockedIncrement(&FastMutex->Count) <= 0)
|
|
|
|
{
|
|
|
|
/* Someone was waiting for it, signal the waiter */
|
2010-03-03 16:03:14 +00:00
|
|
|
KeSetEventBoostPriority(&FastMutex->Event, NULL);
|
2009-01-30 16:45:17 +00:00
|
|
|
}
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-01-30 16:45:17 +00:00
|
|
|
/* Lower IRQL back */
|
|
|
|
KeLowerIrql(OldIrql);
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
BOOLEAN
|
|
|
|
_ExTryToAcquireFastMutex(IN OUT PFAST_MUTEX FastMutex)
|
|
|
|
{
|
|
|
|
KIRQL OldIrql;
|
|
|
|
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-01-30 16:45:17 +00:00
|
|
|
/* Raise to APC_LEVEL */
|
|
|
|
KeRaiseIrql(APC_LEVEL, &OldIrql);
|
2010-12-26 22:25:47 +00:00
|
|
|
|
2009-01-30 16:45:17 +00:00
|
|
|
/* Check if we can quickly acquire it */
|
|
|
|
if (InterlockedCompareExchange(&FastMutex->Count, 0, 1) == 1)
|
|
|
|
{
|
|
|
|
/* We have, set us as owners */
|
|
|
|
FastMutex->Owner = KeGetCurrentThread();
|
|
|
|
FastMutex->OldIrql = OldIrql;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Acquire attempt failed */
|
|
|
|
KeLowerIrql(OldIrql);
|
|
|
|
YieldProcessor();
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
VOID
|
|
|
|
_ExEnterCriticalRegionAndAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
|
|
|
|
{
|
|
|
|
/* Enter the Critical Region */
|
|
|
|
KeEnterCriticalRegion();
|
|
|
|
|
|
|
|
/* Acquire the mutex unsafely */
|
|
|
|
_ExAcquireFastMutexUnsafe(FastMutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
VOID
|
|
|
|
_ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(IN OUT PFAST_MUTEX FastMutex)
|
|
|
|
{
|
|
|
|
/* Release the mutex unsafely */
|
|
|
|
_ExReleaseFastMutexUnsafe(FastMutex);
|
|
|
|
|
|
|
|
/* Leave the critical region */
|
|
|
|
KeLeaveCriticalRegion();
|
|
|
|
}
|
|
|
|
|
2003-09-10 06:12:22 +00:00
|
|
|
/* OTHER FUNCTIONS **********************************************************/
|
|
|
|
|
2008-06-02 10:21:49 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
ExTryToAcquireResourceExclusiveLite(
|
|
|
|
IN PERESOURCE Resource
|
|
|
|
);
|
|
|
|
|
2004-12-01 14:28:54 +00:00
|
|
|
NTSTATUS
|
2015-09-28 07:44:49 +00:00
|
|
|
ExpSetTimeZoneInformation(
|
2018-05-31 15:48:29 +00:00
|
|
|
IN PRTL_TIME_ZONE_INFORMATION TimeZoneInformation
|
2015-09-28 07:44:49 +00:00
|
|
|
);
|
2004-12-01 14:28:54 +00:00
|
|
|
|
- Add EXCEPTION_RECORD64 and LIST_ENTRY64, KeTryToAcquireSpinLockAtDpcLevel, BREAKPOINT_COMMAND_STRING, Ke386SetCr2, Ke386SetDr3, Ke386SetDr6.
- Remove non-kernel routines from kdfuncs.h and remove deprecated routines from ke.h.
- Implement KiRestoreProcessorControlState, KeFreezeExecution, KeThawExecution, ExAcquireTimeRefreshLock, ExReleaseTimeRefreshLock.
- Rename ModuleLoadList to PsLoadedModuleList. Add PsNtosImageBase and set value in it.
- Add skeleton wdbgexts.h with what's needed until now, this is a PSDK header.
- Add kddll.h for KDCOM/1394/USB2.DLL prototypes.
- Add windbgkd.h with KD protocol definitions. Used to be an NT5 DDK header, but was removed, so this goes into include\reactos.
svn path=/branches/alex-kd-branch/; revision=25833
2007-02-18 07:21:03 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
2015-09-28 07:44:49 +00:00
|
|
|
ExAcquireTimeRefreshLock(
|
|
|
|
IN BOOLEAN Wait
|
|
|
|
);
|
- Add EXCEPTION_RECORD64 and LIST_ENTRY64, KeTryToAcquireSpinLockAtDpcLevel, BREAKPOINT_COMMAND_STRING, Ke386SetCr2, Ke386SetDr3, Ke386SetDr6.
- Remove non-kernel routines from kdfuncs.h and remove deprecated routines from ke.h.
- Implement KiRestoreProcessorControlState, KeFreezeExecution, KeThawExecution, ExAcquireTimeRefreshLock, ExReleaseTimeRefreshLock.
- Rename ModuleLoadList to PsLoadedModuleList. Add PsNtosImageBase and set value in it.
- Add skeleton wdbgexts.h with what's needed until now, this is a PSDK header.
- Add kddll.h for KDCOM/1394/USB2.DLL prototypes.
- Add windbgkd.h with KD protocol definitions. Used to be an NT5 DDK header, but was removed, so this goes into include\reactos.
svn path=/branches/alex-kd-branch/; revision=25833
2007-02-18 07:21:03 +00:00
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
2015-09-28 07:44:49 +00:00
|
|
|
ExReleaseTimeRefreshLock(
|
|
|
|
VOID
|
|
|
|
);
|
- Add EXCEPTION_RECORD64 and LIST_ENTRY64, KeTryToAcquireSpinLockAtDpcLevel, BREAKPOINT_COMMAND_STRING, Ke386SetCr2, Ke386SetDr3, Ke386SetDr6.
- Remove non-kernel routines from kdfuncs.h and remove deprecated routines from ke.h.
- Implement KiRestoreProcessorControlState, KeFreezeExecution, KeThawExecution, ExAcquireTimeRefreshLock, ExReleaseTimeRefreshLock.
- Rename ModuleLoadList to PsLoadedModuleList. Add PsNtosImageBase and set value in it.
- Add skeleton wdbgexts.h with what's needed until now, this is a PSDK header.
- Add kddll.h for KDCOM/1394/USB2.DLL prototypes.
- Add windbgkd.h with KD protocol definitions. Used to be an NT5 DDK header, but was removed, so this goes into include\reactos.
svn path=/branches/alex-kd-branch/; revision=25833
2007-02-18 07:21:03 +00:00
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
2015-09-28 07:44:49 +00:00
|
|
|
ExUpdateSystemTimeFromCmos(
|
|
|
|
IN BOOLEAN UpdateInterruptTime,
|
|
|
|
IN ULONG MaxSepInSeconds
|
|
|
|
);
|
- Add EXCEPTION_RECORD64 and LIST_ENTRY64, KeTryToAcquireSpinLockAtDpcLevel, BREAKPOINT_COMMAND_STRING, Ke386SetCr2, Ke386SetDr3, Ke386SetDr6.
- Remove non-kernel routines from kdfuncs.h and remove deprecated routines from ke.h.
- Implement KiRestoreProcessorControlState, KeFreezeExecution, KeThawExecution, ExAcquireTimeRefreshLock, ExReleaseTimeRefreshLock.
- Rename ModuleLoadList to PsLoadedModuleList. Add PsNtosImageBase and set value in it.
- Add skeleton wdbgexts.h with what's needed until now, this is a PSDK header.
- Add kddll.h for KDCOM/1394/USB2.DLL prototypes.
- Add windbgkd.h with KD protocol definitions. Used to be an NT5 DDK header, but was removed, so this goes into include\reactos.
svn path=/branches/alex-kd-branch/; revision=25833
2007-02-18 07:21:03 +00:00
|
|
|
|
2015-09-28 07:44:49 +00:00
|
|
|
VOID
|
2005-09-13 23:28:21 +00:00
|
|
|
NTAPI
|
2015-09-28 07:44:49 +00:00
|
|
|
ExAllocateLocallyUniqueId(
|
|
|
|
OUT LUID *LocallyUniqueId
|
|
|
|
);
|
2005-02-14 00:28:12 +00:00
|
|
|
|
Thread/Process Termination/Repeaing Rewrite + Fixes
---------------------------------------------------
- ps/cid.c:
* Moved CID Lookup functions here
- ps/security.c:
* Moved all security related functions here. Makes other files neater and security functions
easier to locate.
- ps/thread.c:
* Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and
renamed functions from Ps to Ki.
* Implemented PsIsSystemThread.
* Removed Reaper Thread Init (now obsolete).
* Renamed PiDeleteThread to PspDeleteThread.
* Moved Thread State functions from tinfo.c to here.
- ps/process.c:
* Removed Query/Set Process functions and moved to ps/query.c
* Renamed PiDeletePRocess to PspDeleteProcess
* Removed obsoleted Process Termination functions, moved persistent one to kill.c
- ps/create.c:
* Moved the security APIs to security.c
* Correctly implemented PsCreateSystemThread to actually create system threads.
- ps/suspend.c
* Rewrote Nt Executive functions to use Kernel functions.
* Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in
some aspects, especially the issue of the APC looping around the KeWaitXxx call and the
fact that the routines excluded/ignored the FreezeCount.
- ps/debug.c
* Fixed completely broken implementation of Get/SetThreadContext. The old version crashed
when called and did not work at all. Suspend Regression test now works.
* Moved Context<->TrapFrame functions to ke/i386/
* Combined Set/GetThreadContext APCs into a single one, and used special context structure.
- ps/query.c:
* Moved Thread/Process Query/Set Routines here.
- ps/tinfo.c:
* Removed.
- ps/kill.c
* Removed complicated Process Termination semantics and useless Attach/Detach in favor for
a much more lightweight function which performs the same tasks as before and actually works.
TaskManager can now terminate foreign processes.
* Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled
thread. This results in much less code as well as an increase in speed and less micro
management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without
requiring masks that were added as hacks to allow it.
* Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new
termination code.
* Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done
by Hartmut.
* Added PspDeletethread here.
* Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out-
lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions,
actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown,
and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate
Thread as documented.
* Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to
be compatible with the changes above.
* Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described
above, and moved each subsystem specific termination helper into its own subsytem.
* Improved NtTerminateProcess and added more debugging messages.
* Improved NtTerminateThread and added check against System Thread and made it compatible with
new implementation.
* Corrected PsTerminateSystemThread now that we support System Threads.
* Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the
port, and added tag to pool allocation (documented in pooltag.txt)
include/internal/*.h:
* Defined Scheduler Functions and misc new functions or renamed functions.
ke/apc.c:
* Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated
to a thread, as well as their APCs and DPCs.
REGRESSIONS FOUND: NONE
BUGS/REGRESSIOSN FIXED:
* Thread/Get Set Context now works.
* Suspend Regression test now works.
* Task manager can now kill foreign processes, even hung ones (like it should).
* ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks.
KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right
places. I just wanted to have this first part ready first, so that it won't get too big.
svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
|
|
|
VOID
|
2006-09-06 12:19:00 +00:00
|
|
|
NTAPI
|
2015-09-28 07:44:49 +00:00
|
|
|
ExTimerRundown(
|
|
|
|
VOID
|
|
|
|
);
|
Thread/Process Termination/Repeaing Rewrite + Fixes
---------------------------------------------------
- ps/cid.c:
* Moved CID Lookup functions here
- ps/security.c:
* Moved all security related functions here. Makes other files neater and security functions
easier to locate.
- ps/thread.c:
* Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and
renamed functions from Ps to Ki.
* Implemented PsIsSystemThread.
* Removed Reaper Thread Init (now obsolete).
* Renamed PiDeleteThread to PspDeleteThread.
* Moved Thread State functions from tinfo.c to here.
- ps/process.c:
* Removed Query/Set Process functions and moved to ps/query.c
* Renamed PiDeletePRocess to PspDeleteProcess
* Removed obsoleted Process Termination functions, moved persistent one to kill.c
- ps/create.c:
* Moved the security APIs to security.c
* Correctly implemented PsCreateSystemThread to actually create system threads.
- ps/suspend.c
* Rewrote Nt Executive functions to use Kernel functions.
* Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in
some aspects, especially the issue of the APC looping around the KeWaitXxx call and the
fact that the routines excluded/ignored the FreezeCount.
- ps/debug.c
* Fixed completely broken implementation of Get/SetThreadContext. The old version crashed
when called and did not work at all. Suspend Regression test now works.
* Moved Context<->TrapFrame functions to ke/i386/
* Combined Set/GetThreadContext APCs into a single one, and used special context structure.
- ps/query.c:
* Moved Thread/Process Query/Set Routines here.
- ps/tinfo.c:
* Removed.
- ps/kill.c
* Removed complicated Process Termination semantics and useless Attach/Detach in favor for
a much more lightweight function which performs the same tasks as before and actually works.
TaskManager can now terminate foreign processes.
* Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled
thread. This results in much less code as well as an increase in speed and less micro
management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without
requiring masks that were added as hacks to allow it.
* Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new
termination code.
* Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done
by Hartmut.
* Added PspDeletethread here.
* Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out-
lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions,
actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown,
and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate
Thread as documented.
* Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to
be compatible with the changes above.
* Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described
above, and moved each subsystem specific termination helper into its own subsytem.
* Improved NtTerminateProcess and added more debugging messages.
* Improved NtTerminateThread and added check against System Thread and made it compatible with
new implementation.
* Corrected PsTerminateSystemThread now that we support System Threads.
* Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the
port, and added tag to pool allocation (documented in pooltag.txt)
include/internal/*.h:
* Defined Scheduler Functions and misc new functions or renamed functions.
ke/apc.c:
* Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated
to a thread, as well as their APCs and DPCs.
REGRESSIONS FOUND: NONE
BUGS/REGRESSIOSN FIXED:
* Thread/Get Set Context now works.
* Suspend Regression test now works.
* Task manager can now kill foreign processes, even hung ones (like it should).
* ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks.
KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right
places. I just wanted to have this first part ready first, so that it won't get too big.
svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2007-05-08 21:35:10 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
HeadlessInit(
|
|
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
|
|
);
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
CODE_SEG("INIT")
|
2007-05-08 21:35:10 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
XIPInit(
|
|
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
|
|
);
|
|
|
|
|
2004-12-24 17:07:00 +00:00
|
|
|
#define InterlockedDecrementUL(Addend) \
|
|
|
|
(ULONG)InterlockedDecrement((PLONG)(Addend))
|
|
|
|
|
|
|
|
#define InterlockedIncrementUL(Addend) \
|
|
|
|
(ULONG)InterlockedIncrement((PLONG)(Addend))
|
|
|
|
|
|
|
|
#define InterlockedExchangeUL(Target, Value) \
|
|
|
|
(ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
|
|
|
|
|
|
|
|
#define InterlockedExchangeAddUL(Addend, Value) \
|
|
|
|
(ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
|
|
|
|
|
|
|
|
#define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \
|
|
|
|
(ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
|
|
|
|
|
2018-01-29 19:31:07 +00:00
|
|
|
#define InterlockedCompareExchangeSizeT(Destination, Exchange, Comperand) \
|
|
|
|
(SIZE_T)InterlockedCompareExchangePointer((PVOID*)(Destination), (PVOID)(SIZE_T)(Exchange), (PVOID)(SIZE_T)(Comperand))
|
|
|
|
|
2022-01-02 19:21:22 +00:00
|
|
|
#ifdef _WIN64
|
|
|
|
#define InterlockedExchangeSizeT(Target, Value) \
|
|
|
|
(SIZE_T)InterlockedExchange64((PLONG64)Target, (LONG64)Value)
|
|
|
|
#else
|
|
|
|
#define InterlockedExchangeSizeT(Target, Value) \
|
|
|
|
(SIZE_T)InterlockedExchange((PLONG)Target, (LONG)Value)
|
|
|
|
#endif
|
|
|
|
|
2004-12-24 17:07:00 +00:00
|
|
|
#define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \
|
|
|
|
(ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))
|
2021-03-26 08:32:34 +00:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
} // extern "C"
|
|
|
|
#endif
|