]> git.saurik.com Git - apple/libc.git/blob - sys/atomic.3
Libc-498.1.5.tar.gz
[apple/libc.git] / sys / atomic.3
1 .Dd May 26, 2004
2 .Dt ATOMIC 3
3 .Os Darwin
4 .Sh NAME
5 .Nm OSAtomicAdd32 ,
6 .Nm OSAtomicAdd32Barrier ,
7 .Nm OSAtomicIncrement32 ,
8 .Nm OSAtomicIncrement32Barrier ,
9 .Nm OSAtomicDecrement32 ,
10 .Nm OSAtomicDecrement32Barrier ,
11 .Nm OSAtomicOr32 ,
12 .Nm OSAtomicOr32Barrier ,
13 .Nm OSAtomicOr32Orig ,
14 .Nm OSAtomicOr32OrigBarrier ,
15 .Nm OSAtomicAnd32 ,
16 .Nm OSAtomicAnd32Barrier ,
17 .Nm OSAtomicAnd32Orig ,
18 .Nm OSAtomicAnd32OrigBarrier ,
19 .Nm OSAtomicXor32 ,
20 .Nm OSAtomicXor32Barrier ,
21 .Nm OSAtomicXor32Orig ,
22 .Nm OSAtomicXor32OrigBarrier ,
23 .Nm OSAtomicAdd64 ,
24 .Nm OSAtomicAdd64Barrier ,
25 .Nm OSAtomicIncrement64 ,
26 .Nm OSAtomicIncrement64Barrier ,
27 .Nm OSAtomicDecrement64 ,
28 .Nm OSAtomicDecrement64Barrier ,
29 .Nm OSAtomicCompareAndSwapInt ,
30 .Nm OSAtomicCompareAndSwapIntBarrier ,
31 .Nm OSAtomicCompareAndSwapLong ,
32 .Nm OSAtomicCompareAndSwapLongBarrier ,
33 .Nm OSAtomicCompareAndSwapPtr ,
34 .Nm OSAtomicCompareAndSwapPtrBarrier ,
35 .Nm OSAtomicCompareAndSwap32 ,
36 .Nm OSAtomicCompareAndSwap32Barrier ,
37 .Nm OSAtomicCompareAndSwap64 ,
38 .Nm OSAtomicCompareAndSwap64Barrier ,
39 .Nm OSAtomicTestAndSet ,
40 .Nm OSAtomicTestAndSetBarrier ,
41 .Nm OSAtomicTestAndClear ,
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
49 .Sh LIBRARY
50 .Lb libc
51 .Sh SYNOPSIS
52 .In libkern/OSAtomic.h
53 .Ft int32_t
54 .Fn OSAtomicAdd32 "int32_t theAmount" "volatile int32_t *theValue"
55 .Ft int32_t
56 .Fn OSAtomicAdd32Barrier "int32_t theAmount" "volatile int32_t *theValue"
57 .Ft int32_t
58 .Fn OSAtomicIncrement32 "volatile int32_t *theValue"
59 .Ft int32_t
60 .Fn OSAtomicIncrement32Barrier "volatile int32_t *theValue"
61 .Ft int32_t
62 .Fn OSAtomicDecrement32 "volatile int32_t *theValue"
63 .Ft int32_t
64 .Fn OSAtomicDecrement32Barrier "volatile int32_t *theValue"
65 .Ft int32_t
66 .Fn OSAtomicOr32 "uint32_t theMask" "volatile uint32_t *theValue"
67 .Ft int32_t
68 .Fn OSAtomicOr32Barrier "uint32_t theMask" "volatile uint32_t *theValue"
69 .Ft int32_t
70 .Fn OSAtomicAnd32 "uint32_t theMask" "volatile uint32_t *theValue"
71 .Ft int32_t
72 .Fn OSAtomicAnd32Barrier "uint32_t theMask" "volatile uint32_t *theValue"
73 .Ft int32_t
74 .Fn OSAtomicXor32 "uint32_t theMask" "volatile uint32_t *theValue"
75 .Ft int32_t
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"
89 .Ft int64_t
90 .Fn OSAtomicAdd64 "int64_t theAmount" "volatile int64_t *theValue"
91 .Ft int64_t
92 .Fn OSAtomicAdd64Barrier "int64_t theAmount" "volatile int64_t *theValue"
93 .Ft int64_t
94 .Fn OSAtomicIncrement64 "volatile int64_t *theValue"
95 .Ft int64_t
96 .Fn OSAtomicIncrement64Barrier "volatile int64_t *theValue"
97 .Ft int64_t
98 .Fn OSAtomicDecrement64 "volatile int64_t *theValue"
99 .Ft int64_t
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"
107 .Ft bool
108 .Fn OSAtomicCompareAndSwapLongBarrier "long oldValue" "long newValue" "volatile long *theValue"
109 .Ft bool
110 .Fn OSAtomicCompareAndSwapPtr "void* oldValue" "void* newValue" "void* volatile *theValue"
111 .Ft bool
112 .Fn OSAtomicCompareAndSwapPtrBarrier "void* oldValue" "void* newValue" "void* volatile *theValue"
113 .Ft bool
114 .Fn OSAtomicCompareAndSwap32 "int32_t oldValue" "int32_t newValue" "volatile int32_t *theValue"
115 .Ft bool
116 .Fn OSAtomicCompareAndSwap32Barrier "int32_t oldValue" "int32_t newValue" "volatile int32_t *theValue"
117 .Ft bool
118 .Fn OSAtomicCompareAndSwap64 "int64_t oldValue" "int64_t newValue" "volatile int64_t *theValue"
119 .Ft bool
120 .Fn OSAtomicCompareAndSwap64Barrier "int64_t oldValue" "int64_t newValue" "volatile int64_t *theValue"
121 .Ft bool
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"
139 .Sh DESCRIPTION
140 These functions are thread and multiprocessor safe. For each function, there
141 is a version that does and another that does not incorporate a memory barrier.
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
151 that the initialization is complete, then you must use OSAtomicIncrement32Barrier()
152 to ensure that the stores to your data structure complete before the atomic add.
153 Likewise, the consumer of that data structure must use OSAtomicDecrement32Barrier(),
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
161 .Fn OSAtomicCompareAndSwap
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 ).
169 .Pp
170 The memory address
171 .Fa theValue
172 must be naturally aligned, ie 32-bit aligned for 32-bit operations and 64-bit
173 aligned for 64-bit operations.
174 .Pp
175 The 64-bit operations are not implemented for 32-bit processes on PPC platforms.
176 .Pp
177 The
178 .Fn OSAtomicCompareAndSwap
179 operations compare
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.
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.
233 .Sh RETURN VALUES
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.
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.
239 The dequeue operation returns the most recently enqueued element, or NULL if the list in empty.
240 .Sh SEE ALSO
241 .Xr spinlock 3 ,
242 .Xr barrier 3
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).