20 #include <winpr/config.h>
22 #include <winpr/platform.h>
23 #include <winpr/synch.h>
24 #include <winpr/handle.h>
26 #include <winpr/interlocked.h>
38 ListHead->s.Alignment = 0;
39 ListHead->s.Region = 0;
40 ListHead->Header8.Init = 1;
42 ListHead->Alignment = 0;
47 WINPR_PSLIST_ENTRY ListEntry)
53 newHeader.HeaderX64.NextEntry = (((ULONG_PTR)ListEntry) >> 4);
59 ListEntry->Next = (PSLIST_ENTRY)(((ULONG_PTR)old.HeaderX64.NextEntry) << 4);
61 newHeader.HeaderX64.Depth = old.HeaderX64.Depth + 1;
62 newHeader.HeaderX64.Sequence = old.HeaderX64.Sequence + 1;
64 if (InterlockedCompareExchange64((LONGLONG*)ListHead, newHeader.s.Alignment,
67 InterlockedCompareExchange64(&((LONGLONG*)ListHead)[1], newHeader.s.Region,
73 return (PSLIST_ENTRY)((ULONG_PTR)old.HeaderX64.NextEntry << 4);
75 newHeader.s.Next.Next = ListEntry;
80 ListEntry->Next = old.s.Next.Next;
81 newHeader.s.Depth = old.s.Depth + 1;
82 newHeader.s.Sequence = old.s.Sequence + 1;
83 if (old.Alignment > INT64_MAX)
85 if (newHeader.Alignment > INT64_MAX)
87 if (ListHead->Alignment > INT64_MAX)
89 }
while (InterlockedCompareExchange64((LONGLONG*)&ListHead->Alignment,
90 (LONGLONG)newHeader.Alignment,
91 (LONGLONG)old.Alignment) != (LONGLONG)old.Alignment);
93 return old.s.Next.Next;
97 WINPR_PSLIST_ENTRY InterlockedPushListSListEx(
WINPR_PSLIST_HEADER ListHead, WINPR_PSLIST_ENTRY List,
98 WINPR_PSLIST_ENTRY ListEnd, ULONG Count)
112 WINPR_PSLIST_ENTRY entry = NULL;
119 entry = (PSLIST_ENTRY)(((ULONG_PTR)old.HeaderX64.NextEntry) << 4);
124 newHeader.HeaderX64.NextEntry = ((ULONG_PTR)entry->Next) >> 4;
125 newHeader.HeaderX64.Depth = old.HeaderX64.Depth - 1;
126 newHeader.HeaderX64.Sequence = old.HeaderX64.Sequence - 1;
128 if (InterlockedCompareExchange64((LONGLONG*)ListHead, newHeader.s.Alignment,
131 InterlockedCompareExchange64(&((LONGLONG*)ListHead)[1], newHeader.s.Region,
141 entry = old.s.Next.Next;
146 newHeader.s.Next.Next = entry->Next;
147 newHeader.s.Depth = old.s.Depth - 1;
148 newHeader.s.Sequence = old.s.Sequence + 1;
150 if (old.Alignment > INT64_MAX)
152 if (newHeader.Alignment > INT64_MAX)
154 if (ListHead->Alignment > INT64_MAX)
156 }
while (InterlockedCompareExchange64((LONGLONG*)&ListHead->Alignment,
157 (LONGLONG)newHeader.Alignment,
158 (LONGLONG)old.Alignment) != (LONGLONG)old.Alignment);
168 if (!QueryDepthSList(ListHead))
172 newHeader.s.Alignment = 0;
173 newHeader.s.Region = 0;
174 newHeader.HeaderX64.HeaderType = 1;
179 newHeader.HeaderX64.Sequence = old.HeaderX64.Sequence + 1;
181 if (InterlockedCompareExchange64((LONGLONG*)ListHead, newHeader.s.Alignment,
184 InterlockedCompareExchange64(&((LONGLONG*)ListHead)[1], newHeader.s.Region,
190 return (PSLIST_ENTRY)(((ULONG_PTR)old.HeaderX64.NextEntry) << 4);
192 newHeader.Alignment = 0;
197 newHeader.s.Sequence = old.s.Sequence + 1;
199 if (old.Alignment > INT64_MAX)
201 if (newHeader.Alignment > INT64_MAX)
203 if (ListHead->Alignment > INT64_MAX)
205 }
while (InterlockedCompareExchange64((LONGLONG*)&ListHead->Alignment,
206 (LONGLONG)newHeader.Alignment,
207 (LONGLONG)old.Alignment) != (LONGLONG)old.Alignment);
209 return old.s.Next.Next;
216 return ListHead->HeaderX64.Depth;
218 return ListHead->s.Depth;
222 LONG InterlockedIncrement(LONG
volatile* Addend)
224 #if defined(__GNUC__) || defined(__clang__)
225 WINPR_PRAGMA_DIAG_PUSH
226 WINPR_PRAGMA_DIAG_IGNORED_ATOMIC_SEQ_CST
227 return __sync_add_and_fetch(Addend, 1);
228 WINPR_PRAGMA_DIAG_POP
234 LONG InterlockedDecrement(LONG
volatile* Addend)
236 #if defined(__GNUC__) || defined(__clang__)
237 WINPR_PRAGMA_DIAG_PUSH
238 WINPR_PRAGMA_DIAG_IGNORED_ATOMIC_SEQ_CST
239 return __sync_sub_and_fetch(Addend, 1);
240 WINPR_PRAGMA_DIAG_POP
246 LONG InterlockedExchange(LONG
volatile* Target, LONG Value)
248 #if defined(__GNUC__) || defined(__clang__)
249 WINPR_PRAGMA_DIAG_PUSH
250 WINPR_PRAGMA_DIAG_IGNORED_ATOMIC_SEQ_CST
251 return __sync_val_compare_and_swap(Target, *Target, Value);
252 WINPR_PRAGMA_DIAG_POP
258 LONG InterlockedExchangeAdd(LONG
volatile* Addend, LONG Value)
260 #if defined(__GNUC__) || defined(__clang__)
261 WINPR_PRAGMA_DIAG_PUSH
262 WINPR_PRAGMA_DIAG_IGNORED_ATOMIC_SEQ_CST
263 return __sync_fetch_and_add(Addend, Value);
264 WINPR_PRAGMA_DIAG_POP
270 LONG InterlockedCompareExchange(LONG
volatile* Destination, LONG Exchange, LONG Comperand)
272 #if defined(__GNUC__) || defined(__clang__)
273 WINPR_PRAGMA_DIAG_PUSH
274 WINPR_PRAGMA_DIAG_IGNORED_ATOMIC_SEQ_CST
275 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
276 WINPR_PRAGMA_DIAG_POP
282 PVOID InterlockedCompareExchangePointer(PVOID
volatile* Destination, PVOID Exchange,
285 #if defined(__GNUC__) || defined(__clang__)
286 WINPR_PRAGMA_DIAG_PUSH
287 WINPR_PRAGMA_DIAG_IGNORED_ATOMIC_SEQ_CST
288 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
289 WINPR_PRAGMA_DIAG_POP
297 #if defined(_WIN32) && !defined(WINPR_INTERLOCKED_COMPARE_EXCHANGE64)
301 #elif defined(_WIN32) && defined(WINPR_INTERLOCKED_COMPARE_EXCHANGE64)
303 static volatile HANDLE mutex = NULL;
305 BOOL static_mutex_lock(
volatile HANDLE* static_mutex)
307 if (*static_mutex == NULL)
311 if (!(handle = CreateMutex(NULL, FALSE, NULL)))
314 if (InterlockedCompareExchangePointer((PVOID*)static_mutex, (PVOID)handle, NULL) != NULL)
315 (void)CloseHandle(handle);
318 return (WaitForSingleObject(*static_mutex, INFINITE) == WAIT_OBJECT_0);
321 LONGLONG InterlockedCompareExchange64(LONGLONG
volatile* Destination, LONGLONG Exchange,
324 LONGLONG previousValue = 0;
325 BOOL locked = static_mutex_lock(&mutex);
327 previousValue = *Destination;
329 if (*Destination == Comperand)
330 *Destination = Exchange;
333 (void)ReleaseMutex(mutex);
335 (
void)fprintf(stderr,
336 "WARNING: InterlockedCompareExchange64 operation might have failed\n");
338 return previousValue;
341 #elif (defined(ANDROID) && ANDROID) || \
342 (defined(__GNUC__) && !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8))
346 static pthread_mutex_t mutex;
348 LONGLONG InterlockedCompareExchange64(LONGLONG
volatile* Destination, LONGLONG Exchange,
351 LONGLONG previousValue = 0;
353 pthread_mutex_lock(&mutex);
355 previousValue = *Destination;
357 if (*Destination == Comperand)
358 *Destination = Exchange;
360 pthread_mutex_unlock(&mutex);
362 return previousValue;
367 LONGLONG InterlockedCompareExchange64(LONGLONG
volatile* Destination, LONGLONG Exchange,
370 #if defined(__GNUC__) || defined(__clang__)
371 WINPR_PRAGMA_DIAG_PUSH
372 WINPR_PRAGMA_DIAG_IGNORED_ATOMIC_SEQ_CST
373 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
374 WINPR_PRAGMA_DIAG_POP
392 VOID InitializeListHead(WINPR_PLIST_ENTRY ListHead)
394 ListHead->Flink = ListHead->Blink = ListHead;
397 BOOL IsListEmpty(
const WINPR_LIST_ENTRY* ListHead)
399 return (BOOL)(ListHead->Flink == ListHead);
402 BOOL RemoveEntryList(WINPR_PLIST_ENTRY Entry)
404 WINPR_PLIST_ENTRY OldFlink = NULL;
405 WINPR_PLIST_ENTRY OldBlink = NULL;
407 OldFlink = Entry->Flink;
408 OldBlink = Entry->Blink;
409 OldFlink->Blink = OldBlink;
410 OldBlink->Flink = OldFlink;
412 return (BOOL)(OldFlink == OldBlink);
415 VOID InsertHeadList(WINPR_PLIST_ENTRY ListHead, WINPR_PLIST_ENTRY Entry)
417 WINPR_PLIST_ENTRY OldFlink = NULL;
419 OldFlink = ListHead->Flink;
420 Entry->Flink = OldFlink;
421 Entry->Blink = ListHead;
422 OldFlink->Blink = Entry;
423 ListHead->Flink = Entry;
426 WINPR_PLIST_ENTRY RemoveHeadList(WINPR_PLIST_ENTRY ListHead)
428 WINPR_PLIST_ENTRY Flink = NULL;
429 WINPR_PLIST_ENTRY Entry = NULL;
431 Entry = ListHead->Flink;
432 Flink = Entry->Flink;
433 ListHead->Flink = Flink;
434 Flink->Blink = ListHead;
439 VOID InsertTailList(WINPR_PLIST_ENTRY ListHead, WINPR_PLIST_ENTRY Entry)
441 WINPR_PLIST_ENTRY OldBlink = NULL;
443 OldBlink = ListHead->Blink;
444 Entry->Flink = ListHead;
445 Entry->Blink = OldBlink;
446 OldBlink->Flink = Entry;
447 ListHead->Blink = Entry;
450 WINPR_PLIST_ENTRY RemoveTailList(WINPR_PLIST_ENTRY ListHead)
452 WINPR_PLIST_ENTRY Blink = NULL;
453 WINPR_PLIST_ENTRY Entry = NULL;
455 Entry = ListHead->Blink;
456 Blink = Entry->Blink;
457 ListHead->Blink = Blink;
458 Blink->Flink = ListHead;
463 VOID AppendTailList(WINPR_PLIST_ENTRY ListHead, WINPR_PLIST_ENTRY ListToAppend)
465 WINPR_PLIST_ENTRY ListEnd = ListHead->Blink;
467 ListHead->Blink->Flink = ListToAppend;
468 ListHead->Blink = ListToAppend->Blink;
469 ListToAppend->Blink->Flink = ListHead;
470 ListToAppend->Blink = ListEnd;
473 VOID PushEntryList(WINPR_PSINGLE_LIST_ENTRY ListHead, WINPR_PSINGLE_LIST_ENTRY Entry)
475 Entry->Next = ListHead->Next;
476 ListHead->Next = Entry;
479 WINPR_PSINGLE_LIST_ENTRY PopEntryList(WINPR_PSINGLE_LIST_ENTRY ListHead)
481 WINPR_PSINGLE_LIST_ENTRY FirstEntry = NULL;
483 FirstEntry = ListHead->Next;
485 if (FirstEntry != NULL)
486 ListHead->Next = FirstEntry->Next;