Author: pschweitzer
Date: Tue May 30 21:35:05 2017
New Revision: 74703
URL:
http://svn.reactos.org/svn/reactos?rev=74703&view=rev
Log:
[NTDLL_VISTA]
Create a new NTDLL library that exports some of the NTDLL Vista+ functions.
This new NTDLL includes at the time of commit:
- SRW locks implementation that was originally built in RTL but never used ;
- Condition variables implementation which is a new code in ReactOS trunk.
Condition variables is an implementation of Stephan Röger, with minor formatting
changes by Timo Kreuzer and various changes by myself.
CORE-7546
CORE-8204
Added:
trunk/reactos/dll/win32/ntdll_vista/
trunk/reactos/dll/win32/ntdll_vista/CMakeLists.txt (with props)
trunk/reactos/dll/win32/ntdll_vista/DllMain.c (with props)
trunk/reactos/dll/win32/ntdll_vista/condvar.c (with props)
trunk/reactos/dll/win32/ntdll_vista/ntdll_vista.spec (with props)
trunk/reactos/dll/win32/ntdll_vista/rtl_vista.h (with props)
trunk/reactos/dll/win32/ntdll_vista/srw.c
- copied, changed from r74702, trunk/reactos/sdk/lib/rtl/srw.c
Removed:
trunk/reactos/sdk/lib/rtl/srw.c
Modified:
trunk/reactos/dll/win32/CMakeLists.txt
trunk/reactos/sdk/lib/rtl/CMakeLists.txt
Modified: trunk/reactos/dll/win32/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/CMakeLists.txt?r…
==============================================================================
--- trunk/reactos/dll/win32/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/CMakeLists.txt [iso-8859-1] Tue May 30 21:35:05 2017
@@ -134,6 +134,7 @@
add_subdirectory(netid)
add_subdirectory(newdev)
add_subdirectory(npptools)
+add_subdirectory(ntdll_vista)
add_subdirectory(ntdsapi)
add_subdirectory(ntlanman)
add_subdirectory(ntmarta)
Added: trunk/reactos/dll/win32/ntdll_vista/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ntdll_vista/CMak…
==============================================================================
--- trunk/reactos/dll/win32/ntdll_vista/CMakeLists.txt (added)
+++ trunk/reactos/dll/win32/ntdll_vista/CMakeLists.txt [iso-8859-1] Tue May 30 21:35:05
2017
@@ -0,0 +1,17 @@
+
+remove_definitions(-D_WIN32_WINNT=0x502 -DWINVER=0x502)
+add_definitions(-D_WIN32_WINNT=0x600 -DWINVER=0x600)
+
+spec2def(ntdll_vista.dll ntdll_vista.spec ADD_IMPORTLIB)
+
+list(APPEND SOURCE
+ DllMain.c
+ condvar.c
+ srw.c
+ ${CMAKE_CURRENT_BINARY_DIR}/ntdll_vista.def)
+
+add_library(ntdll_vista SHARED ${SOURCE})
+set_module_type(ntdll_vista win32dll ENTRYPOINT DllMain 12)
+add_importlibs(ntdll_vista ntdll kernel32)
+add_dependencies(ntdll_vista psdk)
+add_cd_file(TARGET ntdll_vista DESTINATION reactos/system32 FOR all)
Propchange: trunk/reactos/dll/win32/ntdll_vista/CMakeLists.txt
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/dll/win32/ntdll_vista/DllMain.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ntdll_vista/DllM…
==============================================================================
--- trunk/reactos/dll/win32/ntdll_vista/DllMain.c (added)
+++ trunk/reactos/dll/win32/ntdll_vista/DllMain.c [iso-8859-1] Tue May 30 21:35:05 2017
@@ -0,0 +1,36 @@
+#include <stdarg.h>
+
+#define WIN32_NO_STATUS
+
+#include <windef.h>
+#include <winbase.h>
+#include <winreg.h>
+#include <winuser.h>
+#include <winwlx.h>
+
+#define NDEBUG
+#include <debug.h>
+
+VOID
+RtlpInitializeKeyedEvent(VOID);
+
+VOID
+RtlpCloseKeyedEvent(VOID);
+
+BOOL
+WINAPI
+DllMain(HANDLE hDll,
+ DWORD dwReason,
+ LPVOID lpReserved)
+{
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ DisableThreadLibraryCalls(hDll);
+ RtlpInitializeKeyedEvent();
+ }
+ else if (dwReason == DLL_PROCESS_DETACH)
+ {
+ RtlpCloseKeyedEvent();
+ }
+ return TRUE;
+}
Propchange: trunk/reactos/dll/win32/ntdll_vista/DllMain.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/dll/win32/ntdll_vista/condvar.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ntdll_vista/cond…
==============================================================================
--- trunk/reactos/dll/win32/ntdll_vista/condvar.c (added)
+++ trunk/reactos/dll/win32/ntdll_vista/condvar.c [iso-8859-1] Tue May 30 21:35:05 2017
@@ -0,0 +1,525 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS system libraries
+ * PURPOSE: Condition Variable Routines
+ * PROGRAMMERS: Thomas Weidenmueller <w3seek(a)reactos.com>
+ * Stephan A. R�ger
+ */
+
+/* NOTE: This functionality can be optimized for releasing single
+ threads or for releasing all waiting threads at once. This
+ implementation is optimized for releasing a single thread at a time.
+ It wakes up sleeping threads in FIFO order. */
+
+/* INCLUDES ******************************************************************/
+
+#include <rtl_vista.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* INTERNAL TYPES ************************************************************/
+
+#define COND_VAR_UNUSED_FLAG ((ULONG_PTR)1)
+#define COND_VAR_LOCKED_FLAG ((ULONG_PTR)2)
+#define COND_VAR_FLAGS_MASK ((ULONG_PTR)3)
+#define COND_VAR_ADDRESS_MASK (~COND_VAR_FLAGS_MASK)
+
+typedef struct _COND_VAR_WAIT_ENTRY
+{
+ /* ListEntry must have an alignment of at least 32-bits, since we
+ want COND_VAR_ADDRESS_MASK to cover all of the address. */
+ LIST_ENTRY ListEntry;
+ PVOID WaitKey;
+ BOOLEAN ListRemovalHandled;
+} COND_VAR_WAIT_ENTRY, * PCOND_VAR_WAIT_ENTRY;
+
+#define CONTAINING_COND_VAR_WAIT_ENTRY(address, field) \
+ CONTAINING_RECORD(address, COND_VAR_WAIT_ENTRY, field)
+
+/* GLOBALS *******************************************************************/
+
+static HANDLE CondVarKeyedEventHandle = NULL;
+
+/* INTERNAL FUNCTIONS ********************************************************/
+
+FORCEINLINE
+ULONG_PTR
+InternalCmpXChgCondVarAcq(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable,
+ IN ULONG_PTR Exchange,
+ IN ULONG_PTR Comperand)
+{
+ return
(ULONG_PTR)InterlockedCompareExchangePointerAcquire(&ConditionVariable->Ptr,
+ (PVOID)Exchange,
+ (PVOID)Comperand);
+}
+
+FORCEINLINE
+ULONG_PTR
+InternalCmpXChgCondVarRel(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable,
+ IN ULONG_PTR Exchange,
+ IN ULONG_PTR Comperand)
+{
+ return
(ULONG_PTR)InterlockedCompareExchangePointerRelease(&ConditionVariable->Ptr,
+ (PVOID)Exchange,
+ (PVOID)Comperand);
+}
+
+FORCEINLINE
+BOOLEAN *
+InternalGetListRemovalHandledFlag(IN PCOND_VAR_WAIT_ENTRY Entry)
+{
+ return (BOOLEAN *)&Entry->ListRemovalHandled;
+}
+
+static
+PCOND_VAR_WAIT_ENTRY
+InternalLockCondVar(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable,
+ IN PCOND_VAR_WAIT_ENTRY InsertEntry OPTIONAL,
+ IN BOOLEAN * AbortIfLocked OPTIONAL)
+{
+ /* InsertEntry and AbortIfLocked may be NULL on entry. This routine
+ will return NULL if the lock was not acquired. Otherwise it has
+ successfully acquired the lock and the return value is a valid
+ reference to the list head associated with ConditionVariable.
+ The caller must in this case call InternalUnlockCondVar later
+ in order to unlock the condition variable.
+
+ If InsertEntry is NULL and there are no entries on the list, this
+ routine will not acquire the lock and return NULL. If InsertEntry
+ is not NULL this routine ensures that InsertEntry will be on the
+ list when it returns successfully.
+
+ If the lock is owned by another thread and AbortIfLocked is NULL,
+ this routine will block until it acquires the lock. If AbortIfLocked
+ is not NULL and the lock is owned by another thread, this routine
+ will periodically check if *AbortIfLocked is nonzero and if so, will
+ return NULL instead of continuing the wait. */
+
+ ULONG_PTR OldVal = (ULONG_PTR)ConditionVariable->Ptr;
+
+ for (;;)
+ {
+ ULONG_PTR NewVal, LockRes;
+ PLIST_ENTRY OldListHead;
+
+ if (OldVal & COND_VAR_LOCKED_FLAG)
+ {
+ /* The locked flag is set, indicating someone else currently
+ holds the lock. We'll spin until this flag becomes
+ clear or we're asked to abort. */
+ YieldProcessor();
+
+ if ((AbortIfLocked != NULL) && *AbortIfLocked)
+ {
+ /* The caller wants us to abort in this case. */
+ return NULL;
+ }
+
+ /* Refresh OldVal and try again. */
+ OldVal = *(ULONG_PTR *)&ConditionVariable->Ptr;
+ continue;
+ }
+
+ /* Retrieve the list head currently associated with the
+ condition variable. */
+ OldListHead = (PLIST_ENTRY)(OldVal & COND_VAR_ADDRESS_MASK);
+ if (InsertEntry == NULL)
+ {
+ /* The caller doesn't want to put any entry on the list. */
+ if (OldListHead == NULL)
+ {
+ /* The list is empty, so there is nothing to lock. */
+ return NULL;
+ }
+
+ /* The list isn't empty. In this case we need to preserve
+ all of OldVal. */
+ NewVal = OldVal;
+ }
+ else
+ {
+ /* Let InsertEntry be the new list head. Preserve only the
+ bits inside the COND_VAR_FLAGS_MASK range. */
+ NewVal = ((OldVal & COND_VAR_FLAGS_MASK) |
+ (ULONG_PTR)&InsertEntry->ListEntry);
+ }
+
+ /* Set the flag that indicates someone is holding the lock and
+ try to update the condition variable thread-safe. */
+ NewVal |= COND_VAR_LOCKED_FLAG;
+ LockRes = InternalCmpXChgCondVarAcq(ConditionVariable, NewVal, OldVal);
+ if (LockRes == OldVal)
+ {
+ /* We successfully updated ConditionVariable the way we
+ wanted and now hold the lock. */
+ if (InsertEntry == NULL)
+ {
+ /* We know that OldVal contains a valid address in
+ this case. */
+ ASSERT(OldListHead != NULL);
+ return CONTAINING_COND_VAR_WAIT_ENTRY(OldListHead, ListEntry);
+ }
+
+ /* InsertEntry is not on the list yet, so add it. In any
+ case InsertEntry will be the new list head. */
+ if (OldListHead == NULL)
+ {
+ /* List was empty before. */
+ InitializeListHead(&InsertEntry->ListEntry);
+ }
+ else
+ {
+ /* Make InsertEntry the last entry of the old list.
+ As InsertEntry will take the role as new list head,
+ OldListHead will become the second entry (InsertEntry->Flink)
+ on the new list. */
+ InsertTailList(OldListHead, &InsertEntry->ListEntry);
+ }
+
+ return InsertEntry;
+ }
+
+ /* We didn't manage to update ConditionVariable, so try again. */
+ OldVal = LockRes;
+ }
+}
+
+static
+VOID
+InternalUnlockCondVar(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable,
+ IN PCOND_VAR_WAIT_ENTRY RemoveEntry OPTIONAL)
+{
+ /* This routine assumes that the lock is being held on entry.
+ RemoveEntry may be NULL. If it is not NULL, this routine
+ assumes that RemoveEntry is on the list and will remove it
+ before releasing the lock. */
+ ULONG_PTR OldVal = (ULONG_PTR)ConditionVariable->Ptr;
+ PLIST_ENTRY NewHeadEntry;
+
+ ASSERT((OldVal & COND_VAR_LOCKED_FLAG) &&
+ (OldVal & COND_VAR_ADDRESS_MASK));
+
+ NewHeadEntry = (PLIST_ENTRY)(OldVal & COND_VAR_ADDRESS_MASK);
+ if (RemoveEntry != NULL)
+ {
+ /* We have to drop RemoveEntry from the list. */
+ if (&RemoveEntry->ListEntry == NewHeadEntry)
+ {
+ /* RemoveEntry is the list head. */
+ if (!IsListEmpty(NewHeadEntry))
+ {
+ /* The second entry in the list will become the new
+ list head. It's from the thread that arrived
+ right before the owner of RemoveEntry. */
+ NewHeadEntry = NewHeadEntry->Flink;
+ RemoveEntryList(&RemoveEntry->ListEntry);
+ }
+ else
+ {
+ /* The list will be empty, so discard the list. */
+ NewHeadEntry = NULL;
+ }
+ }
+ else
+ {
+ /* RemoveEntry is not the list head. The current list head
+ will remain. */
+ RemoveEntryList(&RemoveEntry->ListEntry);
+ }
+
+ /* Indicate to the owner of RemoveEntry that the entry
+ was removed from the list. RemoveEntry may not be touched
+ from here on. We don't use volatile semantics here since
+ the cache will anyway be flushed soon when we update
+ ConditionVariable. */
+ RemoveEntry->ListRemovalHandled = TRUE;
+ }
+
+ /* Now unlock thread-safe, while preserving any flags within the
+ COND_VAR_FLAGS_MASK range except for COND_VAR_LOCKED_FLAG. */
+ for (;;)
+ {
+ ULONG_PTR NewVal = ((OldVal & (COND_VAR_FLAGS_MASK ^ COND_VAR_LOCKED_FLAG))
|
+ (ULONG_PTR)NewHeadEntry);
+ ULONG_PTR LockRes = InternalCmpXChgCondVarRel(ConditionVariable, NewVal,
OldVal);
+ if (LockRes == OldVal)
+ {
+ /* We unlocked. */
+ break;
+ }
+
+ /* Try again. */
+ OldVal = LockRes;
+ }
+}
+
+static
+VOID
+InternalWake(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable,
+ IN BOOLEAN ReleaseAll)
+{
+ /* If ReleaseAll is zero on entry, one thread at most will be woken.
+ Otherwise all waiting threads are woken. Wakeups happen in FIFO
+ order. */
+ PCOND_VAR_WAIT_ENTRY CONST HeadEntry = InternalLockCondVar(ConditionVariable, NULL,
NULL);
+ PCOND_VAR_WAIT_ENTRY Entry;
+ PCOND_VAR_WAIT_ENTRY NextEntry;
+ LARGE_INTEGER Timeout;
+ PCOND_VAR_WAIT_ENTRY RemoveOnUnlockEntry;
+
+ ASSERT(CondVarKeyedEventHandle != NULL);
+
+ if (HeadEntry == NULL)
+ {
+ /* There is noone there to wake up. In this case do nothing
+ and return immediately. We don't stockpile releases. */
+ return;
+ }
+
+ Timeout.QuadPart = 0;
+ RemoveOnUnlockEntry = NULL;
+
+ /* Release sleeping threads. We will iterate from the last entry on
+ the list to the first. Note that the loop condition is always
+ true for the initial test. */
+ for (Entry = CONTAINING_COND_VAR_WAIT_ENTRY(HeadEntry->ListEntry.Blink,
ListEntry);
+ Entry != NULL;
+ Entry = NextEntry)
+ {
+ NTSTATUS Status;
+
+ if (HeadEntry == Entry)
+ {
+ /* After the current entry we've iterated through the
+ entire list in backward direction. Then exit.*/
+ NextEntry = NULL;
+ }
+ else
+ {
+ /* Store away the next reference right now, since we may
+ not touch Entry anymore at the end of the block. */
+ NextEntry = CONTAINING_COND_VAR_WAIT_ENTRY(Entry->ListEntry.Blink,
ListEntry);
+ }
+
+ /* Wake the thread associated with this event. We will
+ immediately return if we failed (zero timeout). */
+ Status = NtReleaseKeyedEvent(CondVarKeyedEventHandle,
+ &Entry->WaitKey,
+ FALSE,
+ &Timeout);
+
+ if (!NT_SUCCESS(Status))
+ {
+ /* We failed to wake a thread. We'll keep trying. */
+ ASSERT(STATUS_INVALID_HANDLE != Status);
+ continue;
+ }
+
+ /* We've woken a thread and will make sure this thread
+ is removed from the list. */
+ if (HeadEntry == Entry)
+ {
+ /* This is the list head. We can't remove it as easily as
+ other entries and will pass it to the unlock routine
+ later (we will exit the loop after this round anyway). */
+ RemoveOnUnlockEntry = HeadEntry;
+ }
+ else
+ {
+ /* We can remove the entry right away. */
+ RemoveEntryList(&Entry->ListEntry);
+
+ /* Now tell the woken thread that removal from the list was
+ already taken care of here so that this thread can resume
+ its normal operation more quickly. We may not touch
+ Entry after signaling this, since it may lie in invalid
+ memory from there on. */
+ *InternalGetListRemovalHandledFlag(Entry) = TRUE;
+ }
+
+ if (!ReleaseAll)
+ {
+ /* We've successfully woken one thread as the caller
+ demanded. */
+ break;
+ }
+ }
+
+ InternalUnlockCondVar(ConditionVariable, RemoveOnUnlockEntry);
+}
+
+VOID
+NTAPI
+RtlAcquireSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock);
+VOID
+NTAPI
+RtlAcquireSRWLockShared(IN OUT PRTL_SRWLOCK SRWLock);
+VOID
+NTAPI
+RtlReleaseSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock);
+VOID
+NTAPI
+RtlReleaseSRWLockShared(IN OUT PRTL_SRWLOCK SRWLock);
+
+static
+NTSTATUS
+InternalSleep(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable,
+ IN OUT PRTL_CRITICAL_SECTION CriticalSection OPTIONAL,
+ IN OUT PRTL_SRWLOCK SRWLock OPTIONAL,
+ IN ULONG SRWFlags,
+ IN const LARGE_INTEGER * TimeOut OPTIONAL)
+{
+ /* Either CriticalSection or SRWLock must be NULL, but not both.
+ These caller provided lock must be held on entry and will be
+ held again on return. */
+
+ COND_VAR_WAIT_ENTRY OwnEntry;
+ NTSTATUS Status;
+
+ ASSERT(CondVarKeyedEventHandle != NULL);
+ ASSERT((CriticalSection == NULL) != (SRWLock == NULL));
+
+ RtlZeroMemory(&OwnEntry, sizeof(OwnEntry));
+
+ /* Put OwnEntry on the list. */
+ InternalLockCondVar(ConditionVariable, &OwnEntry, NULL);
+ InternalUnlockCondVar(ConditionVariable, NULL);
+
+ /* We can now drop the caller provided lock as a preparation for
+ going to sleep. */
+ if (CriticalSection == NULL)
+ {
+ if (0 == (RTL_CONDITION_VARIABLE_LOCKMODE_SHARED & SRWFlags))
+ {
+ RtlReleaseSRWLockExclusive(SRWLock);
+ }
+ else
+ {
+ RtlReleaseSRWLockShared(SRWLock);
+ }
+ }
+ else
+ {
+ RtlLeaveCriticalSection(CriticalSection);
+ }
+
+ /* Now sleep using the caller provided timeout. */
+ Status = NtWaitForKeyedEvent(CondVarKeyedEventHandle,
+ &OwnEntry.WaitKey,
+ FALSE,
+ (PLARGE_INTEGER)TimeOut);
+
+ ASSERT(STATUS_INVALID_HANDLE != Status);
+
+ if (!*InternalGetListRemovalHandledFlag(&OwnEntry))
+ {
+ /* Remove OwnEntry from the list again, since it still seems to
+ be on the list. We will know for sure once we've acquired
+ the lock. */
+ if (InternalLockCondVar(ConditionVariable,
+ NULL,
+ InternalGetListRemovalHandledFlag(&OwnEntry)))
+ {
+ /* Unlock and potentially remove OwnEntry. Self-removal is
+ usually only necessary when a timeout occurred. */
+ InternalUnlockCondVar(ConditionVariable,
+ !OwnEntry.ListRemovalHandled ?
+ &OwnEntry : NULL);
+ }
+ }
+
+#if _DEBUG
+ /* Clear OwnEntry to aid in detecting bugs. */
+ RtlZeroMemory(&OwnEntry, sizeof(OwnEntry));
+#endif
+
+ /* Reacquire the caller provided lock, as we are about to return. */
+ if (CriticalSection == NULL)
+ {
+ if (0 == (RTL_CONDITION_VARIABLE_LOCKMODE_SHARED & SRWFlags))
+ {
+ RtlAcquireSRWLockExclusive(SRWLock);
+ }
+ else
+ {
+ RtlAcquireSRWLockShared(SRWLock);
+ }
+ }
+ else
+ {
+ RtlEnterCriticalSection(CriticalSection);
+ }
+
+ /* Return whatever NtWaitForKeyedEvent returned. */
+ return Status;
+}
+
+VOID
+RtlpInitializeKeyedEvent(VOID)
+{
+ ASSERT(CondVarKeyedEventHandle == NULL);
+ NtCreateKeyedEvent(&CondVarKeyedEventHandle, EVENT_ALL_ACCESS, NULL, 0);
+}
+
+VOID
+RtlpCloseKeyedEvent(VOID)
+{
+ ASSERT(CondVarKeyedEventHandle != NULL);
+ NtClose(CondVarKeyedEventHandle);
+ CondVarKeyedEventHandle = NULL;
+}
+
+/* EXPORTED FUNCTIONS ********************************************************/
+
+VOID
+NTAPI
+RtlInitializeConditionVariable(OUT PRTL_CONDITION_VARIABLE ConditionVariable)
+{
+ ConditionVariable->Ptr = NULL;
+}
+
+VOID
+NTAPI
+RtlWakeConditionVariable(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable)
+{
+ InternalWake(ConditionVariable, FALSE);
+}
+
+VOID
+NTAPI
+RtlWakeAllConditionVariable(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable)
+{
+ InternalWake(ConditionVariable, TRUE);
+}
+
+NTSYSAPI
+NTSTATUS
+NTAPI
+RtlSleepConditionVariableCS(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable,
+ IN OUT PRTL_CRITICAL_SECTION CriticalSection,
+ IN const LARGE_INTEGER * TimeOut OPTIONAL)
+{
+ return InternalSleep(ConditionVariable,
+ CriticalSection,
+ (PRTL_SRWLOCK)NULL,
+ 0,
+ TimeOut);
+}
+
+NTSYSAPI
+NTSTATUS
+NTAPI
+RtlSleepConditionVariableSRW(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable,
+ IN OUT PRTL_SRWLOCK SRWLock,
+ IN const LARGE_INTEGER * TimeOut OPTIONAL,
+ IN ULONG Flags)
+{
+ return InternalSleep(ConditionVariable,
+ (PRTL_CRITICAL_SECTION)NULL,
+ SRWLock,
+ Flags,
+ TimeOut);
+}
+
+/* EOF */
Propchange: trunk/reactos/dll/win32/ntdll_vista/condvar.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/dll/win32/ntdll_vista/ntdll_vista.spec
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ntdll_vista/ntdl…
==============================================================================
--- trunk/reactos/dll/win32/ntdll_vista/ntdll_vista.spec (added)
+++ trunk/reactos/dll/win32/ntdll_vista/ntdll_vista.spec [iso-8859-1] Tue May 30 21:35:05
2017
@@ -0,0 +1,10 @@
+@ stdcall RtlInitializeConditionVariable(ptr)
+@ stdcall RtlWakeConditionVariable(ptr)
+@ stdcall RtlWakeAllConditionVariable(ptr)
+@ stdcall RtlSleepConditionVariableCS(ptr ptr ptr)
+@ stdcall RtlSleepConditionVariableSRW(ptr ptr ptr long)
+@ stdcall RtlInitializeSRWLock(ptr)
+@ stdcall RtlAcquireSRWLockShared(ptr)
+@ stdcall RtlReleaseSRWLockShared(ptr)
+@ stdcall RtlAcquireSRWLockExclusive(ptr)
+@ stdcall RtlReleaseSRWLockExclusive(ptr)
Propchange: trunk/reactos/dll/win32/ntdll_vista/ntdll_vista.spec
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/dll/win32/ntdll_vista/rtl_vista.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ntdll_vista/rtl_…
==============================================================================
--- trunk/reactos/dll/win32/ntdll_vista/rtl_vista.h (added)
+++ trunk/reactos/dll/win32/ntdll_vista/rtl_vista.h [iso-8859-1] Tue May 30 21:35:05 2017
@@ -0,0 +1,57 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS System Libraries
+ * FILE: lib/rtl/rtl.h
+ * PURPOSE: Run-Time Libary Header
+ * PROGRAMMER: Alex Ionescu
+ */
+
+#ifndef RTL_H
+#define RTL_H
+
+/* We're a core NT DLL, we don't import syscalls */
+#define _INC_SWPRINTF_INL_
+#undef __MSVCRT__
+
+/* C Headers */
+#include <stdlib.h>
+#include <stdio.h>
+
+/* PSDK/NDK Headers */
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+#define COBJMACROS
+#define CONST_VTABLE
+#include <windef.h>
+#include <winbase.h>
+#include <winreg.h>
+#include <objbase.h>
+#include <ntintsafe.h>
+#include <ndk/exfuncs.h>
+#include <ndk/iofuncs.h>
+#include <ndk/kefuncs.h>
+#include <ndk/ldrfuncs.h>
+#include <ndk/mmfuncs.h>
+#include <ndk/obfuncs.h>
+#include <ndk/psfuncs.h>
+#include <ndk/rtlfuncs.h>
+#include <ndk/setypes.h>
+#include <ndk/sefuncs.h>
+#include <ndk/umfuncs.h>
+
+/* SEH support with PSEH */
+#include <pseh/pseh2.h>
+
+/* Use intrinsics for x86 and x64 */
+#if defined(_M_IX86) || defined(_M_AMD64)
+#define InterlockedCompareExchange _InterlockedCompareExchange
+#define InterlockedIncrement _InterlockedIncrement
+#define InterlockedDecrement _InterlockedDecrement
+#define InterlockedExchangeAdd _InterlockedExchangeAdd
+#define InterlockedExchange _InterlockedExchange
+#define InterlockedBitTestAndSet _interlockedbittestandset
+#define InterlockedBitTestAndSet64 _interlockedbittestandset64
+#endif
+
+#endif /* RTL_H */
Propchange: trunk/reactos/dll/win32/ntdll_vista/rtl_vista.h
------------------------------------------------------------------------------
svn:eol-style = native
Copied: trunk/reactos/dll/win32/ntdll_vista/srw.c (from r74702,
trunk/reactos/sdk/lib/rtl/srw.c)
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ntdll_vista/srw.…
==============================================================================
--- trunk/reactos/sdk/lib/rtl/srw.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/ntdll_vista/srw.c [iso-8859-1] Tue May 30 21:35:05 2017
@@ -13,7 +13,7 @@
/* INCLUDES *****************************************************************/
-#include <rtl.h>
+#include <rtl_vista.h>
#define NDEBUG
#include <debug.h>
Modified: trunk/reactos/sdk/lib/rtl/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/lib/rtl/CMakeLists.txt…
==============================================================================
--- trunk/reactos/sdk/lib/rtl/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/sdk/lib/rtl/CMakeLists.txt [iso-8859-1] Tue May 30 21:35:05 2017
@@ -16,7 +16,6 @@
bitmap.c
bootdata.c
compress.c
- condvar.c
crc32.c
critical.c
dbgbuffer.c
@@ -56,7 +55,6 @@
security.c
slist.c
sid.c
- srw.c
splaytree.c
thread.c
time.c
Removed: trunk/reactos/sdk/lib/rtl/srw.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/lib/rtl/srw.c?rev=74702
==============================================================================
--- trunk/reactos/sdk/lib/rtl/srw.c [iso-8859-1] (original)
+++ trunk/reactos/sdk/lib/rtl/srw.c (removed)
@@ -1,765 +0,0 @@
-/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS system libraries
- * PURPOSE: Slim Reader/Writer (SRW) Routines
- * PROGRAMMER: Thomas Weidenmueller <w3seek(a)reactos.com>
- *
- * NOTES: The algorithms used in this implementation
- * may be different from Vista's implementation.
- * Since applications should treat the RTL_SRWLOCK
- * structure as opaque data, it should not matter.
- * The algorithms are probably not as optimized.
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <rtl.h>
-
-#define NDEBUG
-#include <debug.h>
-
-/* FUNCTIONS *****************************************************************/
-
-#ifdef _WIN64
-#define InterlockedBitTestAndSetPointer(ptr,val)
InterlockedBitTestAndSet64((PLONGLONG)ptr,(LONGLONG)val)
-#define InterlockedAddPointer(ptr,val) InterlockedAdd64((PLONGLONG)ptr,(LONGLONG)val)
-#define InterlockedAndPointer(ptr,val) InterlockedAnd64((PLONGLONG)ptr,(LONGLONG)val)
-#define InterlockedOrPointer(ptr,val) InterlockedOr64((PLONGLONG)ptr,(LONGLONG)val)
-#else
-#define InterlockedBitTestAndSetPointer(ptr,val)
InterlockedBitTestAndSet((PLONG)ptr,(LONG)val)
-#define InterlockedAddPointer(ptr,val) InterlockedAdd((PLONG)ptr,(LONG)val)
-#define InterlockedAndPointer(ptr,val) InterlockedAnd((PLONG)ptr,(LONG)val)
-#define InterlockedOrPointer(ptr,val) InterlockedOr((PLONG)ptr,(LONG)val)
-#endif
-
-#define RTL_SRWLOCK_OWNED_BIT 0
-#define RTL_SRWLOCK_CONTENDED_BIT 1
-#define RTL_SRWLOCK_SHARED_BIT 2
-#define RTL_SRWLOCK_CONTENTION_LOCK_BIT 3
-#define RTL_SRWLOCK_OWNED (1 << RTL_SRWLOCK_OWNED_BIT)
-#define RTL_SRWLOCK_CONTENDED (1 << RTL_SRWLOCK_CONTENDED_BIT)
-#define RTL_SRWLOCK_SHARED (1 << RTL_SRWLOCK_SHARED_BIT)
-#define RTL_SRWLOCK_CONTENTION_LOCK (1 << RTL_SRWLOCK_CONTENTION_LOCK_BIT)
-#define RTL_SRWLOCK_MASK (RTL_SRWLOCK_OWNED | RTL_SRWLOCK_CONTENDED | \
- RTL_SRWLOCK_SHARED | RTL_SRWLOCK_CONTENTION_LOCK)
-#define RTL_SRWLOCK_BITS 4
-
-typedef struct _RTLP_SRWLOCK_SHARED_WAKE
-{
- LONG Wake;
- volatile struct _RTLP_SRWLOCK_SHARED_WAKE *Next;
-} volatile RTLP_SRWLOCK_SHARED_WAKE, *PRTLP_SRWLOCK_SHARED_WAKE;
-
-typedef struct _RTLP_SRWLOCK_WAITBLOCK
-{
- /* SharedCount is the number of shared acquirers. */
- LONG SharedCount;
-
- /* Last points to the last wait block in the chain. The value
- is only valid when read from the first wait block. */
- volatile struct _RTLP_SRWLOCK_WAITBLOCK *Last;
-
- /* Next points to the next wait block in the chain. */
- volatile struct _RTLP_SRWLOCK_WAITBLOCK *Next;
-
- union
- {
- /* Wake is only valid for exclusive wait blocks */
- LONG Wake;
- /* The wake chain is only valid for shared wait blocks */
- struct
- {
- PRTLP_SRWLOCK_SHARED_WAKE SharedWakeChain;
- PRTLP_SRWLOCK_SHARED_WAKE LastSharedWake;
- };
- };
-
- BOOLEAN Exclusive;
-} volatile RTLP_SRWLOCK_WAITBLOCK, *PRTLP_SRWLOCK_WAITBLOCK;
-
-
-static VOID
-NTAPI
-RtlpReleaseWaitBlockLockExclusive(IN OUT PRTL_SRWLOCK SRWLock,
- IN PRTLP_SRWLOCK_WAITBLOCK FirstWaitBlock)
-{
- PRTLP_SRWLOCK_WAITBLOCK Next;
- LONG_PTR NewValue;
-
- /* NOTE: We're currently in an exclusive lock in contended mode. */
-
- Next = FirstWaitBlock->Next;
- if (Next != NULL)
- {
- /* There's more blocks chained, we need to update the pointers
- in the next wait block and update the wait block pointer. */
- NewValue = (LONG_PTR)Next | RTL_SRWLOCK_OWNED | RTL_SRWLOCK_CONTENDED;
- if (!FirstWaitBlock->Exclusive)
- {
- /* The next wait block has to be an exclusive lock! */
- ASSERT(Next->Exclusive);
-
- /* Save the shared count */
- Next->SharedCount = FirstWaitBlock->SharedCount;
-
- NewValue |= RTL_SRWLOCK_SHARED;
- }
-
- Next->Last = FirstWaitBlock->Last;
- }
- else
- {
- /* Convert the lock to a simple lock. */
- if (FirstWaitBlock->Exclusive)
- NewValue = RTL_SRWLOCK_OWNED;
- else
- {
- ASSERT(FirstWaitBlock->SharedCount > 0);
-
- NewValue = ((LONG_PTR)FirstWaitBlock->SharedCount <<
RTL_SRWLOCK_BITS) |
- RTL_SRWLOCK_SHARED | RTL_SRWLOCK_OWNED;
- }
- }
-
- (void)InterlockedExchangePointer(&SRWLock->Ptr, (PVOID)NewValue);
-
- if (FirstWaitBlock->Exclusive)
- {
- (void)InterlockedOr(&FirstWaitBlock->Wake,
- TRUE);
- }
- else
- {
- PRTLP_SRWLOCK_SHARED_WAKE WakeChain, NextWake;
-
- /* If we were the first one to acquire the shared
- lock, we now need to wake all others... */
- WakeChain = FirstWaitBlock->SharedWakeChain;
- do
- {
- NextWake = WakeChain->Next;
-
- (void)InterlockedOr((PLONG)&WakeChain->Wake,
- TRUE);
-
- WakeChain = NextWake;
- } while (WakeChain != NULL);
- }
-}
-
-
-static VOID
-NTAPI
-RtlpReleaseWaitBlockLockLastShared(IN OUT PRTL_SRWLOCK SRWLock,
- IN PRTLP_SRWLOCK_WAITBLOCK FirstWaitBlock)
-{
- PRTLP_SRWLOCK_WAITBLOCK Next;
- LONG_PTR NewValue;
-
- /* NOTE: We're currently in a shared lock in contended mode. */
-
- /* The next acquirer to be unwaited *must* be an exclusive lock! */
- ASSERT(FirstWaitBlock->Exclusive);
-
- Next = FirstWaitBlock->Next;
- if (Next != NULL)
- {
- /* There's more blocks chained, we need to update the pointers
- in the next wait block and update the wait block pointer. */
- NewValue = (LONG_PTR)Next | RTL_SRWLOCK_OWNED | RTL_SRWLOCK_CONTENDED;
-
- Next->Last = FirstWaitBlock->Last;
- }
- else
- {
- /* Convert the lock to a simple exclusive lock. */
- NewValue = RTL_SRWLOCK_OWNED;
- }
-
- (void)InterlockedExchangePointer(&SRWLock->Ptr, (PVOID)NewValue);
-
- (void)InterlockedOr(&FirstWaitBlock->Wake,
- TRUE);
-}
-
-
-static VOID
-NTAPI
-RtlpReleaseWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock)
-{
- InterlockedAndPointer(&SRWLock->Ptr,
- ~RTL_SRWLOCK_CONTENTION_LOCK);
-}
-
-
-static PRTLP_SRWLOCK_WAITBLOCK
-NTAPI
-RtlpAcquireWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock)
-{
- LONG_PTR PrevValue;
- PRTLP_SRWLOCK_WAITBLOCK WaitBlock;
-
- while (1)
- {
- PrevValue = InterlockedOrPointer(&SRWLock->Ptr,
- RTL_SRWLOCK_CONTENTION_LOCK);
-
- if (!(PrevValue & RTL_SRWLOCK_CONTENTION_LOCK))
- break;
-
- YieldProcessor();
- }
-
- if (!(PrevValue & RTL_SRWLOCK_CONTENDED) ||
- (PrevValue & ~RTL_SRWLOCK_MASK) == 0)
- {
- /* Too bad, looks like the wait block was removed in the
- meanwhile, unlock again */
- RtlpReleaseWaitBlockLock(SRWLock);
- return NULL;
- }
-
- WaitBlock = (PRTLP_SRWLOCK_WAITBLOCK)(PrevValue & ~RTL_SRWLOCK_MASK);
-
- return WaitBlock;
-}
-
-
-static VOID
-NTAPI
-RtlpAcquireSRWLockExclusiveWait(IN OUT PRTL_SRWLOCK SRWLock,
- IN PRTLP_SRWLOCK_WAITBLOCK WaitBlock)
-{
- LONG_PTR CurrentValue;
-
- while (1)
- {
- CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
- if (!(CurrentValue & RTL_SRWLOCK_SHARED))
- {
- if (CurrentValue & RTL_SRWLOCK_CONTENDED)
- {
- if (WaitBlock->Wake != 0)
- {
- /* Our wait block became the first one
- in the chain, we own the lock now! */
- break;
- }
- }
- else
- {
- /* The last wait block was removed and/or we're
- finally a simple exclusive lock. This means we
- don't need to wait anymore, we acquired the lock! */
- break;
- }
- }
-
- YieldProcessor();
- }
-}
-
-
-static VOID
-NTAPI
-RtlpAcquireSRWLockSharedWait(IN OUT PRTL_SRWLOCK SRWLock,
- IN OUT PRTLP_SRWLOCK_WAITBLOCK FirstWait OPTIONAL,
- IN OUT PRTLP_SRWLOCK_SHARED_WAKE WakeChain)
-{
- if (FirstWait != NULL)
- {
- while (WakeChain->Wake == 0)
- {
- YieldProcessor();
- }
- }
- else
- {
- LONG_PTR CurrentValue;
-
- while (1)
- {
- CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
- if (CurrentValue & RTL_SRWLOCK_SHARED)
- {
- /* The RTL_SRWLOCK_OWNED bit always needs to be set when
- RTL_SRWLOCK_SHARED is set! */
- ASSERT(CurrentValue & RTL_SRWLOCK_OWNED);
-
- if (CurrentValue & RTL_SRWLOCK_CONTENDED)
- {
- if (WakeChain->Wake != 0)
- {
- /* Our wait block became the first one
- in the chain, we own the lock now! */
- break;
- }
- }
- else
- {
- /* The last wait block was removed and/or we're
- finally a simple shared lock. This means we
- don't need to wait anymore, we acquired the lock! */
- break;
- }
- }
-
- YieldProcessor();
- }
- }
-}
-
-
-VOID
-NTAPI
-RtlInitializeSRWLock(OUT PRTL_SRWLOCK SRWLock)
-{
- SRWLock->Ptr = NULL;
-}
-
-
-VOID
-NTAPI
-RtlAcquireSRWLockShared(IN OUT PRTL_SRWLOCK SRWLock)
-{
- __ALIGNED(16) RTLP_SRWLOCK_WAITBLOCK StackWaitBlock;
- RTLP_SRWLOCK_SHARED_WAKE SharedWake;
- LONG_PTR CurrentValue, NewValue;
- PRTLP_SRWLOCK_WAITBLOCK First, Shared, FirstWait;
-
- while (1)
- {
- CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
-
- if (CurrentValue & RTL_SRWLOCK_SHARED)
- {
- /* NOTE: It is possible that the RTL_SRWLOCK_OWNED bit is set! */
-
- if (CurrentValue & RTL_SRWLOCK_CONTENDED)
- {
- /* There's other waiters already, lock the wait blocks and
- increment the shared count */
- First = RtlpAcquireWaitBlockLock(SRWLock);
- if (First != NULL)
- {
- FirstWait = NULL;
-
- if (First->Exclusive)
- {
- /* We need to setup a new wait block! Although
- we're currently in a shared lock and we're acquiring
- a shared lock, there are exclusive locks queued. We need
- to wait until those are released. */
- Shared = First->Last;
-
- if (Shared->Exclusive)
- {
- StackWaitBlock.Exclusive = FALSE;
- StackWaitBlock.SharedCount = 1;
- StackWaitBlock.Next = NULL;
- StackWaitBlock.Last = &StackWaitBlock;
- StackWaitBlock.SharedWakeChain = &SharedWake;
-
- Shared->Next = &StackWaitBlock;
- First->Last = &StackWaitBlock;
-
- Shared = &StackWaitBlock;
- FirstWait = &StackWaitBlock;
- }
- else
- {
- Shared->LastSharedWake->Next = &SharedWake;
- Shared->SharedCount++;
- }
- }
- else
- {
- Shared = First;
- Shared->LastSharedWake->Next = &SharedWake;
- Shared->SharedCount++;
- }
-
- SharedWake.Next = NULL;
- SharedWake.Wake = 0;
-
- Shared->LastSharedWake = &SharedWake;
-
- RtlpReleaseWaitBlockLock(SRWLock);
-
- RtlpAcquireSRWLockSharedWait(SRWLock,
- FirstWait,
- &SharedWake);
-
- /* Successfully incremented the shared count, we acquired the lock
*/
- break;
- }
- }
- else
- {
- /* This is a fastest path, just increment the number of
- current shared locks */
-
- /* Since the RTL_SRWLOCK_SHARED bit is set, the RTL_SRWLOCK_OWNED bit
also has
- to be set! */
-
- ASSERT(CurrentValue & RTL_SRWLOCK_OWNED);
-
- NewValue = (CurrentValue >> RTL_SRWLOCK_BITS) + 1;
- NewValue = (NewValue << RTL_SRWLOCK_BITS) | (CurrentValue &
RTL_SRWLOCK_MASK);
-
- if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr,
- (PVOID)NewValue,
- (PVOID)CurrentValue) ==
CurrentValue)
- {
- /* Successfully incremented the shared count, we acquired the lock
*/
- break;
- }
- }
- }
- else
- {
- if (CurrentValue & RTL_SRWLOCK_OWNED)
- {
- /* The resource is currently acquired exclusively */
- if (CurrentValue & RTL_SRWLOCK_CONTENDED)
- {
- SharedWake.Next = NULL;
- SharedWake.Wake = 0;
-
- /* There's other waiters already, lock the wait blocks and
- increment the shared count. If the last block in the chain
- is an exclusive lock, add another block. */
-
- StackWaitBlock.Exclusive = FALSE;
- StackWaitBlock.SharedCount = 0;
- StackWaitBlock.Next = NULL;
- StackWaitBlock.Last = &StackWaitBlock;
- StackWaitBlock.SharedWakeChain = &SharedWake;
-
- First = RtlpAcquireWaitBlockLock(SRWLock);
- if (First != NULL)
- {
- Shared = First->Last;
- if (Shared->Exclusive)
- {
- Shared->Next = &StackWaitBlock;
- First->Last = &StackWaitBlock;
-
- Shared = &StackWaitBlock;
- FirstWait = &StackWaitBlock;
- }
- else
- {
- FirstWait = NULL;
- Shared->LastSharedWake->Next = &SharedWake;
- }
-
- Shared->SharedCount++;
- Shared->LastSharedWake = &SharedWake;
-
- RtlpReleaseWaitBlockLock(SRWLock);
-
- RtlpAcquireSRWLockSharedWait(SRWLock,
- FirstWait,
- &SharedWake);
-
- /* Successfully incremented the shared count, we acquired the
lock */
- break;
- }
- }
- else
- {
- SharedWake.Next = NULL;
- SharedWake.Wake = 0;
-
- /* We need to setup the first wait block. Currently an exclusive lock
is
- held, change the lock to contended mode. */
- StackWaitBlock.Exclusive = FALSE;
- StackWaitBlock.SharedCount = 1;
- StackWaitBlock.Next = NULL;
- StackWaitBlock.Last = &StackWaitBlock;
- StackWaitBlock.SharedWakeChain = &SharedWake;
- StackWaitBlock.LastSharedWake = &SharedWake;
-
- NewValue = (ULONG_PTR)&StackWaitBlock | RTL_SRWLOCK_OWNED |
RTL_SRWLOCK_CONTENDED;
- if
((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr,
- (PVOID)NewValue,
- (PVOID)CurrentValue)
== CurrentValue)
- {
- RtlpAcquireSRWLockSharedWait(SRWLock,
- &StackWaitBlock,
- &SharedWake);
-
- /* Successfully set the shared count, we acquired the lock */
- break;
- }
- }
- }
- else
- {
- /* This is a fast path, we can simply try to set the shared count to 1
*/
- NewValue = (1 << RTL_SRWLOCK_BITS) | RTL_SRWLOCK_SHARED |
RTL_SRWLOCK_OWNED;
-
- /* The RTL_SRWLOCK_CONTENDED bit should never be set if neither the
- RTL_SRWLOCK_SHARED nor the RTL_SRWLOCK_OWNED bit is set */
- ASSERT(!(CurrentValue & RTL_SRWLOCK_CONTENDED));
-
- if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr,
- (PVOID)NewValue,
- (PVOID)CurrentValue) ==
CurrentValue)
- {
- /* Successfully set the shared count, we acquired the lock */
- break;
- }
- }
- }
-
- YieldProcessor();
- }
-}
-
-
-VOID
-NTAPI
-RtlReleaseSRWLockShared(IN OUT PRTL_SRWLOCK SRWLock)
-{
- LONG_PTR CurrentValue, NewValue;
- PRTLP_SRWLOCK_WAITBLOCK WaitBlock;
- BOOLEAN LastShared;
-
- while (1)
- {
- CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
-
- if (CurrentValue & RTL_SRWLOCK_SHARED)
- {
- if (CurrentValue & RTL_SRWLOCK_CONTENDED)
- {
- /* There's a wait block, we need to wake a pending
- exclusive acquirer if this is the last shared release */
- WaitBlock = RtlpAcquireWaitBlockLock(SRWLock);
- if (WaitBlock != NULL)
- {
- LastShared = (--WaitBlock->SharedCount == 0);
-
- if (LastShared)
- RtlpReleaseWaitBlockLockLastShared(SRWLock,
- WaitBlock);
- else
- RtlpReleaseWaitBlockLock(SRWLock);
-
- /* We released the lock */
- break;
- }
- }
- else
- {
- /* This is a fast path, we can simply decrement the shared
- count and store the pointer */
- NewValue = CurrentValue >> RTL_SRWLOCK_BITS;
-
- if (--NewValue != 0)
- {
- NewValue = (NewValue << RTL_SRWLOCK_BITS) | RTL_SRWLOCK_SHARED
| RTL_SRWLOCK_OWNED;
- }
-
- if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr,
- (PVOID)NewValue,
- (PVOID)CurrentValue) ==
CurrentValue)
- {
- /* Successfully released the lock */
- break;
- }
- }
- }
- else
- {
- /* The RTL_SRWLOCK_SHARED bit has to be present now,
- even in the contended case! */
- RtlRaiseStatus(STATUS_RESOURCE_NOT_OWNED);
- }
-
- YieldProcessor();
- }
-}
-
-
-VOID
-NTAPI
-RtlAcquireSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock)
-{
- __ALIGNED(16) RTLP_SRWLOCK_WAITBLOCK StackWaitBlock;
- PRTLP_SRWLOCK_WAITBLOCK First, Last;
-
- if (InterlockedBitTestAndSetPointer(&SRWLock->Ptr,
- RTL_SRWLOCK_OWNED_BIT))
- {
- LONG_PTR CurrentValue, NewValue;
-
- while (1)
- {
- CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
-
- if (CurrentValue & RTL_SRWLOCK_SHARED)
- {
- /* A shared lock is being held right now. We need to add a wait block!
*/
-
- if (CurrentValue & RTL_SRWLOCK_CONTENDED)
- {
- goto AddWaitBlock;
- }
- else
- {
- /* There are no wait blocks so far, we need to add ourselves as the
first
- wait block. We need to keep the shared count! */
- StackWaitBlock.Exclusive = TRUE;
- StackWaitBlock.SharedCount = (LONG)(CurrentValue >>
RTL_SRWLOCK_BITS);
- StackWaitBlock.Next = NULL;
- StackWaitBlock.Last = &StackWaitBlock;
- StackWaitBlock.Wake = 0;
-
- NewValue = (ULONG_PTR)&StackWaitBlock | RTL_SRWLOCK_SHARED |
RTL_SRWLOCK_CONTENDED | RTL_SRWLOCK_OWNED;
-
- if
((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr,
- (PVOID)NewValue,
- (PVOID)CurrentValue)
== CurrentValue)
- {
- RtlpAcquireSRWLockExclusiveWait(SRWLock,
- &StackWaitBlock);
-
- /* Successfully acquired the exclusive lock */
- break;
- }
- }
- }
- else
- {
- if (CurrentValue & RTL_SRWLOCK_OWNED)
- {
- /* An exclusive lock is being held right now. We need to add a wait
block! */
-
- if (CurrentValue & RTL_SRWLOCK_CONTENDED)
- {
-AddWaitBlock:
- StackWaitBlock.Exclusive = TRUE;
- StackWaitBlock.SharedCount = 0;
- StackWaitBlock.Next = NULL;
- StackWaitBlock.Last = &StackWaitBlock;
- StackWaitBlock.Wake = 0;
-
- First = RtlpAcquireWaitBlockLock(SRWLock);
- if (First != NULL)
- {
- Last = First->Last;
- Last->Next = &StackWaitBlock;
- First->Last = &StackWaitBlock;
-
- RtlpReleaseWaitBlockLock(SRWLock);
-
- RtlpAcquireSRWLockExclusiveWait(SRWLock,
- &StackWaitBlock);
-
- /* Successfully acquired the exclusive lock */
- break;
- }
- }
- else
- {
- /* There are no wait blocks so far, we need to add ourselves as
the first
- wait block. We need to keep the shared count! */
- StackWaitBlock.Exclusive = TRUE;
- StackWaitBlock.SharedCount = 0;
- StackWaitBlock.Next = NULL;
- StackWaitBlock.Last = &StackWaitBlock;
- StackWaitBlock.Wake = 0;
-
- NewValue = (ULONG_PTR)&StackWaitBlock | RTL_SRWLOCK_OWNED |
RTL_SRWLOCK_CONTENDED;
- if
((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr,
- (PVOID)NewValue,
-
(PVOID)CurrentValue) == CurrentValue)
- {
- RtlpAcquireSRWLockExclusiveWait(SRWLock,
- &StackWaitBlock);
-
- /* Successfully acquired the exclusive lock */
- break;
- }
- }
- }
- else
- {
- if (!InterlockedBitTestAndSetPointer(&SRWLock->Ptr,
- RTL_SRWLOCK_OWNED_BIT))
- {
- /* We managed to get hold of a simple exclusive lock! */
- break;
- }
- }
- }
-
- YieldProcessor();
- }
- }
-}
-
-
-VOID
-NTAPI
-RtlReleaseSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock)
-{
- LONG_PTR CurrentValue, NewValue;
- PRTLP_SRWLOCK_WAITBLOCK WaitBlock;
-
- while (1)
- {
- CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
-
- if (!(CurrentValue & RTL_SRWLOCK_OWNED))
- {
- RtlRaiseStatus(STATUS_RESOURCE_NOT_OWNED);
- }
-
- if (!(CurrentValue & RTL_SRWLOCK_SHARED))
- {
- if (CurrentValue & RTL_SRWLOCK_CONTENDED)
- {
- /* There's a wait block, we need to wake the next pending
- acquirer (exclusive or shared) */
- WaitBlock = RtlpAcquireWaitBlockLock(SRWLock);
- if (WaitBlock != NULL)
- {
- RtlpReleaseWaitBlockLockExclusive(SRWLock,
- WaitBlock);
-
- /* We released the lock */
- break;
- }
- }
- else
- {
- /* This is a fast path, we can simply clear the RTL_SRWLOCK_OWNED
- bit. All other bits should be 0 now because this is a simple
- exclusive lock and no one is waiting. */
-
- ASSERT(!(CurrentValue & ~RTL_SRWLOCK_OWNED));
-
- NewValue = 0;
- if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr,
- (PVOID)NewValue,
- (PVOID)CurrentValue) ==
CurrentValue)
- {
- /* We released the lock */
- break;
- }
- }
- }
- else
- {
- /* The RTL_SRWLOCK_SHARED bit must not be present now,
- not even in the contended case! */
- RtlRaiseStatus(STATUS_RESOURCE_NOT_OWNED);
- }
-
- YieldProcessor();
- }
-}