21#include <winpr/config.h> 
   23#include <winpr/synch.h> 
   24#include <winpr/assert.h> 
   30#ifdef WINPR_SYNCHRONIZATION_BARRIER 
   32#include <winpr/sysinfo.h> 
   33#include <winpr/library.h> 
   34#include <winpr/interlocked.h> 
   35#include <winpr/thread.h> 
   49static HMODULE g_Kernel32 = NULL;
 
   50static BOOL g_NativeBarrier = FALSE;
 
   51static INIT_ONCE g_InitOnce = INIT_ONCE_STATIC_INIT;
 
   54                                                         LONG lTotalThreads, LONG lSpinCount);
 
   59static fnInitializeSynchronizationBarrier pfnInitializeSynchronizationBarrier = NULL;
 
   60static fnEnterSynchronizationBarrier pfnEnterSynchronizationBarrier = NULL;
 
   61static fnDeleteSynchronizationBarrier pfnDeleteSynchronizationBarrier = NULL;
 
   63static BOOL CALLBACK InitOnce_Barrier(
PINIT_ONCE once, PVOID param, PVOID* context)
 
   65  g_Kernel32 = LoadLibraryA(
"kernel32.dll");
 
   70  pfnInitializeSynchronizationBarrier = GetProcAddressAs(
 
   71      g_Kernel32, 
"InitializeSynchronizationBarrier", fnInitializeSynchronizationBarrier);
 
   73  pfnEnterSynchronizationBarrier =
 
   74      GetProcAddressAs(g_Kernel32, 
"EnterSynchronizationBarrier", fnEnterSynchronizationBarrier);
 
   75  pfnDeleteSynchronizationBarrier = GetProcAddressAs(g_Kernel32, 
"DeleteSynchronizationBarrier",
 
   76                                                     fnDeleteSynchronizationBarrier);
 
   78  if (pfnInitializeSynchronizationBarrier && pfnEnterSynchronizationBarrier &&
 
   79      pfnDeleteSynchronizationBarrier)
 
   81    g_NativeBarrier = TRUE;
 
   90                                                   LONG lTotalThreads, LONG lSpinCount)
 
   93  HANDLE hEvent0 = NULL;
 
   94  HANDLE hEvent1 = NULL;
 
   97  InitOnceExecuteOnce(&g_InitOnce, InitOnce_Barrier, NULL, NULL);
 
  100    return pfnInitializeSynchronizationBarrier(lpBarrier, lTotalThreads, lSpinCount);
 
  103  if (!lpBarrier || lTotalThreads < 1 || lSpinCount < -1)
 
  105    SetLastError(ERROR_INVALID_PARAMETER);
 
  111  if (lSpinCount == -1)
 
  114  if (!(hEvent0 = CreateEvent(NULL, TRUE, FALSE, NULL)))
 
  117  if (!(hEvent1 = CreateEvent(NULL, TRUE, FALSE, NULL)))
 
  119    (void)CloseHandle(hEvent0);
 
  123  GetNativeSystemInfo(&sysinfo);
 
  125  WINPR_ASSERT(lTotalThreads >= 0);
 
  126  lpBarrier->Reserved1 = (DWORD)lTotalThreads;
 
  127  lpBarrier->Reserved2 = (DWORD)lTotalThreads;
 
  128  lpBarrier->Reserved3[0] = (ULONG_PTR)hEvent0;
 
  129  lpBarrier->Reserved3[1] = (ULONG_PTR)hEvent1;
 
  130  lpBarrier->Reserved4 = sysinfo.dwNumberOfProcessors;
 
  131  WINPR_ASSERT(lSpinCount >= 0);
 
  132  lpBarrier->Reserved5 = (DWORD)lSpinCount;
 
  139  LONG remainingThreads = 0;
 
  140  HANDLE hCurrentEvent = NULL;
 
  141  HANDLE hDormantEvent = NULL;
 
  145    return pfnEnterSynchronizationBarrier(lpBarrier, dwFlags);
 
  172  hCurrentEvent = (HANDLE)lpBarrier->Reserved3[0];
 
  173  hDormantEvent = (HANDLE)lpBarrier->Reserved3[1];
 
  175  remainingThreads = InterlockedDecrement((LONG*)&lpBarrier->Reserved1);
 
  177  WINPR_ASSERT(remainingThreads >= 0);
 
  179  if (remainingThreads > 0)
 
  181    DWORD dwProcessors = lpBarrier->Reserved4;
 
  182    BOOL spinOnly = (dwFlags & SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY) ? TRUE : FALSE;
 
  183    BOOL blockOnly = (dwFlags & SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY) ? TRUE : FALSE;
 
  195    if (spinOnly || (((ULONG)remainingThreads < dwProcessors) && !blockOnly))
 
  197      DWORD dwSpinCount = lpBarrier->Reserved5;
 
  203      volatile ULONG_PTR* cmp = &lpBarrier->Reserved3[0];
 
  205      while ((block = (*cmp == (ULONG_PTR)hCurrentEvent)))
 
  206        if (!spinOnly && ++sp > dwSpinCount)
 
  211      (void)WaitForSingleObject(hCurrentEvent, INFINITE);
 
  217  (void)ResetEvent(hDormantEvent);
 
  220  lpBarrier->Reserved1 = lpBarrier->Reserved2;
 
  223  lpBarrier->Reserved3[1] = (ULONG_PTR)hCurrentEvent;
 
  224  lpBarrier->Reserved3[0] = (ULONG_PTR)hDormantEvent;
 
  227  (void)SetEvent(hCurrentEvent);
 
  236    return pfnDeleteSynchronizationBarrier(lpBarrier);
 
  248  while (lpBarrier->Reserved1 != lpBarrier->Reserved2)
 
  251  if (lpBarrier->Reserved3[0])
 
  252    (void)CloseHandle((HANDLE)lpBarrier->Reserved3[0]);
 
  254  if (lpBarrier->Reserved3[1])
 
  255    (void)CloseHandle((HANDLE)lpBarrier->Reserved3[1]);