]>
Commit | Line | Data |
---|---|---|
59e0d9fe A |
1 | .Dd May 26, 2004 |
2 | .Dt ATOMIC 3 | |
3 | .Os Darwin | |
4 | .Sh NAME | |
5 | .Nm OSAtomicAdd32 , | |
3d9156a7 | 6 | .Nm OSAtomicAdd32Barrier , |
59e0d9fe | 7 | .Nm OSAtomicIncrement32 , |
3d9156a7 | 8 | .Nm OSAtomicIncrement32Barrier , |
59e0d9fe | 9 | .Nm OSAtomicDecrement32 , |
3d9156a7 | 10 | .Nm OSAtomicDecrement32Barrier , |
59e0d9fe | 11 | .Nm OSAtomicOr32 , |
3d9156a7 | 12 | .Nm OSAtomicOr32Barrier , |
224c7076 A |
13 | .Nm OSAtomicOr32Orig , |
14 | .Nm OSAtomicOr32OrigBarrier , | |
59e0d9fe | 15 | .Nm OSAtomicAnd32 , |
3d9156a7 | 16 | .Nm OSAtomicAnd32Barrier , |
224c7076 A |
17 | .Nm OSAtomicAnd32Orig , |
18 | .Nm OSAtomicAnd32OrigBarrier , | |
59e0d9fe | 19 | .Nm OSAtomicXor32 , |
3d9156a7 | 20 | .Nm OSAtomicXor32Barrier , |
224c7076 A |
21 | .Nm OSAtomicXor32Orig , |
22 | .Nm OSAtomicXor32OrigBarrier , | |
59e0d9fe | 23 | .Nm OSAtomicAdd64 , |
3d9156a7 | 24 | .Nm OSAtomicAdd64Barrier , |
59e0d9fe | 25 | .Nm OSAtomicIncrement64 , |
3d9156a7 | 26 | .Nm OSAtomicIncrement64Barrier , |
59e0d9fe | 27 | .Nm OSAtomicDecrement64 , |
3d9156a7 | 28 | .Nm OSAtomicDecrement64Barrier , |
224c7076 A |
29 | .Nm OSAtomicCompareAndSwapInt , |
30 | .Nm OSAtomicCompareAndSwapIntBarrier , | |
31 | .Nm OSAtomicCompareAndSwapLong , | |
32 | .Nm OSAtomicCompareAndSwapLongBarrier , | |
33 | .Nm OSAtomicCompareAndSwapPtr , | |
34 | .Nm OSAtomicCompareAndSwapPtrBarrier , | |
59e0d9fe | 35 | .Nm OSAtomicCompareAndSwap32 , |
3d9156a7 | 36 | .Nm OSAtomicCompareAndSwap32Barrier , |
59e0d9fe | 37 | .Nm OSAtomicCompareAndSwap64 , |
3d9156a7 | 38 | .Nm OSAtomicCompareAndSwap64Barrier , |
59e0d9fe | 39 | .Nm OSAtomicTestAndSet , |
3d9156a7 A |
40 | .Nm OSAtomicTestAndSetBarrier , |
41 | .Nm OSAtomicTestAndClear , | |
224c7076 A |
42 | .Nm OSAtomicTestAndClearBarrier , |
43 | .Nm OSSpinLockTry , | |
44 | .Nm OSSpinLockLock , | |
45 | .Nm OSSpinLockUnlock , | |
46 | .Nm OSAtomicEnqueue , | |
47 | .Nm OSAtomicDequeue | |
48 | .Nd atomic add, increment, decrement, or, and, xor, compare and swap, test and set, test and clear, spinlocks, and lockless queues | |
59e0d9fe A |
49 | .Sh LIBRARY |
50 | .Lb libc | |
51 | .Sh SYNOPSIS | |
52 | .In libkern/OSAtomic.h | |
53 | .Ft int32_t | |
224c7076 | 54 | .Fn OSAtomicAdd32 "int32_t theAmount" "volatile int32_t *theValue" |
59e0d9fe | 55 | .Ft int32_t |
224c7076 | 56 | .Fn OSAtomicAdd32Barrier "int32_t theAmount" "volatile int32_t *theValue" |
3d9156a7 | 57 | .Ft int32_t |
224c7076 | 58 | .Fn OSAtomicIncrement32 "volatile int32_t *theValue" |
59e0d9fe | 59 | .Ft int32_t |
224c7076 | 60 | .Fn OSAtomicIncrement32Barrier "volatile int32_t *theValue" |
3d9156a7 | 61 | .Ft int32_t |
224c7076 | 62 | .Fn OSAtomicDecrement32 "volatile int32_t *theValue" |
59e0d9fe | 63 | .Ft int32_t |
224c7076 | 64 | .Fn OSAtomicDecrement32Barrier "volatile int32_t *theValue" |
3d9156a7 | 65 | .Ft int32_t |
224c7076 | 66 | .Fn OSAtomicOr32 "uint32_t theMask" "volatile uint32_t *theValue" |
59e0d9fe | 67 | .Ft int32_t |
224c7076 | 68 | .Fn OSAtomicOr32Barrier "uint32_t theMask" "volatile uint32_t *theValue" |
3d9156a7 | 69 | .Ft int32_t |
224c7076 | 70 | .Fn OSAtomicAnd32 "uint32_t theMask" "volatile uint32_t *theValue" |
59e0d9fe | 71 | .Ft int32_t |
224c7076 | 72 | .Fn OSAtomicAnd32Barrier "uint32_t theMask" "volatile uint32_t *theValue" |
3d9156a7 | 73 | .Ft int32_t |
224c7076 | 74 | .Fn OSAtomicXor32 "uint32_t theMask" "volatile uint32_t *theValue" |
3d9156a7 | 75 | .Ft int32_t |
224c7076 A |
76 | .Fn OSAtomicXor32Barrier "uint32_t theMask" "volatile uint32_t *theValue" |
77 | .Ft int32_t | |
78 | .Fn OSAtomicOr32Orig "uint32_t theMask" "volatile uint32_t *theValue" | |
79 | .Ft int32_t | |
80 | .Fn OSAtomicOr32OrigBarrier "uint32_t theMask" "volatile uint32_t *theValue" | |
81 | .Ft int32_t | |
82 | .Fn OSAtomicAnd32Orig "uint32_t theMask" "volatile uint32_t *theValue" | |
83 | .Ft int32_t | |
84 | .Fn OSAtomicAnd32OrigBarrier "uint32_t theMask" "volatile uint32_t *theValue" | |
85 | .Ft int32_t | |
86 | .Fn OSAtomicXor32Orig "uint32_t theMask" "volatile uint32_t *theValue" | |
87 | .Ft int32_t | |
88 | .Fn OSAtomicXor32OrigBarrier "uint32_t theMask" "volatile uint32_t *theValue" | |
59e0d9fe | 89 | .Ft int64_t |
224c7076 | 90 | .Fn OSAtomicAdd64 "int64_t theAmount" "volatile int64_t *theValue" |
59e0d9fe | 91 | .Ft int64_t |
224c7076 | 92 | .Fn OSAtomicAdd64Barrier "int64_t theAmount" "volatile int64_t *theValue" |
3d9156a7 | 93 | .Ft int64_t |
224c7076 | 94 | .Fn OSAtomicIncrement64 "volatile int64_t *theValue" |
59e0d9fe | 95 | .Ft int64_t |
224c7076 | 96 | .Fn OSAtomicIncrement64Barrier "volatile int64_t *theValue" |
3d9156a7 | 97 | .Ft int64_t |
224c7076 | 98 | .Fn OSAtomicDecrement64 "volatile int64_t *theValue" |
3d9156a7 | 99 | .Ft int64_t |
224c7076 A |
100 | .Fn OSAtomicDecrement64Barrier "volatile int64_t *theValue" |
101 | .Ft bool | |
102 | .Fn OSAtomicCompareAndSwapInt "int oldValue" "int newValue" "volatile int *theValue" | |
103 | .Ft bool | |
104 | .Fn OSAtomicCompareAndSwapIntBarrier "int oldValue" "int newValue" "volatile int *theValue" | |
105 | .Ft bool | |
106 | .Fn OSAtomicCompareAndSwapLong "long oldValue" "long newValue" "volatile long *theValue" | |
59e0d9fe | 107 | .Ft bool |
224c7076 | 108 | .Fn OSAtomicCompareAndSwapLongBarrier "long oldValue" "long newValue" "volatile long *theValue" |
59e0d9fe | 109 | .Ft bool |
224c7076 | 110 | .Fn OSAtomicCompareAndSwapPtr "void* oldValue" "void* newValue" "void* volatile *theValue" |
3d9156a7 | 111 | .Ft bool |
224c7076 | 112 | .Fn OSAtomicCompareAndSwapPtrBarrier "void* oldValue" "void* newValue" "void* volatile *theValue" |
59e0d9fe | 113 | .Ft bool |
224c7076 | 114 | .Fn OSAtomicCompareAndSwap32 "int32_t oldValue" "int32_t newValue" "volatile int32_t *theValue" |
3d9156a7 | 115 | .Ft bool |
224c7076 | 116 | .Fn OSAtomicCompareAndSwap32Barrier "int32_t oldValue" "int32_t newValue" "volatile int32_t *theValue" |
59e0d9fe | 117 | .Ft bool |
224c7076 | 118 | .Fn OSAtomicCompareAndSwap64 "int64_t oldValue" "int64_t newValue" "volatile int64_t *theValue" |
3d9156a7 | 119 | .Ft bool |
224c7076 | 120 | .Fn OSAtomicCompareAndSwap64Barrier "int64_t oldValue" "int64_t newValue" "volatile int64_t *theValue" |
3d9156a7 | 121 | .Ft bool |
224c7076 A |
122 | .Fn OSAtomicTestAndSet "uint32_t n" "volatile void *theAddress" |
123 | .Ft bool | |
124 | .Fn OSAtomicTestAndSetBarrier "uint32_t n" "volatile void *theAddress" | |
125 | .Ft bool | |
126 | .Fn OSAtomicTestAndClear "uint32_t n" "volatile void *theAddress" | |
127 | .Ft bool | |
128 | .Fn OSAtomicTestAndClearBarrier "uint32_t n" "volatile void *theAddress" | |
129 | .Ft bool | |
130 | .Fn OSSpinLockTry "OSSpinLock *lock" | |
131 | .Ft void | |
132 | .Fn OSSpinLockLock "OSSpinLock *lock" | |
133 | .Ft void | |
134 | .Fn OSSpinLockUnlock "OSSpinLock *lock" | |
135 | .Ft void | |
136 | .Fn OSAtomicEnqueue "OSQueueHead *list" "void *new" "size_t offset" | |
137 | .Ft void* | |
138 | .Fn OSAtomicDequeue "OSQueueHead *list" "size_t offset" | |
59e0d9fe | 139 | .Sh DESCRIPTION |
3d9156a7 | 140 | These functions are thread and multiprocessor safe. For each function, there |
224c7076 | 141 | is a version that does and another that does not incorporate a memory barrier. |
3d9156a7 A |
142 | Barriers strictly order memory access on a weakly-ordered |
143 | architecture such as PPC. All loads and stores executed in sequential program | |
144 | order before the barrier will complete before any load or store executed after | |
145 | the barrier. On a uniprocessor, the barrier operation is typically a nop. | |
146 | On a multiprocessor, the barrier can be quite expensive. | |
147 | .Pp | |
148 | Most code will want to use the barrier functions to insure that memory shared | |
149 | between threads is properly synchronized. For example, if you want to initialize | |
150 | a shared data structure and then atomically increment a variable to indicate | |
224c7076 | 151 | that the initialization is complete, then you must use OSAtomicIncrement32Barrier() |
3d9156a7 | 152 | to ensure that the stores to your data structure complete before the atomic add. |
224c7076 | 153 | Likewise, the consumer of that data structure must use OSAtomicDecrement32Barrier(), |
3d9156a7 A |
154 | in order to ensure that their loads of the structure are not executed before |
155 | the atomic decrement. On the other hand, | |
156 | if you are simply incrementing a global counter, then it is safe and potentially much | |
157 | faster to use OSAtomicIncrement32(). If you are unsure which version to use, prefer | |
158 | the barrier variants as they are safer. | |
159 | .Pp | |
160 | The logical (and, or, xor) and bit test operations are layered on top of the | |
59e0d9fe | 161 | .Fn OSAtomicCompareAndSwap |
224c7076 A |
162 | primitives. There are four versions of each logical operation, depending on whether |
163 | or not there is a barrier, and whether the return value is the result of the | |
164 | operation (eg, | |
165 | .Fn OSAtomicOr32 | |
166 | ) or the original value before the operation (eg, | |
167 | .Fn OSAtomicOr32Orig | |
168 | ). | |
3d9156a7 A |
169 | .Pp |
170 | The memory address | |
59e0d9fe A |
171 | .Fa theValue |
172 | must be naturally aligned, ie 32-bit aligned for 32-bit operations and 64-bit | |
3d9156a7 A |
173 | aligned for 64-bit operations. |
174 | .Pp | |
224c7076 | 175 | The 64-bit operations are not implemented for 32-bit processes on PPC platforms. |
59e0d9fe | 176 | .Pp |
224c7076 A |
177 | The |
178 | .Fn OSAtomicCompareAndSwap | |
179 | operations compare | |
59e0d9fe A |
180 | .Fa oldValue |
181 | to | |
182 | .Fa *theValue , | |
183 | and set | |
184 | .Fa *theValue | |
185 | to | |
186 | .Fa newValue | |
187 | if the comparison is equal. The comparison and assignment | |
188 | occur as one atomic operation. | |
189 | .Pp | |
190 | .Fn OSAtomicTestAndSet | |
191 | and | |
192 | .Fn OSAtomicTestAndClear | |
193 | operate on bit (0x80 >> ( | |
194 | .Fa n | |
195 | & 7)) of byte ((char*) | |
196 | .Fa theAddress | |
197 | + ( | |
198 | .Fa n | |
199 | >> 3)). They set the named bit to either 1 or 0, respectively. | |
200 | .Fa theAddress | |
201 | need not be aligned. | |
224c7076 A |
202 | .Pp |
203 | The routines | |
204 | .Fn OSAtomicEnqueue | |
205 | and | |
206 | .Fn OSAtomicDequeue | |
207 | operate on singly linked LIFO queues. Ie, a dequeue operation will return the | |
208 | most recently enqueued element, or NULL if the list is empty. The operations | |
209 | are lockless, and barriers are used as necessary to permit thread-safe access to | |
210 | the queue element. | |
211 | .Fa offset | |
212 | is the offset in bytes to the link field in the queue element. For example: | |
213 | .Bd -literal -offset indent | |
214 | typedef struct elem { | |
215 | long data1; | |
216 | struct elem *link; | |
217 | int data2; | |
218 | } elem_t; | |
219 | ||
220 | elem_t fred, mary, *p; | |
221 | ||
222 | OSQueueHead q = OS_ATOMIC_QUEUE_INIT; | |
223 | ||
224 | OSAtomicEnqueue( &q, &fred, offsetof(elem_t,link) ); | |
225 | OSAtomicEnqueue( &q, &mary, offsetof(elem_t,link) ); | |
226 | ||
227 | p = OSAtomicDequeue( &q, offsetof(elem_t,link) ); | |
228 | ||
229 | .Ed | |
230 | In this example, the call of | |
231 | .Fn OSAtomicDequeue | |
232 | will return a ptr to mary. | |
59e0d9fe | 233 | .Sh RETURN VALUES |
224c7076 A |
234 | The arithmetic operations return the new value, after the operation has been performed. |
235 | The boolean operations come in two styles, one of which returns the new value, and one | |
236 | of which (the "Orig" versions) returns the old. | |
59e0d9fe A |
237 | The compare-and-swap operations return true if the comparison was equal, ie if the swap occured. |
238 | The bit test and set/clear operations return the original value of the bit. | |
224c7076 | 239 | The dequeue operation returns the most recently enqueued element, or NULL if the list in empty. |
59e0d9fe | 240 | .Sh SEE ALSO |
59e0d9fe A |
241 | .Xr spinlock 3 , |
242 | .Xr barrier 3 | |
224c7076 A |
243 | .Sh HISTORY |
244 | Most of these functions first appeared in Mac OS 10.4 (Tiger). The "Orig" forms of the | |
245 | boolean operations, the "int", "long" and "ptr" forms of compare-and-swap, and lockless | |
246 | enqueue/dequeue first appeared in Mac OS 10.5 (Leopard). |