21#include <winpr/config.h>
23#include <winpr/assert.h>
24#include <winpr/tchar.h>
25#include <winpr/synch.h>
26#include <winpr/sysinfo.h>
27#include <winpr/interlocked.h>
28#include <winpr/thread.h>
32#ifdef WINPR_HAVE_UNISTD_H
39#include <mach/semaphore.h>
45#define TAG WINPR_TAG("synch.critical")
49 InitializeCriticalSectionEx(lpCriticalSection, 0, 0);
52BOOL InitializeCriticalSectionEx(
LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount,
55 WINPR_ASSERT(lpCriticalSection);
68 WLog_WARN(TAG,
"Flags unimplemented");
71 lpCriticalSection->DebugInfo = NULL;
72 lpCriticalSection->LockCount = -1;
73 lpCriticalSection->SpinCount = 0;
74 lpCriticalSection->RecursionCount = 0;
75 lpCriticalSection->OwningThread = NULL;
76 lpCriticalSection->LockSemaphore = (winpr_sem_t*)malloc(
sizeof(winpr_sem_t));
78 if (!lpCriticalSection->LockSemaphore)
83 if (semaphore_create(mach_task_self(), lpCriticalSection->LockSemaphore, SYNC_POLICY_FIFO, 0) !=
89 if (sem_init(lpCriticalSection->LockSemaphore, 0, 0) != 0)
93 SetCriticalSectionSpinCount(lpCriticalSection, dwSpinCount);
96 free(lpCriticalSection->LockSemaphore);
100BOOL InitializeCriticalSectionAndSpinCount(
LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount)
102 return InitializeCriticalSectionEx(lpCriticalSection, dwSpinCount, 0);
105DWORD SetCriticalSectionSpinCount(WINPR_ATTR_UNUSED
LPCRITICAL_SECTION lpCriticalSection,
106 WINPR_ATTR_UNUSED DWORD dwSpinCount)
108 WINPR_ASSERT(lpCriticalSection);
109#if !defined(WINPR_CRITICAL_SECTION_DISABLE_SPINCOUNT)
111 DWORD dwPreviousSpinCount = lpCriticalSection->SpinCount;
116 GetNativeSystemInfo(&sysinfo);
118 if (sysinfo.dwNumberOfProcessors < 2)
122 lpCriticalSection->SpinCount = dwSpinCount;
123 return dwPreviousSpinCount;
132 WINPR_ASSERT(lpCriticalSection);
133#if defined(__APPLE__)
134 semaphore_wait(*((winpr_sem_t*)lpCriticalSection->LockSemaphore));
136 sem_wait((winpr_sem_t*)lpCriticalSection->LockSemaphore);
142 WINPR_ASSERT(lpCriticalSection);
144 semaphore_signal(*((winpr_sem_t*)lpCriticalSection->LockSemaphore));
146 sem_post((winpr_sem_t*)lpCriticalSection->LockSemaphore);
152 WINPR_ASSERT(lpCriticalSection);
153#if !defined(WINPR_CRITICAL_SECTION_DISABLE_SPINCOUNT)
154 ULONG SpinCount = lpCriticalSection->SpinCount;
157 if (SpinCount && TryEnterCriticalSection(lpCriticalSection))
161 while (SpinCount-- && lpCriticalSection->LockCount < 1)
164 if (InterlockedCompareExchange(&lpCriticalSection->LockCount, 0, -1) == -1)
166 lpCriticalSection->RecursionCount = 1;
167 lpCriticalSection->OwningThread = (HANDLE)(ULONG_PTR)GetCurrentThreadId();
172 if (sched_yield() != 0)
186 if (InterlockedIncrement(&lpCriticalSection->LockCount))
189 if (lpCriticalSection->OwningThread == (HANDLE)(ULONG_PTR)GetCurrentThreadId())
192 lpCriticalSection->RecursionCount++;
197 WaitForCriticalSection(lpCriticalSection);
201 lpCriticalSection->RecursionCount = 1;
202 lpCriticalSection->OwningThread = (HANDLE)(ULONG_PTR)GetCurrentThreadId();
207 HANDLE current_thread = (HANDLE)(ULONG_PTR)GetCurrentThreadId();
209 WINPR_ASSERT(lpCriticalSection);
212 if (InterlockedCompareExchange(&lpCriticalSection->LockCount, 0, -1) == -1)
214 lpCriticalSection->RecursionCount = 1;
215 lpCriticalSection->OwningThread = current_thread;
220 if (lpCriticalSection->OwningThread == current_thread)
223 lpCriticalSection->RecursionCount++;
224 InterlockedIncrement(&lpCriticalSection->LockCount);
233 WINPR_ASSERT(lpCriticalSection);
236 if (--lpCriticalSection->RecursionCount < 1)
239 lpCriticalSection->OwningThread = NULL;
241 if (InterlockedDecrement(&lpCriticalSection->LockCount) >= 0)
244 UnWaitCriticalSection(lpCriticalSection);
249 (void)InterlockedDecrement(&lpCriticalSection->LockCount);
255 WINPR_ASSERT(lpCriticalSection);
257 lpCriticalSection->LockCount = -1;
258 lpCriticalSection->SpinCount = 0;
259 lpCriticalSection->RecursionCount = 0;
260 lpCriticalSection->OwningThread = NULL;
262 if (lpCriticalSection->LockSemaphore != NULL)
265 semaphore_destroy(mach_task_self(), *((winpr_sem_t*)lpCriticalSection->LockSemaphore));
267 sem_destroy((winpr_sem_t*)lpCriticalSection->LockSemaphore);
269 free(lpCriticalSection->LockSemaphore);
270 lpCriticalSection->LockSemaphore = NULL;