Commit 2c903e9e authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Move the critical section fallback code out of the Unix library.

This partially reverts commit ff19f219. Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 647c54e5
...@@ -51,6 +51,44 @@ static BOOL crit_section_has_debuginfo(const RTL_CRITICAL_SECTION *crit) ...@@ -51,6 +51,44 @@ static BOOL crit_section_has_debuginfo(const RTL_CRITICAL_SECTION *crit)
} }
/*********************************************************************** /***********************************************************************
* get_semaphore
*/
static inline HANDLE get_semaphore( RTL_CRITICAL_SECTION *crit )
{
HANDLE ret = crit->LockSemaphore;
if (!ret)
{
HANDLE sem;
if (NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 )) return 0;
if (!(ret = InterlockedCompareExchangePointer( &crit->LockSemaphore, sem, 0 )))
ret = sem;
else
NtClose(sem); /* somebody beat us to it */
}
return ret;
}
/***********************************************************************
* wait_semaphore
*/
static inline NTSTATUS wait_semaphore( RTL_CRITICAL_SECTION *crit, int timeout )
{
NTSTATUS ret;
/* debug info is cleared by MakeCriticalSectionGlobal */
if (!crit_section_has_debuginfo( crit ) ||
((ret = unix_funcs->fast_RtlpWaitForCriticalSection( crit, timeout )) == STATUS_NOT_IMPLEMENTED))
{
HANDLE sem = get_semaphore( crit );
LARGE_INTEGER time;
time.QuadPart = timeout * (LONGLONG)-10000000;
ret = NtWaitForSingleObject( sem, FALSE, &time );
}
return ret;
}
/***********************************************************************
* RtlInitializeCriticalSection (NTDLL.@) * RtlInitializeCriticalSection (NTDLL.@)
* *
* Initialises a new critical section. * Initialises a new critical section.
...@@ -260,7 +298,7 @@ NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit ) ...@@ -260,7 +298,7 @@ NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit )
for (;;) for (;;)
{ {
EXCEPTION_RECORD rec; EXCEPTION_RECORD rec;
NTSTATUS status = unix_funcs->fast_RtlpWaitForCriticalSection( crit, 5 ); NTSTATUS status = wait_semaphore( crit, 5 );
timeout -= 5; timeout -= 5;
if ( status == STATUS_TIMEOUT ) if ( status == STATUS_TIMEOUT )
...@@ -270,14 +308,14 @@ NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit ) ...@@ -270,14 +308,14 @@ NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit )
if (!name) name = "?"; if (!name) name = "?";
ERR( "section %p %s wait timed out in thread %04x, blocked by %04x, retrying (60 sec)\n", ERR( "section %p %s wait timed out in thread %04x, blocked by %04x, retrying (60 sec)\n",
crit, debugstr_a(name), GetCurrentThreadId(), HandleToULong(crit->OwningThread) ); crit, debugstr_a(name), GetCurrentThreadId(), HandleToULong(crit->OwningThread) );
status = unix_funcs->fast_RtlpWaitForCriticalSection( crit, 60 ); status = wait_semaphore( crit, 60 );
timeout -= 60; timeout -= 60;
if ( status == STATUS_TIMEOUT && TRACE_ON(relay) ) if ( status == STATUS_TIMEOUT && TRACE_ON(relay) )
{ {
ERR( "section %p %s wait timed out in thread %04x, blocked by %04x, retrying (5 min)\n", ERR( "section %p %s wait timed out in thread %04x, blocked by %04x, retrying (5 min)\n",
crit, debugstr_a(name), GetCurrentThreadId(), HandleToULong(crit->OwningThread) ); crit, debugstr_a(name), GetCurrentThreadId(), HandleToULong(crit->OwningThread) );
status = unix_funcs->fast_RtlpWaitForCriticalSection( crit, 300 ); status = wait_semaphore( crit, 300 );
timeout -= 300; timeout -= 300;
} }
} }
...@@ -327,8 +365,15 @@ NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit ) ...@@ -327,8 +365,15 @@ NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit )
*/ */
NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
{ {
NTSTATUS ret = unix_funcs->fast_RtlpUnWaitCriticalSection( crit ); NTSTATUS ret;
/* debug info is cleared by MakeCriticalSectionGlobal */
if (!crit_section_has_debuginfo( crit ) ||
((ret = unix_funcs->fast_RtlpUnWaitCriticalSection( crit )) == STATUS_NOT_IMPLEMENTED))
{
HANDLE sem = get_semaphore( crit );
ret = NtReleaseSemaphore( sem, 1, NULL );
}
if (ret) RtlRaiseStatus( ret ); if (ret) RtlRaiseStatus( ret );
return ret; return ret;
} }
......
...@@ -2129,16 +2129,9 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl ...@@ -2129,16 +2129,9 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl
} }
static void *no_debug_info_marker = (void *)(ULONG_PTR)-1;
static BOOL crit_section_has_debuginfo(const RTL_CRITICAL_SECTION *crit)
{
return crit->DebugInfo != NULL && crit->DebugInfo != no_debug_info_marker;
}
#ifdef __linux__ #ifdef __linux__
static inline NTSTATUS fast_critsection_wait( RTL_CRITICAL_SECTION *crit, int timeout ) NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
{ {
int val; int val;
struct timespec timespec; struct timespec timespec;
...@@ -2157,7 +2150,7 @@ static inline NTSTATUS fast_critsection_wait( RTL_CRITICAL_SECTION *crit, int ti ...@@ -2157,7 +2150,7 @@ static inline NTSTATUS fast_critsection_wait( RTL_CRITICAL_SECTION *crit, int ti
return STATUS_WAIT_0; return STATUS_WAIT_0;
} }
static inline NTSTATUS fast_critsection_wake( RTL_CRITICAL_SECTION *crit ) NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
{ {
if (!use_futexes()) return STATUS_NOT_IMPLEMENTED; if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
...@@ -2189,7 +2182,7 @@ static inline semaphore_t get_mach_semaphore( RTL_CRITICAL_SECTION *crit ) ...@@ -2189,7 +2182,7 @@ static inline semaphore_t get_mach_semaphore( RTL_CRITICAL_SECTION *crit )
return ret; return ret;
} }
static inline NTSTATUS fast_critsection_wait( RTL_CRITICAL_SECTION *crit, int timeout ) NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
{ {
mach_timespec_t timespec; mach_timespec_t timespec;
semaphore_t sem = get_mach_semaphore( crit ); semaphore_t sem = get_mach_semaphore( crit );
...@@ -2212,7 +2205,7 @@ static inline NTSTATUS fast_critsection_wait( RTL_CRITICAL_SECTION *crit, int ti ...@@ -2212,7 +2205,7 @@ static inline NTSTATUS fast_critsection_wait( RTL_CRITICAL_SECTION *crit, int ti
} }
} }
static inline NTSTATUS fast_critsection_wake( RTL_CRITICAL_SECTION *crit ) NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
{ {
semaphore_t sem = get_mach_semaphore( crit ); semaphore_t sem = get_mach_semaphore( crit );
semaphore_signal( sem ); semaphore_signal( sem );
...@@ -2227,12 +2220,12 @@ NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit ) ...@@ -2227,12 +2220,12 @@ NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
#else /* __APPLE__ */ #else /* __APPLE__ */
static inline NTSTATUS fast_critsection_wait( RTL_CRITICAL_SECTION *crit, int timeout ) NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
{ {
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
static inline NTSTATUS fast_critsection_wake( RTL_CRITICAL_SECTION *crit ) NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
{ {
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
...@@ -2244,56 +2237,6 @@ NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit ) ...@@ -2244,56 +2237,6 @@ NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
#endif #endif
static inline HANDLE get_critsection_semaphore( RTL_CRITICAL_SECTION *crit )
{
HANDLE ret = crit->LockSemaphore;
if (!ret)
{
HANDLE sem;
if (NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 )) return 0;
if (!(ret = InterlockedCompareExchangePointer( &crit->LockSemaphore, sem, 0 )))
ret = sem;
else
NtClose( sem ); /* somebody beat us to it */
}
return ret;
}
NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
{
NTSTATUS ret;
/* debug info is cleared by MakeCriticalSectionGlobal */
if (!crit_section_has_debuginfo( crit ) ||
((ret = fast_critsection_wait( crit, timeout )) == STATUS_NOT_IMPLEMENTED))
{
HANDLE sem = get_critsection_semaphore( crit );
LARGE_INTEGER time;
select_op_t select_op;
time.QuadPart = timeout * (LONGLONG)-10000000;
select_op.wait.op = SELECT_WAIT;
select_op.wait.handles[0] = wine_server_obj_handle( sem );
ret = server_wait( &select_op, offsetof( select_op_t, wait.handles[1] ), 0, &time );
}
return ret;
}
NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
{
NTSTATUS ret;
/* debug info is cleared by MakeCriticalSectionGlobal */
if (!crit_section_has_debuginfo( crit ) ||
((ret = fast_critsection_wake( crit )) == STATUS_NOT_IMPLEMENTED))
{
HANDLE sem = get_critsection_semaphore( crit );
ret = NtReleaseSemaphore( sem, 1, NULL );
}
return ret;
}
#ifdef __linux__ #ifdef __linux__
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment