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
36 #if defined(__APPLE__)
37 #include <mach/task.h>
38 #include <mach/mach.h>
39 #include <mach/semaphore.h>
45 #define TAG WINPR_TAG("synch.critical")
49 InitializeCriticalSectionEx(lpCriticalSection, 0, 0);
52 BOOL 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)
81 #if defined(__APPLE__)
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);
100 BOOL InitializeCriticalSectionAndSpinCount(
LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount)
102 return InitializeCriticalSectionEx(lpCriticalSection, dwSpinCount, 0);
105 DWORD SetCriticalSectionSpinCount(
LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount)
107 WINPR_ASSERT(lpCriticalSection);
108 #if !defined(WINPR_CRITICAL_SECTION_DISABLE_SPINCOUNT)
110 DWORD dwPreviousSpinCount = lpCriticalSection->SpinCount;
115 GetNativeSystemInfo(&sysinfo);
117 if (sysinfo.dwNumberOfProcessors < 2)
121 lpCriticalSection->SpinCount = dwSpinCount;
122 return dwPreviousSpinCount;
130 WINPR_ASSERT(lpCriticalSection);
131 #if defined(__APPLE__)
132 semaphore_wait(*((winpr_sem_t*)lpCriticalSection->LockSemaphore));
134 sem_wait((winpr_sem_t*)lpCriticalSection->LockSemaphore);
140 WINPR_ASSERT(lpCriticalSection);
141 #if defined __APPLE__
142 semaphore_signal(*((winpr_sem_t*)lpCriticalSection->LockSemaphore));
144 sem_post((winpr_sem_t*)lpCriticalSection->LockSemaphore);
150 WINPR_ASSERT(lpCriticalSection);
151 #if !defined(WINPR_CRITICAL_SECTION_DISABLE_SPINCOUNT)
152 ULONG SpinCount = lpCriticalSection->SpinCount;
155 if (SpinCount && TryEnterCriticalSection(lpCriticalSection))
159 while (SpinCount-- && lpCriticalSection->LockCount < 1)
162 if (InterlockedCompareExchange(&lpCriticalSection->LockCount, 0, -1) == -1)
164 lpCriticalSection->RecursionCount = 1;
165 lpCriticalSection->OwningThread = (HANDLE)(ULONG_PTR)GetCurrentThreadId();
170 if (sched_yield() != 0)
184 if (InterlockedIncrement(&lpCriticalSection->LockCount))
187 if (lpCriticalSection->OwningThread == (HANDLE)(ULONG_PTR)GetCurrentThreadId())
190 lpCriticalSection->RecursionCount++;
195 WaitForCriticalSection(lpCriticalSection);
199 lpCriticalSection->RecursionCount = 1;
200 lpCriticalSection->OwningThread = (HANDLE)(ULONG_PTR)GetCurrentThreadId();
205 HANDLE current_thread = (HANDLE)(ULONG_PTR)GetCurrentThreadId();
207 WINPR_ASSERT(lpCriticalSection);
210 if (InterlockedCompareExchange(&lpCriticalSection->LockCount, 0, -1) == -1)
212 lpCriticalSection->RecursionCount = 1;
213 lpCriticalSection->OwningThread = current_thread;
218 if (lpCriticalSection->OwningThread == current_thread)
221 lpCriticalSection->RecursionCount++;
222 InterlockedIncrement(&lpCriticalSection->LockCount);
231 WINPR_ASSERT(lpCriticalSection);
234 if (--lpCriticalSection->RecursionCount < 1)
237 lpCriticalSection->OwningThread = NULL;
239 if (InterlockedDecrement(&lpCriticalSection->LockCount) >= 0)
242 UnWaitCriticalSection(lpCriticalSection);
247 (void)InterlockedDecrement(&lpCriticalSection->LockCount);
253 WINPR_ASSERT(lpCriticalSection);
255 lpCriticalSection->LockCount = -1;
256 lpCriticalSection->SpinCount = 0;
257 lpCriticalSection->RecursionCount = 0;
258 lpCriticalSection->OwningThread = NULL;
260 if (lpCriticalSection->LockSemaphore != NULL)
262 #if defined __APPLE__
263 semaphore_destroy(mach_task_self(), *((winpr_sem_t*)lpCriticalSection->LockSemaphore));
265 sem_destroy((winpr_sem_t*)lpCriticalSection->LockSemaphore);
267 free(lpCriticalSection->LockSemaphore);
268 lpCriticalSection->LockSemaphore = NULL;