]>
Commit | Line | Data |
---|---|---|
442fbc9d A |
1 | #include <libkern/OSAtomic.h> |
2 | #include <System/i386/cpu_capabilities.h> | |
3 | ||
4 | #define OS_UNFAIR_LOCK_INLINE 1 | |
5 | #include "os/lock_private.h" | |
6 | ||
7 | typedef volatile struct { | |
8 | void *first; | |
9 | void *last; | |
10 | os_unfair_lock lock; | |
11 | } __attribute__ ((aligned (16))) UnfairFifoQueueHead; | |
12 | ||
13 | #define set_next(element, offset, new) \ | |
14 | *((void**)(((uintptr_t)element) + offset)) = new; | |
15 | #define get_next(element, offset) \ | |
16 | *((void**)(((uintptr_t)element) + offset)); | |
17 | ||
18 | // This is a naive implementation using unfair locks to support translated | |
19 | // x86_64 apps only. Native x86_64 and arm64 apps will use the | |
20 | // PFZ implementations | |
21 | void OSAtomicFifoEnqueue$VARIANT$UnfairLock(UnfairFifoQueueHead *list, void *new, size_t offset) { | |
22 | set_next(new, offset, NULL); | |
23 | ||
24 | os_unfair_lock_lock_inline(&list->lock); | |
25 | if (list->last == NULL) { | |
26 | list->first = new; | |
27 | } else { | |
28 | set_next(list->last, offset, new); | |
29 | } | |
30 | list->last = new; | |
31 | os_unfair_lock_unlock_inline(&list->lock); | |
32 | } | |
33 | ||
34 | void* OSAtomicFifoDequeue$VARIANT$UnfairLock(UnfairFifoQueueHead *list, size_t offset) { | |
35 | os_unfair_lock_lock_inline(&list->lock); | |
36 | void *element = list->first; | |
37 | if (element != NULL) { | |
38 | void *next = get_next(element, offset); | |
39 | if (next == NULL) { | |
40 | list->last = NULL; | |
41 | } | |
42 | list->first = next; | |
43 | } | |
44 | os_unfair_lock_unlock_inline(&list->lock); | |
45 | ||
46 | return element; | |
47 | } | |
48 | ||
49 | #define MakeResolver(name) \ | |
50 | void * name ## Resolver(void) __asm__("_" #name); \ | |
51 | void * name ## Resolver(void) { \ | |
52 | __asm__(".symbol_resolver _" #name); \ | |
53 | uint64_t capabilities = *(uint64_t*)_COMM_PAGE_CPU_CAPABILITIES64; \ | |
54 | if (capabilities & kIsTranslated) { \ | |
55 | return name ## $VARIANT$UnfairLock; \ | |
56 | } else { \ | |
57 | return name ## $VARIANT$PFZ; \ | |
58 | } \ | |
59 | } | |
60 | ||
61 | void OSAtomicFifoEnqueue$VARIANT$PFZ(OSFifoQueueHead *, void *, size_t); | |
62 | void* OSAtomicFifoDequeue$VARIANT$PFZ(OSFifoQueueHead *, size_t); | |
63 | ||
64 | MakeResolver(OSAtomicFifoEnqueue) | |
65 | MakeResolver(OSAtomicFifoDequeue) |