mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-05 18:01:34 +00:00
ntdll: Move some synchronization Rtl functions to sync.c.
This commit is contained in:
parent
88414d0c5b
commit
94d1bc52c3
2 changed files with 372 additions and 385 deletions
385
dlls/ntdll/rtl.c
385
dlls/ntdll/rtl.c
|
@ -101,204 +101,6 @@ static const int hex_table[] = {
|
|||
-1, 10, 11, 12, 13, 14, 15 /* 0x60-0x66 */
|
||||
};
|
||||
|
||||
/*
|
||||
* resource functions
|
||||
*/
|
||||
|
||||
/***********************************************************************
|
||||
* RtlInitializeResource (NTDLL.@)
|
||||
*
|
||||
* xxxResource() functions implement multiple-reader-single-writer lock.
|
||||
* The code is based on information published in WDJ January 1999 issue.
|
||||
*/
|
||||
void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl)
|
||||
{
|
||||
if( rwl )
|
||||
{
|
||||
rwl->iNumberActive = 0;
|
||||
rwl->uExclusiveWaiters = 0;
|
||||
rwl->uSharedWaiters = 0;
|
||||
rwl->hOwningThreadId = 0;
|
||||
rwl->dwTimeoutBoost = 0; /* no info on this one, default value is 0 */
|
||||
RtlInitializeCriticalSectionEx( &rwl->rtlCS, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO );
|
||||
rwl->rtlCS.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RTL_RWLOCK.rtlCS");
|
||||
NtCreateSemaphore( &rwl->hExclusiveReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
|
||||
NtCreateSemaphore( &rwl->hSharedReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlDeleteResource (NTDLL.@)
|
||||
*/
|
||||
void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl)
|
||||
{
|
||||
if( rwl )
|
||||
{
|
||||
RtlEnterCriticalSection( &rwl->rtlCS );
|
||||
if( rwl->iNumberActive || rwl->uExclusiveWaiters || rwl->uSharedWaiters )
|
||||
ERR("Deleting active MRSW lock (%p), expect failure\n", rwl );
|
||||
rwl->hOwningThreadId = 0;
|
||||
rwl->uExclusiveWaiters = rwl->uSharedWaiters = 0;
|
||||
rwl->iNumberActive = 0;
|
||||
NtClose( rwl->hExclusiveReleaseSemaphore );
|
||||
NtClose( rwl->hSharedReleaseSemaphore );
|
||||
RtlLeaveCriticalSection( &rwl->rtlCS );
|
||||
rwl->rtlCS.DebugInfo->Spare[0] = 0;
|
||||
RtlDeleteCriticalSection( &rwl->rtlCS );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlAcquireResourceExclusive (NTDLL.@)
|
||||
*/
|
||||
BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait)
|
||||
{
|
||||
BYTE retVal = 0;
|
||||
if( !rwl ) return 0;
|
||||
|
||||
start:
|
||||
RtlEnterCriticalSection( &rwl->rtlCS );
|
||||
if( rwl->iNumberActive == 0 ) /* lock is free */
|
||||
{
|
||||
rwl->iNumberActive = -1;
|
||||
retVal = 1;
|
||||
}
|
||||
else if( rwl->iNumberActive < 0 ) /* exclusive lock in progress */
|
||||
{
|
||||
if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
|
||||
{
|
||||
retVal = 1;
|
||||
rwl->iNumberActive--;
|
||||
goto done;
|
||||
}
|
||||
wait:
|
||||
if( fWait )
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
rwl->uExclusiveWaiters++;
|
||||
|
||||
RtlLeaveCriticalSection( &rwl->rtlCS );
|
||||
status = NtWaitForSingleObject( rwl->hExclusiveReleaseSemaphore, FALSE, NULL );
|
||||
if( HIWORD(status) )
|
||||
goto done;
|
||||
goto start; /* restart the acquisition to avoid deadlocks */
|
||||
}
|
||||
}
|
||||
else /* one or more shared locks are in progress */
|
||||
if( fWait )
|
||||
goto wait;
|
||||
|
||||
if( retVal == 1 )
|
||||
rwl->hOwningThreadId = ULongToHandle(GetCurrentThreadId());
|
||||
done:
|
||||
RtlLeaveCriticalSection( &rwl->rtlCS );
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RtlAcquireResourceShared (NTDLL.@)
|
||||
*/
|
||||
BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
BYTE retVal = 0;
|
||||
if( !rwl ) return 0;
|
||||
|
||||
start:
|
||||
RtlEnterCriticalSection( &rwl->rtlCS );
|
||||
if( rwl->iNumberActive < 0 )
|
||||
{
|
||||
if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
|
||||
{
|
||||
rwl->iNumberActive--;
|
||||
retVal = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if( fWait )
|
||||
{
|
||||
rwl->uSharedWaiters++;
|
||||
RtlLeaveCriticalSection( &rwl->rtlCS );
|
||||
status = NtWaitForSingleObject( rwl->hSharedReleaseSemaphore, FALSE, NULL );
|
||||
if( HIWORD(status) )
|
||||
goto done;
|
||||
goto start;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( status != STATUS_WAIT_0 ) /* otherwise RtlReleaseResource() has already done it */
|
||||
rwl->iNumberActive++;
|
||||
retVal = 1;
|
||||
}
|
||||
done:
|
||||
RtlLeaveCriticalSection( &rwl->rtlCS );
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlReleaseResource (NTDLL.@)
|
||||
*/
|
||||
void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl)
|
||||
{
|
||||
RtlEnterCriticalSection( &rwl->rtlCS );
|
||||
|
||||
if( rwl->iNumberActive > 0 ) /* have one or more readers */
|
||||
{
|
||||
if( --rwl->iNumberActive == 0 )
|
||||
{
|
||||
if( rwl->uExclusiveWaiters )
|
||||
{
|
||||
wake_exclusive:
|
||||
rwl->uExclusiveWaiters--;
|
||||
NtReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if( rwl->iNumberActive < 0 ) /* have a writer, possibly recursive */
|
||||
{
|
||||
if( ++rwl->iNumberActive == 0 )
|
||||
{
|
||||
rwl->hOwningThreadId = 0;
|
||||
if( rwl->uExclusiveWaiters )
|
||||
goto wake_exclusive;
|
||||
else
|
||||
if( rwl->uSharedWaiters )
|
||||
{
|
||||
UINT n = rwl->uSharedWaiters;
|
||||
rwl->iNumberActive = rwl->uSharedWaiters; /* prevent new writers from joining until
|
||||
* all queued readers have done their thing */
|
||||
rwl->uSharedWaiters = 0;
|
||||
NtReleaseSemaphore( rwl->hSharedReleaseSemaphore, n, NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
RtlLeaveCriticalSection( &rwl->rtlCS );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlDumpResource (NTDLL.@)
|
||||
*/
|
||||
void WINAPI RtlDumpResource(LPRTL_RWLOCK rwl)
|
||||
{
|
||||
if( rwl )
|
||||
{
|
||||
MESSAGE("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n",
|
||||
rwl, rwl->iNumberActive, rwl->uSharedWaiters, rwl->uExclusiveWaiters );
|
||||
if( rwl->iNumberActive )
|
||||
MESSAGE("\towner thread = %p\n", rwl->hOwningThreadId );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* misc functions
|
||||
*/
|
||||
|
||||
static LONG WINAPI debug_exception_handler( EXCEPTION_POINTERS *eptr )
|
||||
{
|
||||
|
@ -1429,193 +1231,6 @@ PVOID WINAPI RtlDecodePointer( PVOID ptr )
|
|||
return (PVOID)(ptrval ^ get_pointer_obfuscator());
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlInitializeSListHead [NTDLL.@]
|
||||
*/
|
||||
VOID WINAPI RtlInitializeSListHead(PSLIST_HEADER list)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
list->Alignment = list->Region = 0;
|
||||
list->Header16.HeaderType = 1; /* we use the 16-byte header */
|
||||
#else
|
||||
list->Alignment = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlQueryDepthSList [NTDLL.@]
|
||||
*/
|
||||
WORD WINAPI RtlQueryDepthSList(PSLIST_HEADER list)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return list->Header16.Depth;
|
||||
#else
|
||||
return list->Depth;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlFirstEntrySList [NTDLL.@]
|
||||
*/
|
||||
PSLIST_ENTRY WINAPI RtlFirstEntrySList(const SLIST_HEADER* list)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return (SLIST_ENTRY *)((ULONG_PTR)list->Header16.NextEntry << 4);
|
||||
#else
|
||||
return list->Next.Next;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlInterlockedFlushSList [NTDLL.@]
|
||||
*/
|
||||
PSLIST_ENTRY WINAPI RtlInterlockedFlushSList(PSLIST_HEADER list)
|
||||
{
|
||||
SLIST_HEADER old, new;
|
||||
|
||||
#ifdef _WIN64
|
||||
if (!list->Header16.NextEntry) return NULL;
|
||||
new.Alignment = new.Region = 0;
|
||||
new.Header16.HeaderType = 1; /* we use the 16-byte header */
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
new.Header16.Sequence = old.Header16.Sequence + 1;
|
||||
} while (!InterlockedCompareExchange128((__int64 *)list, new.Region, new.Alignment, (__int64 *)&old));
|
||||
return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
|
||||
#else
|
||||
if (!list->Next.Next) return NULL;
|
||||
new.Alignment = 0;
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
new.Sequence = old.Sequence + 1;
|
||||
} while (InterlockedCompareExchange64((__int64 *)&list->Alignment, new.Alignment,
|
||||
old.Alignment) != old.Alignment);
|
||||
return old.Next.Next;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlInterlockedPushEntrySList [NTDLL.@]
|
||||
*/
|
||||
PSLIST_ENTRY WINAPI RtlInterlockedPushEntrySList(PSLIST_HEADER list, PSLIST_ENTRY entry)
|
||||
{
|
||||
SLIST_HEADER old, new;
|
||||
|
||||
#ifdef _WIN64
|
||||
new.Header16.NextEntry = (ULONG_PTR)entry >> 4;
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
entry->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
|
||||
new.Header16.Depth = old.Header16.Depth + 1;
|
||||
new.Header16.Sequence = old.Header16.Sequence + 1;
|
||||
} while (!InterlockedCompareExchange128((__int64 *)list, new.Region, new.Alignment, (__int64 *)&old));
|
||||
return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
|
||||
#else
|
||||
new.Next.Next = entry;
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
entry->Next = old.Next.Next;
|
||||
new.Depth = old.Depth + 1;
|
||||
new.Sequence = old.Sequence + 1;
|
||||
} while (InterlockedCompareExchange64((__int64 *)&list->Alignment, new.Alignment,
|
||||
old.Alignment) != old.Alignment);
|
||||
return old.Next.Next;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlInterlockedPopEntrySList [NTDLL.@]
|
||||
*/
|
||||
PSLIST_ENTRY WINAPI RtlInterlockedPopEntrySList(PSLIST_HEADER list)
|
||||
{
|
||||
SLIST_HEADER old, new;
|
||||
PSLIST_ENTRY entry;
|
||||
|
||||
#ifdef _WIN64
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
if (!(entry = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4))) return NULL;
|
||||
/* entry could be deleted by another thread */
|
||||
__TRY
|
||||
{
|
||||
new.Header16.NextEntry = (ULONG_PTR)entry->Next >> 4;
|
||||
new.Header16.Depth = old.Header16.Depth - 1;
|
||||
new.Header16.Sequence = old.Header16.Sequence + 1;
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
}
|
||||
__ENDTRY
|
||||
} while (!InterlockedCompareExchange128((__int64 *)list, new.Region, new.Alignment, (__int64 *)&old));
|
||||
#else
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
if (!(entry = old.Next.Next)) return NULL;
|
||||
/* entry could be deleted by another thread */
|
||||
__TRY
|
||||
{
|
||||
new.Next.Next = entry->Next;
|
||||
new.Depth = old.Depth - 1;
|
||||
new.Sequence = old.Sequence + 1;
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
}
|
||||
__ENDTRY
|
||||
} while (InterlockedCompareExchange64((__int64 *)&list->Alignment, new.Alignment,
|
||||
old.Alignment) != old.Alignment);
|
||||
#endif
|
||||
return entry;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlInterlockedPushListSListEx [NTDLL.@]
|
||||
*/
|
||||
PSLIST_ENTRY WINAPI RtlInterlockedPushListSListEx(PSLIST_HEADER list, PSLIST_ENTRY first,
|
||||
PSLIST_ENTRY last, ULONG count)
|
||||
{
|
||||
SLIST_HEADER old, new;
|
||||
|
||||
#ifdef _WIN64
|
||||
new.Header16.NextEntry = (ULONG_PTR)first >> 4;
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
new.Header16.Depth = old.Header16.Depth + count;
|
||||
new.Header16.Sequence = old.Header16.Sequence + 1;
|
||||
last->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
|
||||
} while (!InterlockedCompareExchange128((__int64 *)list, new.Region, new.Alignment, (__int64 *)&old));
|
||||
return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
|
||||
#else
|
||||
new.Next.Next = first;
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
new.Depth = old.Depth + count;
|
||||
new.Sequence = old.Sequence + 1;
|
||||
last->Next = old.Next.Next;
|
||||
} while (InterlockedCompareExchange64((__int64 *)&list->Alignment, new.Alignment,
|
||||
old.Alignment) != old.Alignment);
|
||||
return old.Next.Next;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlInterlockedPushListSList [NTDLL.@]
|
||||
*/
|
||||
DEFINE_FASTCALL_WRAPPER(RtlInterlockedPushListSList, 16)
|
||||
PSLIST_ENTRY FASTCALL RtlInterlockedPushListSList(PSLIST_HEADER list, PSLIST_ENTRY first,
|
||||
PSLIST_ENTRY last, ULONG count)
|
||||
{
|
||||
return RtlInterlockedPushListSListEx(list, first, last, count);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* RtlGetCompressionWorkSpaceSize [NTDLL.@]
|
||||
*/
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "winternl.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/list.h"
|
||||
#include "wine/exception.h"
|
||||
#include "ntdll_misc.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(sync);
|
||||
|
@ -999,3 +1000,374 @@ void WINAPI RtlWakeAddressSingle( const void *addr )
|
|||
|
||||
if (tid) NtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)tid );
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlInitializeSListHead (NTDLL.@)
|
||||
*/
|
||||
void WINAPI RtlInitializeSListHead(PSLIST_HEADER list)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
list->Alignment = list->Region = 0;
|
||||
list->Header16.HeaderType = 1; /* we use the 16-byte header */
|
||||
#else
|
||||
list->Alignment = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlQueryDepthSList (NTDLL.@)
|
||||
*/
|
||||
WORD WINAPI RtlQueryDepthSList(PSLIST_HEADER list)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return list->Header16.Depth;
|
||||
#else
|
||||
return list->Depth;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlFirstEntrySList (NTDLL.@)
|
||||
*/
|
||||
PSLIST_ENTRY WINAPI RtlFirstEntrySList(const SLIST_HEADER* list)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return (SLIST_ENTRY *)((ULONG_PTR)list->Header16.NextEntry << 4);
|
||||
#else
|
||||
return list->Next.Next;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlInterlockedFlushSList (NTDLL.@)
|
||||
*/
|
||||
PSLIST_ENTRY WINAPI RtlInterlockedFlushSList(PSLIST_HEADER list)
|
||||
{
|
||||
SLIST_HEADER old, new;
|
||||
|
||||
#ifdef _WIN64
|
||||
if (!list->Header16.NextEntry) return NULL;
|
||||
new.Alignment = new.Region = 0;
|
||||
new.Header16.HeaderType = 1; /* we use the 16-byte header */
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
new.Header16.Sequence = old.Header16.Sequence + 1;
|
||||
} while (!InterlockedCompareExchange128((__int64 *)list, new.Region, new.Alignment, (__int64 *)&old));
|
||||
return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
|
||||
#else
|
||||
if (!list->Next.Next) return NULL;
|
||||
new.Alignment = 0;
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
new.Sequence = old.Sequence + 1;
|
||||
} while (InterlockedCompareExchange64((__int64 *)&list->Alignment, new.Alignment,
|
||||
old.Alignment) != old.Alignment);
|
||||
return old.Next.Next;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlInterlockedPushEntrySList (NTDLL.@)
|
||||
*/
|
||||
PSLIST_ENTRY WINAPI RtlInterlockedPushEntrySList(PSLIST_HEADER list, PSLIST_ENTRY entry)
|
||||
{
|
||||
SLIST_HEADER old, new;
|
||||
|
||||
#ifdef _WIN64
|
||||
new.Header16.NextEntry = (ULONG_PTR)entry >> 4;
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
entry->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
|
||||
new.Header16.Depth = old.Header16.Depth + 1;
|
||||
new.Header16.Sequence = old.Header16.Sequence + 1;
|
||||
} while (!InterlockedCompareExchange128((__int64 *)list, new.Region, new.Alignment, (__int64 *)&old));
|
||||
return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
|
||||
#else
|
||||
new.Next.Next = entry;
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
entry->Next = old.Next.Next;
|
||||
new.Depth = old.Depth + 1;
|
||||
new.Sequence = old.Sequence + 1;
|
||||
} while (InterlockedCompareExchange64((__int64 *)&list->Alignment, new.Alignment,
|
||||
old.Alignment) != old.Alignment);
|
||||
return old.Next.Next;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlInterlockedPopEntrySList (NTDLL.@)
|
||||
*/
|
||||
PSLIST_ENTRY WINAPI RtlInterlockedPopEntrySList(PSLIST_HEADER list)
|
||||
{
|
||||
SLIST_HEADER old, new;
|
||||
PSLIST_ENTRY entry;
|
||||
|
||||
#ifdef _WIN64
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
if (!(entry = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4))) return NULL;
|
||||
/* entry could be deleted by another thread */
|
||||
__TRY
|
||||
{
|
||||
new.Header16.NextEntry = (ULONG_PTR)entry->Next >> 4;
|
||||
new.Header16.Depth = old.Header16.Depth - 1;
|
||||
new.Header16.Sequence = old.Header16.Sequence + 1;
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
}
|
||||
__ENDTRY
|
||||
} while (!InterlockedCompareExchange128((__int64 *)list, new.Region, new.Alignment, (__int64 *)&old));
|
||||
#else
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
if (!(entry = old.Next.Next)) return NULL;
|
||||
/* entry could be deleted by another thread */
|
||||
__TRY
|
||||
{
|
||||
new.Next.Next = entry->Next;
|
||||
new.Depth = old.Depth - 1;
|
||||
new.Sequence = old.Sequence + 1;
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
}
|
||||
__ENDTRY
|
||||
} while (InterlockedCompareExchange64((__int64 *)&list->Alignment, new.Alignment,
|
||||
old.Alignment) != old.Alignment);
|
||||
#endif
|
||||
return entry;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlInterlockedPushListSListEx (NTDLL.@)
|
||||
*/
|
||||
PSLIST_ENTRY WINAPI RtlInterlockedPushListSListEx(PSLIST_HEADER list, PSLIST_ENTRY first,
|
||||
PSLIST_ENTRY last, ULONG count)
|
||||
{
|
||||
SLIST_HEADER old, new;
|
||||
|
||||
#ifdef _WIN64
|
||||
new.Header16.NextEntry = (ULONG_PTR)first >> 4;
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
new.Header16.Depth = old.Header16.Depth + count;
|
||||
new.Header16.Sequence = old.Header16.Sequence + 1;
|
||||
last->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
|
||||
} while (!InterlockedCompareExchange128((__int64 *)list, new.Region, new.Alignment, (__int64 *)&old));
|
||||
return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
|
||||
#else
|
||||
new.Next.Next = first;
|
||||
do
|
||||
{
|
||||
old = *list;
|
||||
new.Depth = old.Depth + count;
|
||||
new.Sequence = old.Sequence + 1;
|
||||
last->Next = old.Next.Next;
|
||||
} while (InterlockedCompareExchange64((__int64 *)&list->Alignment, new.Alignment,
|
||||
old.Alignment) != old.Alignment);
|
||||
return old.Next.Next;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RtlInterlockedPushListSList (NTDLL.@)
|
||||
*/
|
||||
DEFINE_FASTCALL_WRAPPER(RtlInterlockedPushListSList, 16)
|
||||
PSLIST_ENTRY FASTCALL RtlInterlockedPushListSList(PSLIST_HEADER list, PSLIST_ENTRY first,
|
||||
PSLIST_ENTRY last, ULONG count)
|
||||
{
|
||||
return RtlInterlockedPushListSListEx(list, first, last, count);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RtlInitializeResource (NTDLL.@)
|
||||
*
|
||||
* xxxResource() functions implement multiple-reader-single-writer lock.
|
||||
* The code is based on information published in WDJ January 1999 issue.
|
||||
*/
|
||||
void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl)
|
||||
{
|
||||
if (!rwl) return;
|
||||
rwl->iNumberActive = 0;
|
||||
rwl->uExclusiveWaiters = 0;
|
||||
rwl->uSharedWaiters = 0;
|
||||
rwl->hOwningThreadId = 0;
|
||||
rwl->dwTimeoutBoost = 0; /* no info on this one, default value is 0 */
|
||||
RtlInitializeCriticalSectionEx( &rwl->rtlCS, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO );
|
||||
rwl->rtlCS.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RTL_RWLOCK.rtlCS");
|
||||
NtCreateSemaphore( &rwl->hExclusiveReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
|
||||
NtCreateSemaphore( &rwl->hSharedReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RtlDeleteResource (NTDLL.@)
|
||||
*/
|
||||
void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl)
|
||||
{
|
||||
if (!rwl) return;
|
||||
RtlEnterCriticalSection( &rwl->rtlCS );
|
||||
if( rwl->iNumberActive || rwl->uExclusiveWaiters || rwl->uSharedWaiters )
|
||||
ERR("Deleting active MRSW lock (%p), expect failure\n", rwl );
|
||||
rwl->hOwningThreadId = 0;
|
||||
rwl->uExclusiveWaiters = rwl->uSharedWaiters = 0;
|
||||
rwl->iNumberActive = 0;
|
||||
NtClose( rwl->hExclusiveReleaseSemaphore );
|
||||
NtClose( rwl->hSharedReleaseSemaphore );
|
||||
RtlLeaveCriticalSection( &rwl->rtlCS );
|
||||
rwl->rtlCS.DebugInfo->Spare[0] = 0;
|
||||
RtlDeleteCriticalSection( &rwl->rtlCS );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RtlAcquireResourceExclusive (NTDLL.@)
|
||||
*/
|
||||
BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait)
|
||||
{
|
||||
BYTE retVal = 0;
|
||||
|
||||
if (!rwl) return 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
RtlEnterCriticalSection( &rwl->rtlCS );
|
||||
if( rwl->iNumberActive == 0 ) /* lock is free */
|
||||
{
|
||||
rwl->iNumberActive = -1;
|
||||
retVal = 1;
|
||||
}
|
||||
else if( rwl->iNumberActive < 0 ) /* exclusive lock in progress */
|
||||
{
|
||||
if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
|
||||
{
|
||||
retVal = 1;
|
||||
rwl->iNumberActive--;
|
||||
break;
|
||||
}
|
||||
wait:
|
||||
if( fWait )
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
rwl->uExclusiveWaiters++;
|
||||
|
||||
RtlLeaveCriticalSection( &rwl->rtlCS );
|
||||
status = NtWaitForSingleObject( rwl->hExclusiveReleaseSemaphore, FALSE, NULL );
|
||||
if( HIWORD(status) ) break;
|
||||
continue; /* restart the acquisition to avoid deadlocks */
|
||||
}
|
||||
}
|
||||
else /* one or more shared locks are in progress */
|
||||
if( fWait )
|
||||
goto wait;
|
||||
|
||||
if( retVal == 1 ) rwl->hOwningThreadId = ULongToHandle(GetCurrentThreadId());
|
||||
break;
|
||||
}
|
||||
RtlLeaveCriticalSection( &rwl->rtlCS );
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RtlAcquireResourceShared (NTDLL.@)
|
||||
*/
|
||||
BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
BYTE retVal = 0;
|
||||
|
||||
if (!rwl) return 0;
|
||||
for (;;)
|
||||
{
|
||||
RtlEnterCriticalSection( &rwl->rtlCS );
|
||||
if( rwl->iNumberActive < 0 )
|
||||
{
|
||||
if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
|
||||
{
|
||||
rwl->iNumberActive--;
|
||||
retVal = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if( fWait )
|
||||
{
|
||||
rwl->uSharedWaiters++;
|
||||
RtlLeaveCriticalSection( &rwl->rtlCS );
|
||||
status = NtWaitForSingleObject( rwl->hSharedReleaseSemaphore, FALSE, NULL );
|
||||
if( HIWORD(status) ) break;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( status != STATUS_WAIT_0 ) /* otherwise RtlReleaseResource() has already done it */
|
||||
rwl->iNumberActive++;
|
||||
retVal = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
RtlLeaveCriticalSection( &rwl->rtlCS );
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlReleaseResource (NTDLL.@)
|
||||
*/
|
||||
void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl)
|
||||
{
|
||||
RtlEnterCriticalSection( &rwl->rtlCS );
|
||||
|
||||
if( rwl->iNumberActive > 0 ) /* have one or more readers */
|
||||
{
|
||||
if( --rwl->iNumberActive == 0 )
|
||||
{
|
||||
if( rwl->uExclusiveWaiters )
|
||||
{
|
||||
rwl->uExclusiveWaiters--;
|
||||
NtReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( rwl->iNumberActive < 0 ) /* have a writer, possibly recursive */
|
||||
{
|
||||
if( ++rwl->iNumberActive == 0 )
|
||||
{
|
||||
rwl->hOwningThreadId = 0;
|
||||
if( rwl->uExclusiveWaiters )
|
||||
{
|
||||
rwl->uExclusiveWaiters--;
|
||||
NtReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
|
||||
}
|
||||
else if( rwl->uSharedWaiters )
|
||||
{
|
||||
UINT n = rwl->uSharedWaiters;
|
||||
rwl->iNumberActive = rwl->uSharedWaiters; /* prevent new writers from joining until
|
||||
* all queued readers have done their thing */
|
||||
rwl->uSharedWaiters = 0;
|
||||
NtReleaseSemaphore( rwl->hSharedReleaseSemaphore, n, NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
RtlLeaveCriticalSection( &rwl->rtlCS );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlDumpResource (NTDLL.@)
|
||||
*/
|
||||
void WINAPI RtlDumpResource(LPRTL_RWLOCK rwl)
|
||||
{
|
||||
if (!rwl) return;
|
||||
ERR( "%p: active count = %i waiting readers = %i waiting writers = %i owner thread = %p",
|
||||
rwl, rwl->iNumberActive, rwl->uSharedWaiters, rwl->uExclusiveWaiters, rwl->hOwningThreadId );
|
||||
ERR( "\n" );
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue