extern TIME_ZONE_INFORMATION ExpTimeZoneInfo;
extern LARGE_INTEGER ExpTimeZoneBias;
extern ULONG ExpTimeZoneId;
+extern ULONG ExpTickCountMultiplier;
+extern ULONG ExpLastTimeZoneBias;
extern POBJECT_TYPE ExEventPairObjectType;
+extern POBJECT_TYPE _ExEventObjectType, _ExSemaphoreObjectType;
extern ULONG NtBuildNumber;
extern ULONG NtMajorVersion;
extern ULONG NtMinorVersion;
extern FAST_MUTEX ExpEnvironmentLock;
extern ERESOURCE ExpFirmwareTableResource;
extern LIST_ENTRY ExpFirmwareTableProviderListHead;
+extern BOOLEAN ExpIsWinPEMode;
+ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
+ULONG ExpUnicodeCaseTableDataOffset;
+PVOID ExpNlsSectionPointer;
#define MAX_FAST_REFS 7
#ifndef CONFIG_SMP
#define ExAcquireResourceLock(l, i) { \
(void)i; \
- Ke386DisableInterrupts(); \
+ _disable(); \
}
-#define ExReleaseResourceLock(l, i) Ke386EnableInterrupts();
+#define ExReleaseResourceLock(l, i) _enable();
#else
#define ExAcquireResourceLock(l, i) KeAcquireSpinLock(l, i);
#define ExReleaseResourceLock(l, i) KeReleaseSpinLock(l, i);
#define ExInitializeRundownProtection _ExInitializeRundownProtection
#define ExWaitForRundownProtectionRelease _ExWaitForRundownProtectionRelease
#define ExRundownCompleted _ExRundownCompleted
+#define ExGetPreviousMode KeGetPreviousMode
+
+//
+// Detect GCC 4.1.2+
+//
+#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40102
+
+//
+// Broken GCC with Alignment Bug. We'll do alignment ourselves at higher cost.
+//
+#define DEFINE_WAIT_BLOCK(x) \
+ struct _AlignHack \
+ { \
+ UCHAR Hack[15]; \
+ EX_PUSH_LOCK_WAIT_BLOCK UnalignedBlock; \
+ } WaitBlockBuffer; \
+ PEX_PUSH_LOCK_WAIT_BLOCK x = (PEX_PUSH_LOCK_WAIT_BLOCK) \
+ ((ULONG_PTR)&WaitBlockBuffer.UnalignedBlock &~ 0xF);
+
+#else
+
+//
+// This is only for compatibility; the compiler will optimize the extra
+// local variable (the actual pointer) away, so we don't take any perf hit
+// by doing this.
+//
+#define DEFINE_WAIT_BLOCK(x) \
+ EX_PUSH_LOCK_WAIT_BLOCK WaitBlockBuffer; \
+ PEX_PUSH_LOCK_WAIT_BLOCK x = &WaitBlockBuffer;
+
+#endif
/* INITIALIZATION FUNCTIONS *************************************************/
VOID
NTAPI
-ExpInitTimeZoneInfo(VOID);
+ExpInitializePushLocks(VOID);
+
+BOOLEAN
+NTAPI
+ExRefreshTimeZoneInformation(
+ IN PLARGE_INTEGER SystemBootTime
+);
VOID
NTAPI
NTAPI
ExInitPoolLookasidePointers(VOID);
+/* Callback Functions ********************************************************/
+
+VOID
+NTAPI
+ExInitializeCallBack(
+ IN PEX_CALLBACK Callback
+);
+
/* Rundown Functions ********************************************************/
VOID
#define ExpSetRundown(x, y) InterlockedExchange64((PLONGLONG)x, y)
#else
#define ExpChangeRundown(x, y, z) InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z))
+#define ExpChangePushlock(x, y, z) LongToPtr(InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z)))
#define ExpSetRundown(x, y) InterlockedExchange((PLONG)x, y)
#endif
FORCEINLINE
_ExAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef)
{
- ULONG_PTR Value, NewValue, OldValue;
+ ULONG_PTR Value, NewValue;
/* Get the current value and mask the active bit */
Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
NewValue = Value + EX_RUNDOWN_COUNT_INC;
/* Change the value */
- OldValue = ExpChangeRundown(RunRef, NewValue, Value);
- if (OldValue != Value)
+ NewValue = ExpChangeRundown(RunRef, NewValue, Value);
+ if (NewValue != Value)
{
/* Rundown was active, use long path */
return ExfAcquireRundownProtection(RunRef);
FORCEINLINE
_ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef)
{
- ULONG_PTR Value, NewValue, OldValue;
+ ULONG_PTR Value, NewValue;
/* Get the current value and mask the active bit */
Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
NewValue = Value - EX_RUNDOWN_COUNT_INC;
/* Change the value */
- OldValue = ExpChangeRundown(RunRef, NewValue, Value);
+ NewValue = ExpChangeRundown(RunRef, NewValue, Value);
/* Check if the rundown was active */
- if (OldValue != Value)
+ if (NewValue != Value)
{
/* Rundown was active, use long path */
ExfReleaseRundownProtection(RunRef);
/* Set the active bit */
Value = ExpChangeRundown(RunRef, EX_RUNDOWN_ACTIVE, 0);
- if ((Value) || (Value != EX_RUNDOWN_ACTIVE))
+ if ((Value) && (Value != EX_RUNDOWN_ACTIVE))
{
/* If the the rundown wasn't already active, then take the long path */
ExfWaitForRundownProtectionRelease(RunRef);
/* PUSHLOCKS *****************************************************************/
+/* FIXME: VERIFY THESE! */
+
+VOID
+FASTCALL
+ExBlockPushLock(PEX_PUSH_LOCK PushLock,
+ PVOID WaitBlock);
+
+VOID
+FASTCALL
+ExfUnblockPushLock(PEX_PUSH_LOCK PushLock,
+ PVOID CurrentWaitBlock);
+
+VOID
+FASTCALL
+ExWaitForUnblockPushLock(IN PEX_PUSH_LOCK PushLock,
+ IN PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock);
+
+/*++
+ * @name ExInitializePushLock
+ * INTERNAL MACRO
+ *
+ * The ExInitializePushLock macro initializes a PushLock.
+ *
+ * @params PushLock
+ * Pointer to the pushlock which is to be initialized.
+ *
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+FORCEINLINE
+ExInitializePushLock(IN PULONG_PTR PushLock)
+{
+ /* Set the value to 0 */
+ *PushLock = 0;
+}
+
/*++
* @name ExAcquirePushLockExclusive
* INTERNAL MACRO
/* Try acquiring the lock */
NewValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
- if (InterlockedCompareExchangePointer(PushLock, NewValue.Ptr, 0))
+ if (ExpChangePushlock(PushLock, NewValue.Ptr, 0))
{
/* Someone changed it, use the slow path */
DbgPrint("%s - Contention!\n", __FUNCTION__);
ASSERT(PushLock->Waiting || PushLock->Shared > 0);
}
+/*++
+ * @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.
+ *
+ *--*/
+BOOLEAN
+FORCEINLINE
+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;
+}
+
/*++
* @name ExWaitOnPushLock
* INTERNAL MACRO
FORCEINLINE
ExWaitOnPushLock(PEX_PUSH_LOCK PushLock)
{
- /* Acquire the lock */
- ExfAcquirePushLockExclusive(PushLock);
- ASSERT(PushLock->Locked);
+ /* Check if we're locked */
+ if (PushLock->Locked)
+ {
+ /* Acquire the lock */
+ ExfAcquirePushLockExclusive(PushLock);
+ ASSERT(PushLock->Locked);
- /* Release it */
- ExfReleasePushLockExclusive(PushLock);
+ /* Release it */
+ ExfReleasePushLockExclusive(PushLock);
+ }
}
/*++
/* Try to clear the pushlock */
OldValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
- if (InterlockedCompareExchangePointer(PushLock, 0, OldValue.Ptr) !=
- OldValue.Ptr)
+ if (ExpChangePushlock(PushLock, 0, OldValue.Ptr) != OldValue.Ptr)
{
/* There are still other people waiting on it */
DbgPrint("%s - Contention!\n", __FUNCTION__);
ASSERT(PushLock->Waiting || PushLock->Shared == 0);
/* Unlock the pushlock */
- OldValue.Value = InterlockedExchangeAddSizeT((PLONG)PushLock, -1);
+ OldValue.Value = InterlockedExchangeAddSizeT((PLONG)PushLock,
+ -EX_PUSH_LOCK_LOCK);
/* Sanity checks */
ASSERT(OldValue.Locked);
/* Check if nobody is waiting on us and try clearing the lock here */
if ((OldValue.Waiting) ||
- (InterlockedCompareExchangePointer(PushLock, NewValue.Ptr, OldValue.Ptr) ==
+ (ExpChangePushlock(PushLock, NewValue.Ptr, OldValue.Ptr) !=
OldValue.Ptr))
{
/* We have waiters, use the long path */