ntdll: Move some synchronization Rtl functions to sync.c.

This commit is contained in:
Alexandre Julliard 2024-06-14 11:40:59 +02:00
parent 88414d0c5b
commit 94d1bc52c3
2 changed files with 372 additions and 385 deletions

View file

@ -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.@]
*/

View file

@ -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" );
}