mirror of https://github.com/FreeRDP/FreeRDP
libwinpr-synch: replace pthreads-based barrier implementation by interlocked operations + event and avoid deadlocks
This commit is contained in:
parent
54264936d1
commit
6c85505ecc
|
@ -27,121 +27,13 @@
|
|||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
BOOL WINAPI InitializeSynchronizationBarrier(LPSYNCHRONIZATION_BARRIER lpBarrier, LONG lTotalThreads, LONG lSpinCount)
|
||||
{
|
||||
int status;
|
||||
WINPR_BARRIER* pBarrier;
|
||||
|
||||
if (!lpBarrier)
|
||||
return FALSE;
|
||||
|
||||
ZeroMemory(lpBarrier, sizeof(SYNCHRONIZATION_BARRIER));
|
||||
|
||||
pBarrier = (WINPR_BARRIER*) calloc(1, sizeof(WINPR_BARRIER));
|
||||
|
||||
if (!pBarrier)
|
||||
return FALSE;
|
||||
|
||||
if (lSpinCount < 0)
|
||||
lSpinCount = 2000;
|
||||
|
||||
pBarrier->lTotalThreads = lTotalThreads;
|
||||
pBarrier->lSpinCount = lSpinCount;
|
||||
|
||||
status = pthread_barrierattr_init(&(pBarrier->attr));
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
fprintf(stderr, "pthread_barrierattr_init failure: %d\n", errno);
|
||||
free(pBarrier);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pthread_barrierattr_setpshared(&(pBarrier->attr), PTHREAD_PROCESS_SHARED);
|
||||
|
||||
status = pthread_barrier_init(&(pBarrier->barrier), &(pBarrier->attr), lTotalThreads);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
fprintf(stderr, "pthread_barrier_init failure: %d\n", errno);
|
||||
free(pBarrier);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
lpBarrier->Reserved3[0] = (ULONG_PTR) pBarrier;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WINAPI EnterSynchronizationBarrier(LPSYNCHRONIZATION_BARRIER lpBarrier, DWORD dwFlags)
|
||||
{
|
||||
BOOL status;
|
||||
int waitStatus;
|
||||
WINPR_BARRIER* pBarrier;
|
||||
|
||||
if (!lpBarrier)
|
||||
return FALSE;
|
||||
|
||||
pBarrier = (WINPR_BARRIER*) lpBarrier->Reserved3[0];
|
||||
|
||||
if (!pBarrier)
|
||||
return FALSE;
|
||||
|
||||
waitStatus = pthread_barrier_wait(&(pBarrier->barrier));
|
||||
|
||||
if (waitStatus == 0)
|
||||
{
|
||||
status = FALSE; /* success, this is not the last thread */
|
||||
}
|
||||
else if (waitStatus == PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
status = TRUE; /* success, this is the last thread */
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "pthread_barrier_wait failure: %d\n", errno);
|
||||
status = FALSE; /* failure */
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
BOOL WINAPI DeleteSynchronizationBarrier(LPSYNCHRONIZATION_BARRIER lpBarrier)
|
||||
{
|
||||
WINPR_BARRIER* pBarrier;
|
||||
|
||||
/**
|
||||
* According to MSDN, DeleteSynchronizationBarrier always returns TRUE
|
||||
*/
|
||||
|
||||
if (!lpBarrier)
|
||||
return TRUE;
|
||||
|
||||
pBarrier = (WINPR_BARRIER*) lpBarrier->Reserved3[0];
|
||||
|
||||
if (!pBarrier)
|
||||
return TRUE;
|
||||
|
||||
pthread_barrier_destroy(&(pBarrier->barrier));
|
||||
|
||||
pthread_barrierattr_destroy(&(pBarrier->attr));
|
||||
|
||||
free(pBarrier);
|
||||
|
||||
ZeroMemory(lpBarrier, sizeof(SYNCHRONIZATION_BARRIER));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#elif (defined(_WIN32) && (_WIN32_WINNT < 0x0602))
|
||||
#if (!defined(_WIN32)) || (defined(_WIN32) && (_WIN32_WINNT < 0x0602))
|
||||
|
||||
#include <winpr/library.h>
|
||||
#include <winpr/interlocked.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static HMODULE g_Kernel32 = NULL;
|
||||
static BOOL g_NativeBarrier = FALSE;
|
||||
static INIT_ONCE g_InitOnce = INIT_ONCE_STATIC_INIT;
|
||||
|
@ -179,14 +71,18 @@ static BOOL CALLBACK InitOnce_Barrier(PINIT_ONCE once, PVOID param, PVOID *conte
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
BOOL WINAPI InitializeSynchronizationBarrier(LPSYNCHRONIZATION_BARRIER lpBarrier, LONG lTotalThreads, LONG lSpinCount)
|
||||
{
|
||||
WINPR_BARRIER* pBarrier;
|
||||
|
||||
#ifdef _WIN32
|
||||
InitOnceExecuteOnce(&g_InitOnce, InitOnce_Barrier, NULL, NULL);
|
||||
|
||||
if (g_NativeBarrier)
|
||||
return pfnInitializeSynchronizationBarrier(lpBarrier, lTotalThreads, lSpinCount);
|
||||
#endif
|
||||
|
||||
if (!lpBarrier)
|
||||
return FALSE;
|
||||
|
@ -224,8 +120,10 @@ BOOL WINAPI EnterSynchronizationBarrier(LPSYNCHRONIZATION_BARRIER lpBarrier, DWO
|
|||
BOOL status = FALSE;
|
||||
WINPR_BARRIER* pBarrier;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (g_NativeBarrier)
|
||||
return pfnEnterSynchronizationBarrier(lpBarrier, dwFlags);
|
||||
#endif
|
||||
|
||||
if (!lpBarrier)
|
||||
return FALSE;
|
||||
|
@ -254,8 +152,10 @@ BOOL WINAPI DeleteSynchronizationBarrier(LPSYNCHRONIZATION_BARRIER lpBarrier)
|
|||
{
|
||||
WINPR_BARRIER* pBarrier;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (g_NativeBarrier)
|
||||
return pfnDeleteSynchronizationBarrier(lpBarrier);
|
||||
#endif
|
||||
|
||||
if (!lpBarrier)
|
||||
return TRUE;
|
||||
|
|
|
@ -146,16 +146,10 @@ struct winpr_timer_queue_timer
|
|||
|
||||
struct winpr_barrier
|
||||
{
|
||||
DECLSPEC_ALIGN(4) LONG count;
|
||||
LONG lTotalThreads;
|
||||
LONG lSpinCount;
|
||||
|
||||
#if !defined(_WIN32)
|
||||
pthread_barrier_t barrier;
|
||||
pthread_barrierattr_t attr;
|
||||
#elif (defined(_WIN32) && (_WIN32_WINNT < 0x0602))
|
||||
HANDLE event;
|
||||
DECLSPEC_ALIGN(4) LONG count;
|
||||
#endif
|
||||
};
|
||||
typedef struct winpr_barrier WINPR_BARRIER;
|
||||
|
||||
|
|
Loading…
Reference in New Issue