libwinpr-synch: replace pthreads-based barrier implementation by interlocked operations + event and avoid deadlocks

This commit is contained in:
Marc-André Moreau 2014-08-08 21:02:15 -04:00
parent 54264936d1
commit 6c85505ecc
2 changed files with 12 additions and 118 deletions

View File

@ -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;

View File

@ -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;