first public release
[dpdk.git] / lib / librte_eal / common / include / rte_atomic.h
1 /*-
2  *   BSD LICENSE
3  * 
4  *   Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  * 
7  *   Redistribution and use in source and binary forms, with or without 
8  *   modification, are permitted provided that the following conditions 
9  *   are met:
10  * 
11  *     * Redistributions of source code must retain the above copyright 
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright 
14  *       notice, this list of conditions and the following disclaimer in 
15  *       the documentation and/or other materials provided with the 
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its 
18  *       contributors may be used to endorse or promote products derived 
19  *       from this software without specific prior written permission.
20  * 
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  * 
33  *  version: DPDK.L.1.2.3-3
34  */
35
36 #ifndef _RTE_ATOMIC_H_
37 #define _RTE_ATOMIC_H_
38
39 /**
40  * @file
41  * Atomic Operations
42  *
43  * This file defines a generic API for atomic
44  * operations. The implementation is architecture-specific.
45  *
46  * See lib/librte_eal/common/include/i686/arch/rte_atomic.h
47  * See lib/librte_eal/common/include/x86_64/arch/rte_atomic.h
48  */
49
50 #ifdef __cplusplus
51 extern "C" {
52 #endif
53
54 #include <stdint.h>
55
56 #include "arch/rte_atomic.h"
57
58
59 #ifdef __DOXYGEN__
60
61 /**
62  * General memory barrier.
63  *
64  * Guarantees that the LOAD and STORE operations generated before the
65  * barrier occur before the LOAD and STORE operations generated after.
66  */
67 #define rte_mb()  asm volatile("mfence;" : : : "memory")
68
69 /**
70  * Write memory barrier.
71  *
72  * Guarantees that the STORE operations generated before the barrier
73  * occur before the STORE operations generated after.
74  */
75 #define rte_wmb() asm volatile("sfence;" : : : "memory")
76
77 /**
78  * Read memory barrier.
79  *
80  * Guarantees that the LOAD operations generated before the barrier
81  * occur before the LOAD operations generated after.
82  */
83 #define rte_rmb() asm volatile("lfence;" : : : "memory")
84
85 /*------------------------- 16 bit atomic operations -------------------------*/
86
87 /**
88  * Atomic compare and set.
89  *
90  * (atomic) equivalent to:
91  *   if (*dst == exp)
92  *     *dst = src (all 16-bit words)
93  *
94  * @param dst
95  *   The destination location into which the value will be written.
96  * @param exp
97  *   The expected value.
98  * @param src
99  *   The new value.
100  * @return
101  *   Non-zero on success; 0 on failure.
102  */
103 static inline int
104 rte_atomic16_cmpset(volatile uint16_t *dst, uint16_t exp, uint16_t src);
105
106 /**
107  * The atomic counter structure.
108  */
109 typedef struct {
110         volatile int16_t cnt; /**< An internal counter value. */
111 } rte_atomic16_t;
112
113 /**
114  * Static initializer for an atomic counter.
115  */
116 #define RTE_ATOMIC16_INIT(val) { (val) }
117
118 /**
119  * Initialize an atomic counter.
120  *
121  * @param v
122  *   A pointer to the atomic counter.
123  */
124 static inline void
125 rte_atomic16_init(rte_atomic16_t *v)
126 {
127         v->cnt = 0;
128 }
129
130 /**
131  * Atomically read a 16-bit value from a counter.
132  *
133  * @param v
134  *   A pointer to the atomic counter.
135  * @return
136  *   The value of the counter.
137  */
138 static inline int16_t
139 rte_atomic16_read(const rte_atomic16_t *v);
140
141 /**
142  * Atomically set a counter to a 16-bit value.
143  *
144  * @param v
145  *   A pointer to the atomic counter.
146  * @param new_value
147  *   The new value for the counter.
148  */
149 static inline void
150 rte_atomic16_set(rte_atomic16_t *v, int16_t new_value);
151
152 /**
153  * Atomically add a 16-bit value to an atomic counter.
154  *
155  * @param v
156  *   A pointer to the atomic counter.
157  * @param inc
158  *   The value to be added to the counter.
159  */
160 static inline void
161 rte_atomic16_add(rte_atomic16_t *v, int16_t inc);
162
163 /**
164  * Atomically subtract a 16-bit value from an atomic counter.
165  *
166  * @param v
167  *   A pointer to the atomic counter.
168  * @param dec
169  *   The value to be subtracted from the counter.
170  */
171 static inline void
172 rte_atomic16_sub(rte_atomic16_t *v, int16_t dec);
173
174 /**
175  * Atomically increment a counter by one.
176  *
177  * @param v
178  *   A pointer to the atomic counter.
179  */
180 static inline void
181 rte_atomic16_inc(rte_atomic16_t *v);
182
183 /**
184  * Atomically decrement a counter by one.
185  *
186  * @param v
187  *   A pointer to the atomic counter.
188  */
189 static inline void
190 rte_atomic16_dec(rte_atomic16_t *v);
191
192 /**
193  * Atomically add a 16-bit value to a counter and return the result.
194  *
195  * Atomically adds the 16-bits value (inc) to the atomic counter (v) and
196  * returns the value of v after addition.
197  *
198  * @param v
199  *   A pointer to the atomic counter.
200  * @param inc
201  *   The value to be added to the counter.
202  * @return
203  *   The value of v after the addition.
204  */
205 static inline int16_t
206 rte_atomic16_add_return(rte_atomic16_t *v, int16_t inc);
207
208 /**
209  * Atomically subtract a 16-bit value from a counter and return
210  * the result.
211  *
212  * Atomically subtracts the 16-bit value (inc) from the atomic counter
213  * (v) and returns the value of v after the subtraction.
214  *
215  * @param v
216  *   A pointer to the atomic counter.
217  * @param dec
218  *   The value to be subtracted from the counter.
219  * @return
220  *   The value of v after the subtraction.
221  */
222 static inline int16_t
223 rte_atomic16_sub_return(rte_atomic16_t *v, int16_t dec);
224
225 /**
226  * Atomically increment a 16-bit counter by one and test.
227  *
228  * Atomically increments the atomic counter (v) by one and returns true if
229  * the result is 0, or false in all other cases.
230  *
231  * @param v
232  *   A pointer to the atomic counter.
233  * @return
234  *   True if the result after the increment operation is 0; false otherwise.
235  */
236 static inline int
237 rte_atomic16_inc_and_test(rte_atomic16_t *v);
238
239 /**
240  * Atomically decrement a 16-bit counter by one and test.
241  *
242  * Atomically decrements the atomic counter (v) by one and returns true if
243  * the result is 0, or false in all other cases.
244  *
245  * @param v
246  *   A pointer to the atomic counter.
247  * @return
248  *   True if the result after the decrement operation is 0; false otherwise.
249  */
250 static inline int
251 rte_atomic16_dec_and_test(rte_atomic16_t *v);
252
253 /**
254  * Atomically test and set a 16-bit atomic counter.
255  *
256  * If the counter value is already set, return 0 (failed). Otherwise, set
257  * the counter value to 1 and return 1 (success).
258  *
259  * @param v
260  *   A pointer to the atomic counter.
261  * @return
262  *   0 if failed; else 1, success.
263  */
264 static inline int
265 rte_atomic16_test_and_set(rte_atomic16_t *v);
266
267 /**
268  * Atomically set a 16-bit counter to 0.
269  *
270  * @param v
271  *   A pointer to the atomic counter.
272  */
273 static inline void
274 rte_atomic16_clear(rte_atomic16_t *v);
275
276 /*------------------------- 32 bit atomic operations -------------------------*/
277
278 /**
279  * Atomic compare and set.
280  *
281  * (atomic) equivalent to:
282  *   if (*dst == exp)
283  *     *dst = src (all 32-bit words)
284  *
285  * @param dst
286  *   The destination location into which the value will be written.
287  * @param exp
288  *   The expected value.
289  * @param src
290  *   The new value.
291  * @return
292  *   Non-zero on success; 0 on failure.
293  */
294 static inline int
295 rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src);
296
297 /**
298  * The atomic counter structure.
299  */
300 typedef struct {
301         volatile int32_t cnt; /**< An internal counter value. */
302 } rte_atomic32_t;
303
304 /**
305  * Static initializer for an atomic counter.
306  */
307 #define RTE_ATOMIC32_INIT(val) { (val) }
308
309 /**
310  * Initialize an atomic counter.
311  *
312  * @param v
313  *   A pointer to the atomic counter.
314  */
315 static inline void
316 rte_atomic32_init(rte_atomic32_t *v);
317
318 /**
319  * Atomically read a 32-bit value from a counter.
320  *
321  * @param v
322  *   A pointer to the atomic counter.
323  * @return
324  *   The value of the counter.
325  */
326 static inline int32_t
327 rte_atomic32_read(const rte_atomic32_t *v);
328
329 /**
330  * Atomically set a counter to a 32-bit value.
331  *
332  * @param v
333  *   A pointer to the atomic counter.
334  * @param new_value
335  *   The new value for the counter.
336  */
337 static inline void
338 rte_atomic32_set(rte_atomic32_t *v, int32_t new_value);
339
340 /**
341  * Atomically add a 32-bit value to an atomic counter.
342  *
343  * @param v
344  *   A pointer to the atomic counter.
345  * @param inc
346  *   The value to be added to the counter.
347  */
348 static inline void
349 rte_atomic32_add(rte_atomic32_t *v, int32_t inc);
350
351 /**
352  * Atomically subtract a 32-bit value from an atomic counter.
353  *
354  * @param v
355  *   A pointer to the atomic counter.
356  * @param dec
357  *   The value to be subtracted from the counter.
358  */
359 static inline void
360 rte_atomic32_sub(rte_atomic32_t *v, int32_t dec);
361
362 /**
363  * Atomically increment a counter by one.
364  *
365  * @param v
366  *   A pointer to the atomic counter.
367  */
368 static inline void
369 rte_atomic32_inc(rte_atomic32_t *v);
370
371 /**
372  * Atomically decrement a counter by one.
373  *
374  * @param v
375  *   A pointer to the atomic counter.
376  */
377 static inline void
378 rte_atomic32_dec(rte_atomic32_t *v);
379
380 /**
381  * Atomically add a 32-bit value to a counter and return the result.
382  *
383  * Atomically adds the 32-bits value (inc) to the atomic counter (v) and
384  * returns the value of v after addition.
385  *
386  * @param v
387  *   A pointer to the atomic counter.
388  * @param inc
389  *   The value to be added to the counter.
390  * @return
391  *   The value of v after the addition.
392  */
393 static inline int32_t
394 rte_atomic32_add_return(rte_atomic32_t *v, int32_t inc);
395
396 /**
397  * Atomically subtract a 32-bit value from a counter and return
398  * the result.
399  *
400  * Atomically subtracts the 32-bit value (inc) from the atomic counter
401  * (v) and returns the value of v after the subtraction.
402  *
403  * @param v
404  *   A pointer to the atomic counter.
405  * @param dec
406  *   The value to be subtracted from the counter.
407  * @return
408  *   The value of v after the subtraction.
409  */
410 static inline int32_t
411 rte_atomic32_sub_return(rte_atomic32_t *v, int32_t dec);
412
413 /**
414  * Atomically increment a 32-bit counter by one and test.
415  *
416  * Atomically increments the atomic counter (v) by one and returns true if
417  * the result is 0, or false in all other cases.
418  *
419  * @param v
420  *   A pointer to the atomic counter.
421  * @return
422  *   True if the result after the increment operation is 0; false otherwise.
423  */
424 static inline int
425 rte_atomic32_inc_and_test(rte_atomic32_t *v);
426
427 /**
428  * Atomically decrement a 32-bit counter by one and test.
429  *
430  * Atomically decrements the atomic counter (v) by one and returns true if
431  * the result is 0, or false in all other cases.
432  *
433  * @param v
434  *   A pointer to the atomic counter.
435  * @return
436  *   True if the result after the decrement operation is 0; false otherwise.
437  */
438 static inline int
439 rte_atomic32_dec_and_test(rte_atomic32_t *v);
440
441 /**
442  * Atomically test and set a 32-bit atomic counter.
443  *
444  * If the counter value is already set, return 0 (failed). Otherwise, set
445  * the counter value to 1 and return 1 (success).
446  *
447  * @param v
448  *   A pointer to the atomic counter.
449  * @return
450  *   0 if failed; else 1, success.
451  */
452 static inline int
453 rte_atomic32_test_and_set(rte_atomic32_t *v);
454
455 /**
456  * Atomically set a 32-bit counter to 0.
457  *
458  * @param v
459  *   A pointer to the atomic counter.
460  */
461 static inline void
462 rte_atomic32_clear(rte_atomic32_t *v);
463
464 /*------------------------- 64 bit atomic operations -------------------------*/
465
466 /**
467  * An atomic compare and set function used by the mutex functions.
468  * (atomic) equivalent to:
469  *   if (*dst == exp)
470  *     *dst = src (all 64-bit words)
471  *
472  * @param dst
473  *   The destination into which the value will be written.
474  * @param exp
475  *   The expected value.
476  * @param src
477  *   The new value.
478  * @return
479  *   Non-zero on success; 0 on failure.
480  */
481 static inline int
482 rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src);
483
484 /**
485  * The atomic counter structure.
486  */
487 typedef struct {
488         volatile int64_t cnt;  /**< Internal counter value. */
489 } rte_atomic64_t;
490
491 /**
492  * Static initializer for an atomic counter.
493  */
494 #define RTE_ATOMIC64_INIT(val) { (val) }
495
496 /**
497  * Initialize the atomic counter.
498  *
499  * @param v
500  *   A pointer to the atomic counter.
501  */
502 static inline void
503 rte_atomic64_init(rte_atomic64_t *v);
504
505 /**
506  * Atomically read a 64-bit counter.
507  *
508  * @param v
509  *   A pointer to the atomic counter.
510  * @return
511  *   The value of the counter.
512  */
513 static inline int64_t
514 rte_atomic64_read(rte_atomic64_t *v);
515
516 /**
517  * Atomically set a 64-bit counter.
518  *
519  * @param v
520  *   A pointer to the atomic counter.
521  * @param new_value
522  *   The new value of the counter.
523  */
524 static inline void
525 rte_atomic64_set(rte_atomic64_t *v, int64_t new_value);
526
527 /**
528  * Atomically add a 64-bit value to a counter.
529  *
530  * @param v
531  *   A pointer to the atomic counter.
532  * @param inc
533  *   The value to be added to the counter.
534  */
535 static inline void
536 rte_atomic64_add(rte_atomic64_t *v, int64_t inc);
537
538 /**
539  * Atomically subtract a 64-bit value from a counter.
540  *
541  * @param v
542  *   A pointer to the atomic counter.
543  * @param dec
544  *   The value to be subtracted from the counter.
545  */
546 static inline void
547 rte_atomic64_sub(rte_atomic64_t *v, int64_t dec);
548
549 /**
550  * Atomically increment a 64-bit counter by one and test.
551  *
552  * @param v
553  *   A pointer to the atomic counter.
554  */
555 static inline void
556 rte_atomic64_inc(rte_atomic64_t *v);
557
558 /**
559  * Atomically decrement a 64-bit counter by one and test.
560  *
561  * @param v
562  *   A pointer to the atomic counter.
563  */
564 static inline void
565 rte_atomic64_dec(rte_atomic64_t *v);
566
567 /**
568  * Add a 64-bit value to an atomic counter and return the result.
569  *
570  * Atomically adds the 64-bit value (inc) to the atomic counter (v) and
571  * returns the value of v after the addition.
572  *
573  * @param v
574  *   A pointer to the atomic counter.
575  * @param inc
576  *   The value to be added to the counter.
577  * @return
578  *   The value of v after the addition.
579  */
580 static inline int64_t
581 rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc);
582
583 /**
584  * Subtract a 64-bit value from an atomic counter and return the result.
585  *
586  * Atomically subtracts the 64-bit value (dec) from the atomic counter (v)
587  * and returns the value of v after the subtraction.
588  *
589  * @param v
590  *   A pointer to the atomic counter.
591  * @param dec
592  *   The value to be subtracted from the counter.
593  * @return
594  *   The value of v after the subtraction.
595  */
596 static inline int64_t
597 rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec);
598
599 /**
600  * Atomically increment a 64-bit counter by one and test.
601  *
602  * Atomically increments the atomic counter (v) by one and returns
603  * true if the result is 0, or false in all other cases.
604  *
605  * @param v
606  *   A pointer to the atomic counter.
607  * @return
608  *   True if the result after the addition is 0; false otherwise.
609  */
610 static inline int
611 rte_atomic64_inc_and_test(rte_atomic64_t *v);
612
613 /**
614  * Atomically decrement a 64-bit counter by one and test.
615  *
616  * Atomically decrements the atomic counter (v) by one and returns true if
617  * the result is 0, or false in all other cases.
618  *
619  * @param v
620  *   A pointer to the atomic counter.
621  * @return
622  *   True if the result after subtraction is 0; false otherwise.
623  */
624 static inline int
625 rte_atomic64_dec_and_test(rte_atomic64_t *v);
626
627 /**
628  * Atomically test and set a 64-bit atomic counter.
629  *
630  * If the counter value is already set, return 0 (failed). Otherwise, set
631  * the counter value to 1 and return 1 (success).
632  *
633  * @param v
634  *   A pointer to the atomic counter.
635  * @return
636  *   0 if failed; else 1, success.
637  */
638 static inline int
639 rte_atomic64_test_and_set(rte_atomic64_t *v);
640
641 /**
642  * Atomically set a 64-bit counter to 0.
643  *
644  * @param v
645  *   A pointer to the atomic counter.
646  */
647 static inline void
648 rte_atomic64_clear(rte_atomic64_t *v);
649
650 #endif /* __DOXYGEN__ */
651
652
653 #ifdef __cplusplus
654 }
655 #endif
656
657 #endif /* _RTE_ATOMIC_H_ */