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