- Display a temporary note in ipconfig to avoid user confusion.
- Requires fixing of GetAdaptersInfo
Modified: trunk/reactos/apps/utils/net/ipconfig/ipconfig.c
_____
Modified: trunk/reactos/apps/utils/net/ipconfig/ipconfig.c
--- trunk/reactos/apps/utils/net/ipconfig/ipconfig.c 2006-01-03
23:36:05 UTC (rev 20557)
+++ trunk/reactos/apps/utils/net/ipconfig/ipconfig.c 2006-01-03
23:41:57 UTC (rev 20558)
@@ -144,12 +144,14 @@
}
pAdapter = pAdapterInfo;
- //HKEY hKey;
- //LPCTSTR lpSubKey =
_T("SYSTEM\\ControlSet\\Control\\Network");
+ /* temp note until GetAdatersInfo is fixed */
+ _tprintf(_T("Note - ipconfig is currently returning incorrect
information\n"));
+ _tprintf(_T("If your adapter is configured correctly, it will
usually \n"));
+ _tprintf(_T("display the loopback, otherwise an error will be
displayed\n\n"));
+
_tprintf(_T("\nReactOS IP Configuration\n\n"));
-
if (bAll)
{
_tprintf(_T("\tHost Name . . . . . . . . . . . . : %s\n"),
pFixedInfo->HostName);
- Implement Pushlocks. Only Waking, and Exclusive Acquire/Release +
Waits have been tested. The shared paths and block/unblock are still
untested and may probably contain bugs. Pushlocks are not yet used in
the kernel and they won't be until all paths are tested and validated.
- Public DDIs Implemented: ExfAcquirePushLockExclusive,
ExfAcquirePushLockShared, ExfTryToWakePushLock, ExfReleasePushLock,
ExfReleasePushLockExclusive, ExfReleasePushLockShared,
ExfUnblockPushLock.
Added: trunk/reactos/ntoskrnl/ex/pushlock.c
Modified: trunk/reactos/ntoskrnl/include/internal/ex.h
Modified: trunk/reactos/ntoskrnl/include/internal/ntoskrnl.h
Modified: trunk/reactos/ntoskrnl/ntoskrnl.xml
_____
Copied: trunk/reactos/ntoskrnl/ex/pushlock.c (from rev 20362,
trunk/reactos/ntoskrnl/ex/synch.c)
--- trunk/reactos/ntoskrnl/ex/synch.c 2005-12-27 01:14:55 UTC (rev
20362)
+++ trunk/reactos/ntoskrnl/ex/pushlock.c 2006-01-03 23:36:05 UTC
(rev 20557)
@@ -0,0 +1,1164 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Kernel
+ * FILE: ntoskrnl/ex/pushlock.c
+ * PURPOSE: Pushlock and Cache-Aware Pushlock Implementation
+ * PROGRAMMER: Alex Ionescu (alex.ionescu(a)reactos.com)
+ */
+
+/* INCLUDES
*****************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <internal/debug.h>
+
+/* DATA
**********************************************************************/
+
+ULONG ExPushLockSpinCount;
+
+/* PRIVATE FUNCTIONS
*********************************************************/
+
+/*++
+ * @name ExpInitializePushLocks
+ *
+ * The ExpInitializePushLocks routine initialized Pushlock support.
+ *
+ * @param None.
+ *
+ * @return None.
+ *
+ * @remarks The ExpInitializePushLocks routine sets up the spin on SMP
machines.
+ *
+ *--*/
+VOID
+NTAPI
+ExpInitializePushLocks(VOID)
+{
+ /* Initialize an internal 1024-iteration spin for MP CPUs */
+ ExPushLockSpinCount = (KeNumberProcessors == 1) ? 0 : 1024;
+}
+
+/*++
+ * @name ExfWakePushLock
+ *
+ * The ExfWakePushLock routine wakes a Pushlock that is in the
waiting
+ * state.
+ *
+ * @param PushLock
+ * Pointer to a pushlock that is waiting.
+ *
+ * @param OldValue
+ * Last known value of the pushlock before this routine was
called.
+ *
+ * @return None.
+ *
+ * @remarks This is an internal routine; do not call it manually. Only
the system
+ * can properly know if the pushlock is ready to be awakened
or not.
+ * External callers should use ExfTrytoWakePushLock.
+ *
+ *--*/
+VOID
+FASTCALL
+ExfWakePushLock(PEX_PUSH_LOCK PushLock,
+ EX_PUSH_LOCK OldValue)
+{
+ EX_PUSH_LOCK NewValue;
+ PEX_PUSH_LOCK_WAIT_BLOCK PreviousWaitBlock, FirstWaitBlock,
NextWaitBlock;
+ PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock;
+ KIRQL OldIrql;
+
+ /* Start main wake loop */
+ for (;;)
+ {
+ /* Sanity checks */
+ ASSERT(!OldValue.MultipleShared);
+
+ /* Check if it's locked */
+ if (OldValue.Locked)
+ {
+ /* If it's locked we must simply un-wake it*/
+ for (;;)
+ {
+ /* It's not waking anymore */
+ NewValue.Value = OldValue.Value &~ EX_PUSH_LOCK_WAKING;
+
+ /* Sanity checks */
+ ASSERT(!NewValue.Waking);
+ ASSERT(NewValue.Locked);
+ ASSERT(NewValue.Waiting);
+
+ /* Write the New Value */
+ NewValue.Ptr =
InterlockedCompareExchangePointer(PushLock,
+
NewValue.Ptr,
+
OldValue.Ptr);
+ if (NewValue.Value == OldValue.Value) return;
+
+ /* Someone changed the value behind our back, update
it*/
+ OldValue = NewValue;
+
+ /* Check if it's still locked */
+ if (OldValue.Locked) continue;
+ }
+ }
+
+ /* Save the First Block */
+ FirstWaitBlock =
(PEX_PUSH_LOCK_WAIT_BLOCK)((ULONG_PTR)OldValue.Ptr &
+ ~EX_PUSH_LOCK_PTR_BITS);
+ NextWaitBlock = FirstWaitBlock;
+ WaitBlock = NextWaitBlock->Last;
+
+ /* Try to find a wait block */
+ while (!WaitBlock)
+ {
+ /* Save the previous block */
+ PreviousWaitBlock = NextWaitBlock;
+
+ /* Move to next block */
+ NextWaitBlock = NextWaitBlock->Next;
+
+ /* Save the previous block */
+ NextWaitBlock->Previous = PreviousWaitBlock;
+
+ /* Move to the next one */
+ WaitBlock = NextWaitBlock->Last;
+ }
+
+ /* Check if the last Wait Block is not Exclusive or if it's the
only one */
+ PreviousWaitBlock = WaitBlock->Previous;
+ if (!(WaitBlock->Flags & EX_PUSH_LOCK_FLAGS_EXCLUSIVE) ||
+ !(PreviousWaitBlock))
+ {
+ /* Destroy the pushlock */
+ if (InterlockedCompareExchangePointer(PushLock, 0,
OldValue.Ptr) ==
+ OldValue.Ptr) break;
+ }
+ else
+ {
+ /* Link the wait blocks */
+ FirstWaitBlock->Last = PreviousWaitBlock;
+ WaitBlock->Previous = NULL;
+
+ /* Sanity checks */
+ ASSERT(FirstWaitBlock != WaitBlock);
+ ASSERT(PushLock->Waiting);
+
+ /* Remove waking bit from pushlock */
+ InterlockedAnd((PLONG)PushLock, ~EX_PUSH_LOCK_WAKING);
+ }
+ }
+
+ /* Check if there's a previous block */
+ OldIrql = DISPATCH_LEVEL;
+ if (WaitBlock->Previous)
+ {
+ /* Raise to Dispatch */
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+ }
+
+ /* Signaling loop */
+ for (;;)
+ {
+ /* Get the previous Wait block */
+ PreviousWaitBlock = WaitBlock->Previous;
+
+ /* Sanity check */
+ ASSERT(!WaitBlock->Signaled);
+
+ /* We are about to get signaled */
+ WaitBlock->Signaled = TRUE;
+
+ /* Set the Wait Bit in the Wait Block */
+ if (!InterlockedBitTestAndReset(&WaitBlock->Flags, 1))
+ {
+ /* Nobody signaled us, so do it */
+ KeSignalGateBoostPriority(&WaitBlock->WakeGate);
+ }
+
+ /* Set the wait block and check if there still is one to loop*/
+ WaitBlock = PreviousWaitBlock;
+ if (!WaitBlock) break;
+ }
+
+ /* Check if we have to lower back the IRQL */
+ if (OldIrql != DISPATCH_LEVEL) KeLowerIrql(OldIrql);
+}
+
+/*++
+ * @name ExpOptimizePushLockList
+ *
+ * The ExpOptimizePushLockList routine optimizes the list of
waiters
+ * associated to a pushlock's wait block.
+ *
+ * @param PushLock
+ * Pointer to a pushlock whose waiter list needs to be
optimized.
+ *
+ * @param OldValue
+ * Last known value of the pushlock before this routine was
called.
+ *
+ * @return None.
+ *
+ * @remarks At the end of the optimization, the pushlock will also be
wakened.
+ *
+ *--*/
+VOID
+FASTCALL
+ExpOptimizePushLockList(PEX_PUSH_LOCK PushLock,
+ EX_PUSH_LOCK OldValue)
+{
+ PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock, LastWaitBlock,
PreviousWaitBlock;
+ EX_PUSH_LOCK NewValue;
+
+ /* Check if the pushlock is locked */
+ if (OldValue.Locked)
+ {
+ /* Start main loop */
+ for (;;)
+ {
+ /* Get the wait block */
+ WaitBlock =
(PEX_PUSH_LOCK_WAIT_BLOCK)((ULONG_PTR)OldValue.Ptr &
+ ~EX_PUSH_LOCK_PTR_BITS);
+
+ /* Loop the blocks */
+ LastWaitBlock = WaitBlock->Last;
+ while (LastWaitBlock)
+ {
+ /* Save the block */
+ PreviousWaitBlock = WaitBlock;
+
+ /* Get the next block */
+ WaitBlock = WaitBlock->Next;
+
+ /* Save the previous */
+ WaitBlock->Previous = PreviousWaitBlock;
+
+ /* Move to the next */
+ LastWaitBlock = WaitBlock->Last;
+ }
+
+ /* Remove the wake bit */
+ NewValue.Value = OldValue.Value &~ EX_PUSH_LOCK_WAKING;
+
+ /* Sanity checks */
+ ASSERT(NewValue.Locked);
+ ASSERT(!NewValue.Waking);
+
+ /* Update the value */
+ NewValue.Ptr = InterlockedCompareExchangePointer(PushLock,
+
NewValue.Ptr,
+
OldValue.Ptr);
+
+ /* If we updated correctly, leave */
+ if (NewValue.Value == OldValue.Value) return;
+
+ /* If the value is now locked, loop again */
+ if (NewValue.Locked) continue;
+ }
+ }
+
+ /* Wake the push lock */
+ ExfWakePushLock(PushLock, OldValue);
+}
+
+/*++
+ * @name ExTimedWaitForUnblockPushLock
+ *
+ * The ExTimedWaitForUnblockPushLock routine waits for a pushlock
+ * to be unblocked, for a specified internal.
+ *
+ * @param PushLock
+ * Pointer to a pushlock whose waiter list needs to be
optimized.
+ *
+ * @param WaitBlock
+ * Pointer to the pushlock's wait block.
+ *
+ * @param Timeout
+ * Amount of time to wait for this pushlock to be unblocked.
+ *
+ * @return STATUS_SUCCESS is the pushlock is now unblocked, otherwise
the error
+ * code returned by KeWaitForSingleObject.
+ *
+ * @remarks If the wait fails, then a manual unblock is attempted.
+ *
+ *--*/
+NTSTATUS
+FASTCALL
+ExTimedWaitForUnblockPushLock(IN PEX_PUSH_LOCK PushLock,
+ IN PVOID WaitBlock,
+ IN PLARGE_INTEGER Timeout)
+{
+ ULONG i;
+ NTSTATUS Status;
+
+ /* Initialize the wait event */
+
KeInitializeEvent(&((PEX_PUSH_LOCK_WAIT_BLOCK)WaitBlock)->WakeEvent,
+ NotificationEvent,
+ FALSE);
+
+ /* Spin on the push lock if necessary */
+ i = ExPushLockSpinCount;
+ if (i)
+ {
+ /* Spin */
+ while (--i)
+ {
+ /* Check if we got lucky and can leave early */
+ if (!(((PEX_PUSH_LOCK_WAIT_BLOCK)WaitBlock)->Flags &
+ EX_PUSH_LOCK_WAITING))
+ {
+ /* This wait block isn't waiting anymore, we can leave
*/
+ return STATUS_SUCCESS;
+ }
+ YieldProcessor();
+ }
+ }
+
+ /* Now try to remove the wait bit */
+ if
(InterlockedBitTestAndReset(&((PEX_PUSH_LOCK_WAIT_BLOCK)WaitBlock)->Flag
s,
+ 1))
+ {
+ /* Nobody removed it already, let's do a full wait */
+ Status =
KeWaitForSingleObject(&((PEX_PUSH_LOCK_WAIT_BLOCK)WaitBlock)->
+ WakeEvent,
+ WrPushLock,
+ KernelMode,
+ FALSE,
+ Timeout);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Try unblocking the pushlock */
+ ExfUnblockPushLock(PushLock, WaitBlock);
+ }
+ }
+ else
+ {
+ /* Someone beat us to it, no need to wait */
+ Status = STATUS_SUCCESS;
+ }
+
+ /* Return status */
+ return Status;
+}
+
+/*++
+ * @name ExBlockPushLock
+ *
+ * The ExBlockPushLock routine blocks a pushlock.
+ *
+ * @param PushLock
+ * Pointer to a pushlock whose waiter list needs to be
optimized.
+ *
+ * @param WaitBlock
+ * Pointer to the pushlock's wait block.
+ *
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+FASTCALL
+ExBlockPushLock(PEX_PUSH_LOCK PushLock,
+ PVOID WaitBlock)
+{
+ PVOID NewValue, OldValue;
+
+ /* Set the waiting bit */
+ ((PEX_PUSH_LOCK_WAIT_BLOCK)WaitBlock)->Flags |=
EX_PUSH_LOCK_FLAGS_WAIT;
+
+ /* Link the wait blocks */
+ ((PEX_PUSH_LOCK_WAIT_BLOCK)WaitBlock)->Next = PushLock->Ptr;
+
+ /* Try to set this one as the wait block now */
+ NewValue = PushLock->Ptr;
+ for (;;)
+ {
+ /* Set the new wait block value */
+ OldValue = InterlockedCompareExchangePointer(&PushLock->Ptr,
+ WaitBlock,
+ NewValue);
+ if (OldValue == NewValue) break;
+ NewValue = OldValue;
+ }
+}
+
+/* PUBLIC FUNCTIONS
**********************************************************/
+
+/*++
+ * @name ExAcquirePushLockExclusive
+ * @implemented NT5.1
+ *
+ * The ExAcquirePushLockExclusive macro exclusively acquires a
PushLock.
+ *
+ * @params PushLock
+ * Pointer to the pushlock which is to be acquired.
+ *
+ * @return None.
+ *
+ * @remarks Callers of ExAcquirePushLockShared must be running at IRQL
<= APC_LEVEL.
+ * This macro should usually be paired up with
KeAcquireCriticalRegion.
+ *
+ *--*/
+VOID
+FASTCALL
+ExfAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
+{
+ EX_PUSH_LOCK_WAIT_BLOCK WaitBlock;
+ EX_PUSH_LOCK OldValue = *PushLock, NewValue, TempValue;
+ BOOLEAN NeedWake;
+ ULONG i;
+
+ /* Start main loop */
+ for (;;)
+ {
+ /* Check if it's unlocked */
+ if (!OldValue.Locked)
+ {
+ /* Lock it */
+ NewValue.Value = OldValue.Value | EX_PUSH_LOCK_LOCK;
+ ASSERT(NewValue.Locked);
+
+ /* Set the new value */
+ if (InterlockedCompareExchangePointer(PushLock,
+ NewValue.Ptr,
+ OldValue.Ptr) !=
OldValue.Ptr)
+ {
+ /* Retry */
+ OldValue = *PushLock;
+ continue;
+ }
+
+ /* Break out of the loop */
+ break;
+ }
+ else
+ {
+ /* We'll have to create a Waitblock */
+ WaitBlock.Flags = EX_PUSH_LOCK_FLAGS_EXCLUSIVE |
+ EX_PUSH_LOCK_FLAGS_WAIT;
+ WaitBlock.Previous = NULL;
+ NeedWake = FALSE;
+
+ /* Check if there is already a waiter */
+ if (OldValue.Waiting)
+ {
+ /* Nobody is the last waiter yet */
+ WaitBlock.Last = NULL;
+
+ /* We are an exclusive waiter */
+ WaitBlock.ShareCount = 0;
+
+ /* Set the current Wait Block pointer */
+ WaitBlock.Next = (PEX_PUSH_LOCK_WAIT_BLOCK)((ULONG_PTR)
+ OldValue.Ptr &~
EX_PUSH_LOCK_PTR_BITS);
+
+ /* Point to ours */
+ NewValue.Value = (OldValue.Value &
EX_PUSH_LOCK_MULTIPLE_SHARED) |
+ EX_PUSH_LOCK_LOCK |
+ EX_PUSH_LOCK_WAKING |
+ EX_PUSH_LOCK_WAITING |
+ PtrToUlong(&WaitBlock);
+
+ /* Check if the pushlock was already waking */
+ if (OldValue.Waking) NeedWake = TRUE;
+ }
+ else
+ {
+ /* We are the first waiter, so loop the wait block */
+ WaitBlock.Last = &WaitBlock;
+
+ /* Set the share count */
+ WaitBlock.ShareCount = OldValue.Shared;
+
+ /* Check if someone is sharing this pushlock */
+ if (OldValue.Shared > 1)
+ {
+ /* Point to our wait block */
+ NewValue.Value = EX_PUSH_LOCK_MULTIPLE_SHARED |
+ EX_PUSH_LOCK_LOCK |
+ EX_PUSH_LOCK_WAITING |
+ PtrToUlong(&WaitBlock);
+ }
+ else
+ {
+ /* No shared count */
+ WaitBlock.ShareCount = 0;
+
+ /* Point to our wait block */
+ NewValue.Value = EX_PUSH_LOCK_LOCK |
+ EX_PUSH_LOCK_WAITING |
+ PtrToUlong(&WaitBlock);
+ }
+ }
+
+#if DBG
+ /* Setup the Debug Wait Block */
+ WaitBlock.Signaled = 0;
+ WaitBlock.OldValue = OldValue;
+ WaitBlock.NewValue = NewValue;
+ WaitBlock.PushLock = PushLock;
+#endif
+
+ /* Sanity check */
+ ASSERT(NewValue.Waiting);
+ ASSERT(NewValue.Locked);
+
+ /* Write the new value */
+ TempValue = NewValue;
+ NewValue.Ptr = InterlockedCompareExchangePointer(PushLock,
+
NewValue.Ptr,
+
OldValue.Ptr);
+ if (NewValue.Value != OldValue.Value)
+ {
+ /* Retry */
+ OldValue = *PushLock;
+ continue;
+ }
+
+ /* Check if the pushlock needed waking */
+ if (NeedWake)
+ {
+ /* Scan the Waiters and Wake PushLocks */
+ ExpOptimizePushLockList(PushLock, TempValue);
+ }
+
+ /* Set up the Wait Gate */
+ KeInitializeGate(&WaitBlock.WakeGate);
+
+ /* Now spin on the push lock if necessary */
+ i = ExPushLockSpinCount;
+ if ((i) && (WaitBlock.Flags & EX_PUSH_LOCK_WAITING))
+ {
+ /* Spin */
+ while (--i) YieldProcessor();
+ }
+
+ /* Now try to remove the wait bit */
+ if (InterlockedBitTestAndReset(&WaitBlock.Flags, 1))
+ {
+ /* Nobody removed it already, let's do a full wait */
+ KeWaitForGate(&WaitBlock.WakeGate, WrPushLock,
KernelMode);
+ ASSERT(WaitBlock.Signaled);
+ }
+
+ /* We shouldn't be shared anymore */
+ ASSERT((WaitBlock.ShareCount == 0));
+
+ /* Loop again */
+ OldValue = NewValue;
+ }
+ }
+}
+
+/*++
+ * @name ExAcquirePushLockExclusive
+ * @implemented NT5.1
+ *
+ * The ExAcquirePushLockShared macro acquires a shared PushLock.
+ *
+ * @params PushLock
+ * Pointer to the pushlock which is to be acquired.
+ *
+ * @return None.
+ *
+ * @remarks Callers of ExAcquirePushLockShared must be running at IRQL
<= APC_LEVEL.
+ * This macro should usually be paired up with
KeAcquireCriticalRegion.
+ *
+ *--*/
+VOID
+FASTCALL
+ExfAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
+{
+ EX_PUSH_LOCK_WAIT_BLOCK WaitBlock;
+ EX_PUSH_LOCK OldValue = *PushLock, NewValue;
+ BOOLEAN NeedWake;
+ ULONG i;
+
+ /* Start main loop */
+ for (;;)
+ {
+ /* Check if it's unlocked or if it's waiting without any
sharers */
+ if (!(OldValue.Locked) || (OldValue.Waiting && OldValue.Shared
== 0))
+ {
+ /* Check if anyone is waiting on it */
+ if (!OldValue.Waiting)
+ {
+ /* Increase the share count and lock it */
+ NewValue.Value = OldValue.Value | EX_PUSH_LOCK_LOCK;
+ NewValue.Shared++;
+ }
+ else
+ {
+ /* Simply set the lock bit */
+ NewValue.Value = OldValue.Value | EX_PUSH_LOCK_LOCK;
+ }
+
+ /* Sanity check */
+ ASSERT(NewValue.Locked);
+
+ /* Set the new value */
+ NewValue.Ptr = InterlockedCompareExchangePointer(PushLock,
+
NewValue.Ptr,
+
OldValue.Ptr);
+ if (NewValue.Value != OldValue.Value)
+ {
+ /* Retry */
+ OldValue = NewValue;
+ continue;
+ }
+
+ /* Break out of the loop */
+ break;
+ }
+ else
+ {
+ /* We'll have to create a Waitblock */
+ WaitBlock.Flags = EX_PUSH_LOCK_FLAGS_WAIT;
+ WaitBlock.ShareCount = 0;
+ NeedWake = FALSE;
+ WaitBlock.Previous = NULL;
+
+ /* Check if there is already a waiter */
+ if (OldValue.Waiting)
+ {
+ /* Set the current Wait Block pointer */
+ WaitBlock.Next = (PEX_PUSH_LOCK_WAIT_BLOCK)((ULONG_PTR)
+ OldValue.Ptr &~
EX_PUSH_LOCK_PTR_BITS);
+
+ /* Nobody is the last waiter yet */
+ WaitBlock.Last = NULL;
+
+ /* Point to ours */
+ NewValue.Value = (OldValue.Value &
(EX_PUSH_LOCK_MULTIPLE_SHARED |
+ EX_PUSH_LOCK_LOCK))
|
+ EX_PUSH_LOCK_WAKING |
+ EX_PUSH_LOCK_WAITING |
+ PtrToUlong(&WaitBlock);
+
+ /* Check if the pushlock was already waking */
+ if (OldValue.Waking) NeedWake = TRUE;
+ }
+ else
+ {
+ /* We are the first waiter, so loop the wait block */
+ WaitBlock.Last = &WaitBlock;
+
+ /* Point to our wait block */
+ NewValue.Value = (OldValue.Value &
(EX_PUSH_LOCK_MULTIPLE_SHARED |
+
EX_PUSH_LOCK_WAKING)) |
+ EX_PUSH_LOCK_WAITING |
+ PtrToUlong(&WaitBlock);
+ }
+
+ /* Sanity check */
+ ASSERT(NewValue.Waiting);
+
+#if DBG
+ /* Setup the Debug Wait Block */
+ WaitBlock.Signaled = 0;
+ WaitBlock.OldValue = OldValue;
+ WaitBlock.NewValue = NewValue;
+ WaitBlock.PushLock = PushLock;
+#endif
+
+ /* Write the new value */
+ if (InterlockedCompareExchangePointer(PushLock,
+ NewValue.Ptr,
+ OldValue.Ptr) !=
OldValue.Ptr)
+ {
+ /* Retry */
+ OldValue = NewValue;
+ continue;
+ }
+
+ /* Update the value now */
+ OldValue = NewValue;
+
+ /* Check if the pushlock needed waking */
+ if (NeedWake)
+ {
+ /* Scan the Waiters and Wake PushLocks */
+ ExpOptimizePushLockList(PushLock, OldValue);
+ }
+
+ /* Set up the Wait Gate */
+ KeInitializeGate(&WaitBlock.WakeGate);
+
+ /* Now spin on the push lock if necessary */
+ i = ExPushLockSpinCount;
+ if ((i) && (WaitBlock.Flags & EX_PUSH_LOCK_WAITING))
+ {
+ /* Spin */
+ while (--i) YieldProcessor();
+ }
+
+ /* Now try to remove the wait bit */
+ if (InterlockedBitTestAndReset(&WaitBlock.Flags, 1))
+ {
+ /* Fast-path did not work, we need to do a full wait */
+ KeWaitForGate(&WaitBlock.WakeGate, WrPushLock,
KernelMode);
+ ASSERT(WaitBlock.Signaled);
+ }
+
+ /* We shouldn't be shared anymore */
+ ASSERT((WaitBlock.ShareCount == 0));
+ }
+ }
+}
+
+/*++
+ * @name ExfReleasePushLock
+ * @implemented NT5.1
+ *
+ * The ExReleasePushLockExclusive routine releases a previously
+ * exclusively acquired PushLock.
+ *
+ * @params PushLock
+ * Pointer to a previously acquired pushlock.
+ *
+ * @return None.
+ *
+ * @remarks Callers of ExReleasePushLockExclusive must be running at
IRQL <= APC_LEVEL.
+ * This macro should usually be paired up with
KeLeaveCriticalRegion.
+ *
+ *--*/
+VOID
+FASTCALL
+ExfReleasePushLock(PEX_PUSH_LOCK PushLock)
+{
+ EX_PUSH_LOCK OldValue = *PushLock;
+ EX_PUSH_LOCK NewValue;
+ PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock;
+
+ /* Sanity check */
+ ASSERT(OldValue.Locked);
+
+ /* Check if someone is waiting on the lock */
+ if (!OldValue.Waiting)
+ {
+ /* Nobody is waiting on it, so we'll try a quick release */
+ for (;;)
+ {
+ /* Check if it's shared */
+ if (OldValue.Shared > 1)
+ {
+ /* Write the Old Value but decrease share count */
+ NewValue = OldValue;
+ NewValue.Shared--;
+ }
+ else
+ {
+ /* Simply clear the lock */
+ NewValue.Value = 0;
+ }
+
+ /* Write the New Value */
+ NewValue.Ptr = InterlockedCompareExchangePointer(PushLock,
+
NewValue.Ptr,
+
OldValue.Ptr);
+ if (NewValue.Value == OldValue.Value)
+ {
+ /* No waiters left, we're done */
+ goto quit;
+ }
+
+ /* Did it enter a wait state? */
+ OldValue = NewValue;
+ if (NewValue.Waiting) break;
+ }
+ }
+
+ /* Ok, we do know someone is waiting on it. Are there more then
one? */
+ if (OldValue.MultipleShared)
+ {
+ /* Find the last Wait Block */
+ for (WaitBlock =
(PEX_PUSH_LOCK_WAIT_BLOCK)((ULONG_PTR)OldValue.Ptr &
+
~EX_PUSH_LOCK_PTR_BITS);
+ WaitBlock->Last;
+ WaitBlock = WaitBlock->Next);
+
+ /* Make sure the Share Count is above 0 */
+ if (WaitBlock->ShareCount)
+ {
+ /* This shouldn't be an exclusive wait block */
+ ASSERT(WaitBlock->Flags&EX_PUSH_LOCK_FLAGS_EXCLUSIVE);
+
+ /* Do the decrease and check if the lock isn't shared
anymore */
+ if (InterlockedExchangeAdd(&WaitBlock->ShareCount, -1))
+ {
+ /* Someone is still holding the lock */
+ goto quit;
+ }
+ }
+ }
+
+ /*
+ * If nobody was waiting on the block, then we possibly reduced the
number
+ * of times the pushlock was shared, and we unlocked it.
+ * If someone was waiting, and more then one person is waiting,
then we
+ * reduced the number of times the pushlock is shared in the wait
block.
+ * Therefore, at this point, we can now 'satisfy' the wait.
+ */
+ for (;;)
+ {
+ /* Now we need to see if it's waking */
+ if (OldValue.Waking)
+ {
+ /* Remove the lock and multiple shared bits */
+ NewValue.Value = OldValue.Value;
+ NewValue.MultipleShared = FALSE;
+ NewValue.Locked = FALSE;
+
+ /* Sanity check */
+ ASSERT(NewValue.Waking && !NewValue.Locked &&
!NewValue.MultipleShared);
+
+ /* Write the new value */
+ NewValue.Ptr = InterlockedCompareExchangePointer(PushLock,
+
NewValue.Ptr,
+
OldValue.Ptr);
+ if (NewValue.Value == OldValue.Value) break;
+
+ /* The value changed, try the unlock again */
+ continue;
+ }
+ else
+ {
+ /* Remove the lock and multiple shared bits */
+ NewValue.Value = OldValue.Value;
+ NewValue.MultipleShared = FALSE;
+ NewValue.Locked = FALSE;
+
+ /* It's not already waking, so add the wake bit */
+ NewValue.Waking = TRUE;
+
+ /* Sanity check */
+ ASSERT(NewValue.Waking && !NewValue.Locked &&
!NewValue.MultipleShared);
+
+ /* Write the new value */
+ NewValue.Ptr = InterlockedCompareExchangePointer(PushLock,
+
NewValue.Ptr,
+
OldValue.Ptr);
+ if (NewValue.Value != OldValue.Value) continue;
+
+ /* The write was successful. The pushlock is Unlocked and
Waking */
+ ExfWakePushLock(PushLock, NewValue);
+ break;
+ }
+ }
+quit:
+ /* Done! */
+ return;
+}
+
+/*++
+ * @name ExfReleasePushLockShared
+ * @implemented NT5.2
+ *
+ * The ExfReleasePushLockShared macro releases a previously
acquired PushLock.
+ *
+ * @params PushLock
+ * Pointer to a previously acquired pushlock.
+ *
+ * @return None.
+ *
+ * @remarks Callers of ExReleasePushLockShared must be running at IRQL
<= APC_LEVEL.
+ * This macro should usually be paired up with
KeLeaveCriticalRegion.
+ *
+ *--*/
+VOID
+FASTCALL
+ExfReleasePushLockShared(PEX_PUSH_LOCK PushLock)
+{
+ EX_PUSH_LOCK OldValue = *PushLock;
+ EX_PUSH_LOCK NewValue;
+ PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock;
+
+ /* Check if someone is waiting on the lock */
+ if (!OldValue.Waiting)
+ {
+ /* Nobody is waiting on it, so we'll try a quick release */
+ for (;;)
+ {
+ /* Check if it's shared */
+ if (OldValue.Shared > 1)
+ {
+ /* Write the Old Value but decrease share count */
+ NewValue = OldValue;
+ NewValue.Shared--;
+ }
+ else
+ {
+ /* Simply clear the lock */
+ NewValue.Value = 0;
+ }
+
+ /* Write the New Value */
+ NewValue.Ptr = InterlockedCompareExchangePointer(PushLock,
+
NewValue.Ptr,
+
OldValue.Ptr);
+ if (NewValue.Value == OldValue.Value)
+ {
+ /* No waiters left, we're done */
+ goto quit;
+ }
+
+ /* Did it enter a wait state? */
+ OldValue = NewValue;
+ if (NewValue.Waiting) break;
+ }
+ }
+
+ /* Ok, we do know someone is waiting on it. Are there more then
one? */
+ if (OldValue.MultipleShared)
+ {
+ /* Find the last Wait Block */
+ for (WaitBlock =
(PEX_PUSH_LOCK_WAIT_BLOCK)((ULONG_PTR)OldValue.Ptr &
+
~EX_PUSH_LOCK_PTR_BITS);
+ WaitBlock->Last;
+ WaitBlock = WaitBlock->Next);
+
+ /* Sanity checks */
+ ASSERT(WaitBlock->ShareCount > 0);
+ ASSERT(WaitBlock->Flags&EX_PUSH_LOCK_FLAGS_EXCLUSIVE);
+
+ /* Do the decrease and check if the lock isn't shared anymore
*/
+ if (InterlockedExchangeAdd(&WaitBlock->ShareCount, -1)) goto
quit;
+ }
+
+ /*
+ * If nobody was waiting on the block, then we possibly reduced the
number
+ * of times the pushlock was shared, and we unlocked it.
+ * If someone was waiting, and more then one person is waiting,
then we
+ * reduced the number of times the pushlock is shared in the wait
block.
+ * Therefore, at this point, we can now 'satisfy' the wait.
+ */
+ for (;;)
+ {
+ /* Now we need to see if it's waking */
+ if (OldValue.Waking)
+ {
+ /* Remove the lock and multiple shared bits */
+ NewValue.Value = OldValue.Value;
+ NewValue.MultipleShared = FALSE;
+ NewValue.Locked = FALSE;
+
+ /* Sanity check */
+ ASSERT(NewValue.Waking && !NewValue.Locked &&
!NewValue.MultipleShared);
+
+ /* Write the new value */
+ NewValue.Ptr = InterlockedCompareExchangePointer(PushLock,
+
NewValue.Ptr,
+
OldValue.Ptr);
+ if (NewValue.Value == OldValue.Value) break;
+
+ /* The value changed, try the unlock again */
+ continue;
+ }
+ else
+ {
+ /* Remove the lock and multiple shared bits */
+ NewValue.Value = OldValue.Value;
+ NewValue.MultipleShared = FALSE;
+ NewValue.Locked = FALSE;
+
+ /* It's not already waking, so add the wake bit */
+ NewValue.Waking = TRUE;
+
+ /* Sanity check */
+ ASSERT(NewValue.Waking && !NewValue.Locked &&
!NewValue.MultipleShared);
+
+ /* Write the new value */
+ NewValue.Ptr = InterlockedCompareExchangePointer(PushLock,
+
NewValue.Ptr,
+
OldValue.Ptr);
+ if (NewValue.Value != OldValue.Value) continue;
+
+ /* The write was successful. The pushlock is Unlocked and
Waking */
+ ExfWakePushLock(PushLock, NewValue);
+ break;
+ }
+ }
+quit:
+ /* Done! */
+ return;
+}
+
+/*++
+ * ExfReleasePushLockExclusive
+ * @implemented NT5.2
+ *
+ * The ExfReleasePushLockExclusive routine releases a previously
+ * exclusively acquired PushLock.
+ *
+ * @params PushLock
+ * Pointer to a previously acquired pushlock.
+ *
+ * @return None.
[truncated at 1000 lines; 463 more skipped]
- Dirty temporary fix to unregress abiword/qemu.
Modified: trunk/reactos/lib/kernel32/misc/atom.c
_____
Modified: trunk/reactos/lib/kernel32/misc/atom.c
--- trunk/reactos/lib/kernel32/misc/atom.c 2006-01-03 21:34:19 UTC
(rev 20554)
+++ trunk/reactos/lib/kernel32/misc/atom.c 2006-01-03 22:25:09 UTC
(rev 20555)
@@ -72,6 +72,7 @@
/* Check if we can abuse the TEB */
if (AnsiString.MaximumLength > 260)
{
+RosHack:
/* We can't, allocate a new string */
AtomNameString = &UnicodeString;
Status = RtlAnsiStringToUnicodeString(AtomNameString,
@@ -80,8 +81,18 @@
}
else
{
- /* We can! Use the TEB */
+ /* We can! Get the TEB String */
AtomNameString = &NtCurrentTeb()->StaticUnicodeString;
+
+ /* FIXME: HACK! */
+ if (!AtomNameString->MaximumLength)
+ {
+ DPRINT1("Hit the ROS TEB Static Unicode String
Bug\n",
+ "Please try to fix the underlying
problem!!!\n");
+ goto RosHack;
+ }
+
+ /* Convert it into the TEB */
Status = RtlAnsiStringToUnicodeString(AtomNameString,
&AnsiString,
FALSE);
@@ -171,6 +182,7 @@
/* Check if we can abuse the TEB */
if (AnsiString.MaximumLength > 260)
{
+RosHack:
/* We can't, allocate a new string */
AtomNameString = &UnicodeString;
Status = RtlAnsiStringToUnicodeString(AtomNameString,
@@ -179,8 +191,18 @@
}
else
{
- /* We can! Use the TEB */
+ /* We can! Get the TEB String */
AtomNameString = &NtCurrentTeb()->StaticUnicodeString;
+
+ /* FIXME: HACK! */
+ if (!AtomNameString->MaximumLength)
+ {
+ DPRINT1("Hit the ROS TEB Static Unicode String
Bug\n",
+ "Please try to fix the underlying
problem!!!\n");
+ goto RosHack;
+ }
+
+ /* Convert it into the TEB */
Status = RtlAnsiStringToUnicodeString(AtomNameString,
&AnsiString,
FALSE);