xref: /dpdk/lib/eal/x86/include/rte_atomic_64.h (revision 558f03577b28d2757bc93fc26cd1217026c48d0c)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2010-2014 Intel Corporation.
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
599a2dd95SBruce Richardson /*
699a2dd95SBruce Richardson  * Inspired from FreeBSD src/sys/amd64/include/atomic.h
799a2dd95SBruce Richardson  * Copyright (c) 1998 Doug Rabson
899a2dd95SBruce Richardson  * Copyright (c) 2019 Intel Corporation
999a2dd95SBruce Richardson  * All rights reserved.
1099a2dd95SBruce Richardson  */
1199a2dd95SBruce Richardson 
1299a2dd95SBruce Richardson #ifndef _RTE_ATOMIC_X86_H_
1399a2dd95SBruce Richardson #error do not include this file directly, use <rte_atomic.h> instead
1499a2dd95SBruce Richardson #endif
1599a2dd95SBruce Richardson 
1699a2dd95SBruce Richardson #ifndef _RTE_ATOMIC_X86_64_H_
1799a2dd95SBruce Richardson #define _RTE_ATOMIC_X86_64_H_
1899a2dd95SBruce Richardson 
1999a2dd95SBruce Richardson #include <stdint.h>
20*558f0357SStephen Hemminger 
2199a2dd95SBruce Richardson #include <rte_common.h>
2299a2dd95SBruce Richardson 
2399a2dd95SBruce Richardson /*------------------------- 64 bit atomic operations -------------------------*/
2499a2dd95SBruce Richardson 
2599a2dd95SBruce Richardson #ifndef RTE_FORCE_INTRINSICS
2699a2dd95SBruce Richardson static inline int
rte_atomic64_cmpset(volatile uint64_t * dst,uint64_t exp,uint64_t src)2799a2dd95SBruce Richardson rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src)
2899a2dd95SBruce Richardson {
2999a2dd95SBruce Richardson 	uint8_t res;
3099a2dd95SBruce Richardson 
3199a2dd95SBruce Richardson 
3299a2dd95SBruce Richardson 	asm volatile(
3399a2dd95SBruce Richardson 			MPLOCKED
3499a2dd95SBruce Richardson 			"cmpxchgq %[src], %[dst];"
3599a2dd95SBruce Richardson 			"sete %[res];"
3699a2dd95SBruce Richardson 			: [res] "=a" (res),     /* output */
3799a2dd95SBruce Richardson 			  [dst] "=m" (*dst)
3899a2dd95SBruce Richardson 			: [src] "r" (src),      /* input */
3999a2dd95SBruce Richardson 			  "a" (exp),
4099a2dd95SBruce Richardson 			  "m" (*dst)
4199a2dd95SBruce Richardson 			: "memory");            /* no-clobber list */
4299a2dd95SBruce Richardson 
4399a2dd95SBruce Richardson 	return res;
4499a2dd95SBruce Richardson }
4599a2dd95SBruce Richardson 
4699a2dd95SBruce Richardson static inline uint64_t
rte_atomic64_exchange(volatile uint64_t * dst,uint64_t val)4799a2dd95SBruce Richardson rte_atomic64_exchange(volatile uint64_t *dst, uint64_t val)
4899a2dd95SBruce Richardson {
4999a2dd95SBruce Richardson 	asm volatile(
5099a2dd95SBruce Richardson 			MPLOCKED
5199a2dd95SBruce Richardson 			"xchgq %0, %1;"
5299a2dd95SBruce Richardson 			: "=r" (val), "=m" (*dst)
5399a2dd95SBruce Richardson 			: "0" (val),  "m" (*dst)
5499a2dd95SBruce Richardson 			: "memory");         /* no-clobber list */
5599a2dd95SBruce Richardson 	return val;
5699a2dd95SBruce Richardson }
5799a2dd95SBruce Richardson 
5899a2dd95SBruce Richardson static inline void
rte_atomic64_init(rte_atomic64_t * v)5999a2dd95SBruce Richardson rte_atomic64_init(rte_atomic64_t *v)
6099a2dd95SBruce Richardson {
6199a2dd95SBruce Richardson 	v->cnt = 0;
6299a2dd95SBruce Richardson }
6399a2dd95SBruce Richardson 
6499a2dd95SBruce Richardson static inline int64_t
rte_atomic64_read(rte_atomic64_t * v)6599a2dd95SBruce Richardson rte_atomic64_read(rte_atomic64_t *v)
6699a2dd95SBruce Richardson {
6799a2dd95SBruce Richardson 	return v->cnt;
6899a2dd95SBruce Richardson }
6999a2dd95SBruce Richardson 
7099a2dd95SBruce Richardson static inline void
rte_atomic64_set(rte_atomic64_t * v,int64_t new_value)7199a2dd95SBruce Richardson rte_atomic64_set(rte_atomic64_t *v, int64_t new_value)
7299a2dd95SBruce Richardson {
7399a2dd95SBruce Richardson 	v->cnt = new_value;
7499a2dd95SBruce Richardson }
7599a2dd95SBruce Richardson 
7699a2dd95SBruce Richardson static inline void
rte_atomic64_add(rte_atomic64_t * v,int64_t inc)7799a2dd95SBruce Richardson rte_atomic64_add(rte_atomic64_t *v, int64_t inc)
7899a2dd95SBruce Richardson {
7999a2dd95SBruce Richardson 	asm volatile(
8099a2dd95SBruce Richardson 			MPLOCKED
8199a2dd95SBruce Richardson 			"addq %[inc], %[cnt]"
8299a2dd95SBruce Richardson 			: [cnt] "=m" (v->cnt)   /* output */
8399a2dd95SBruce Richardson 			: [inc] "ir" (inc),     /* input */
8499a2dd95SBruce Richardson 			  "m" (v->cnt)
8599a2dd95SBruce Richardson 			);
8699a2dd95SBruce Richardson }
8799a2dd95SBruce Richardson 
8899a2dd95SBruce Richardson static inline void
rte_atomic64_sub(rte_atomic64_t * v,int64_t dec)8999a2dd95SBruce Richardson rte_atomic64_sub(rte_atomic64_t *v, int64_t dec)
9099a2dd95SBruce Richardson {
9199a2dd95SBruce Richardson 	asm volatile(
9299a2dd95SBruce Richardson 			MPLOCKED
9399a2dd95SBruce Richardson 			"subq %[dec], %[cnt]"
9499a2dd95SBruce Richardson 			: [cnt] "=m" (v->cnt)   /* output */
9599a2dd95SBruce Richardson 			: [dec] "ir" (dec),     /* input */
9699a2dd95SBruce Richardson 			  "m" (v->cnt)
9799a2dd95SBruce Richardson 			);
9899a2dd95SBruce Richardson }
9999a2dd95SBruce Richardson 
10099a2dd95SBruce Richardson static inline void
rte_atomic64_inc(rte_atomic64_t * v)10199a2dd95SBruce Richardson rte_atomic64_inc(rte_atomic64_t *v)
10299a2dd95SBruce Richardson {
10399a2dd95SBruce Richardson 	asm volatile(
10499a2dd95SBruce Richardson 			MPLOCKED
10599a2dd95SBruce Richardson 			"incq %[cnt]"
10699a2dd95SBruce Richardson 			: [cnt] "=m" (v->cnt)   /* output */
10799a2dd95SBruce Richardson 			: "m" (v->cnt)          /* input */
10899a2dd95SBruce Richardson 			);
10999a2dd95SBruce Richardson }
11099a2dd95SBruce Richardson 
11199a2dd95SBruce Richardson static inline void
rte_atomic64_dec(rte_atomic64_t * v)11299a2dd95SBruce Richardson rte_atomic64_dec(rte_atomic64_t *v)
11399a2dd95SBruce Richardson {
11499a2dd95SBruce Richardson 	asm volatile(
11599a2dd95SBruce Richardson 			MPLOCKED
11699a2dd95SBruce Richardson 			"decq %[cnt]"
11799a2dd95SBruce Richardson 			: [cnt] "=m" (v->cnt)   /* output */
11899a2dd95SBruce Richardson 			: "m" (v->cnt)          /* input */
11999a2dd95SBruce Richardson 			);
12099a2dd95SBruce Richardson }
12199a2dd95SBruce Richardson 
12299a2dd95SBruce Richardson static inline int64_t
rte_atomic64_add_return(rte_atomic64_t * v,int64_t inc)12399a2dd95SBruce Richardson rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc)
12499a2dd95SBruce Richardson {
12599a2dd95SBruce Richardson 	int64_t prev = inc;
12699a2dd95SBruce Richardson 
12799a2dd95SBruce Richardson 	asm volatile(
12899a2dd95SBruce Richardson 			MPLOCKED
12999a2dd95SBruce Richardson 			"xaddq %[prev], %[cnt]"
13099a2dd95SBruce Richardson 			: [prev] "+r" (prev),   /* output */
13199a2dd95SBruce Richardson 			  [cnt] "=m" (v->cnt)
13299a2dd95SBruce Richardson 			: "m" (v->cnt)          /* input */
13399a2dd95SBruce Richardson 			);
13499a2dd95SBruce Richardson 	return prev + inc;
13599a2dd95SBruce Richardson }
13699a2dd95SBruce Richardson 
13799a2dd95SBruce Richardson static inline int64_t
rte_atomic64_sub_return(rte_atomic64_t * v,int64_t dec)13899a2dd95SBruce Richardson rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec)
13999a2dd95SBruce Richardson {
14099a2dd95SBruce Richardson 	return rte_atomic64_add_return(v, -dec);
14199a2dd95SBruce Richardson }
14299a2dd95SBruce Richardson 
rte_atomic64_inc_and_test(rte_atomic64_t * v)14399a2dd95SBruce Richardson static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v)
14499a2dd95SBruce Richardson {
14599a2dd95SBruce Richardson 	uint8_t ret;
14699a2dd95SBruce Richardson 
14799a2dd95SBruce Richardson 	asm volatile(
14899a2dd95SBruce Richardson 			MPLOCKED
14999a2dd95SBruce Richardson 			"incq %[cnt] ; "
15099a2dd95SBruce Richardson 			"sete %[ret]"
15199a2dd95SBruce Richardson 			: [cnt] "+m" (v->cnt), /* output */
15299a2dd95SBruce Richardson 			  [ret] "=qm" (ret)
15399a2dd95SBruce Richardson 			);
15499a2dd95SBruce Richardson 
15599a2dd95SBruce Richardson 	return ret != 0;
15699a2dd95SBruce Richardson }
15799a2dd95SBruce Richardson 
rte_atomic64_dec_and_test(rte_atomic64_t * v)15899a2dd95SBruce Richardson static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v)
15999a2dd95SBruce Richardson {
16099a2dd95SBruce Richardson 	uint8_t ret;
16199a2dd95SBruce Richardson 
16299a2dd95SBruce Richardson 	asm volatile(
16399a2dd95SBruce Richardson 			MPLOCKED
16499a2dd95SBruce Richardson 			"decq %[cnt] ; "
16599a2dd95SBruce Richardson 			"sete %[ret]"
16699a2dd95SBruce Richardson 			: [cnt] "+m" (v->cnt),  /* output */
16799a2dd95SBruce Richardson 			  [ret] "=qm" (ret)
16899a2dd95SBruce Richardson 			);
16999a2dd95SBruce Richardson 	return ret != 0;
17099a2dd95SBruce Richardson }
17199a2dd95SBruce Richardson 
rte_atomic64_test_and_set(rte_atomic64_t * v)17299a2dd95SBruce Richardson static inline int rte_atomic64_test_and_set(rte_atomic64_t *v)
17399a2dd95SBruce Richardson {
17499a2dd95SBruce Richardson 	return rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, 0, 1);
17599a2dd95SBruce Richardson }
17699a2dd95SBruce Richardson 
rte_atomic64_clear(rte_atomic64_t * v)17799a2dd95SBruce Richardson static inline void rte_atomic64_clear(rte_atomic64_t *v)
17899a2dd95SBruce Richardson {
17999a2dd95SBruce Richardson 	v->cnt = 0;
18099a2dd95SBruce Richardson }
18199a2dd95SBruce Richardson #endif
18299a2dd95SBruce Richardson 
18399a2dd95SBruce Richardson /*------------------------ 128 bit atomic operations -------------------------*/
18499a2dd95SBruce Richardson 
18599a2dd95SBruce Richardson static inline int
rte_atomic128_cmp_exchange(rte_int128_t * dst,rte_int128_t * exp,const rte_int128_t * src,unsigned int weak,int success,int failure)18699a2dd95SBruce Richardson rte_atomic128_cmp_exchange(rte_int128_t *dst,
18799a2dd95SBruce Richardson 			   rte_int128_t *exp,
18899a2dd95SBruce Richardson 			   const rte_int128_t *src,
18999a2dd95SBruce Richardson 			   unsigned int weak,
19099a2dd95SBruce Richardson 			   int success,
19199a2dd95SBruce Richardson 			   int failure)
19299a2dd95SBruce Richardson {
19399a2dd95SBruce Richardson 	RTE_SET_USED(weak);
19499a2dd95SBruce Richardson 	RTE_SET_USED(success);
19599a2dd95SBruce Richardson 	RTE_SET_USED(failure);
19699a2dd95SBruce Richardson 	uint8_t res;
19799a2dd95SBruce Richardson 
19899a2dd95SBruce Richardson 	asm volatile (
19999a2dd95SBruce Richardson 		      MPLOCKED
20099a2dd95SBruce Richardson 		      "cmpxchg16b %[dst];"
20199a2dd95SBruce Richardson 		      " sete %[res]"
20299a2dd95SBruce Richardson 		      : [dst] "=m" (dst->val[0]),
20399a2dd95SBruce Richardson 			"=a" (exp->val[0]),
20499a2dd95SBruce Richardson 			"=d" (exp->val[1]),
20599a2dd95SBruce Richardson 			[res] "=r" (res)
20699a2dd95SBruce Richardson 		      : "b" (src->val[0]),
20799a2dd95SBruce Richardson 			"c" (src->val[1]),
20899a2dd95SBruce Richardson 			"a" (exp->val[0]),
20999a2dd95SBruce Richardson 			"d" (exp->val[1]),
21099a2dd95SBruce Richardson 			"m" (dst->val[0])
21199a2dd95SBruce Richardson 		      : "memory");
21299a2dd95SBruce Richardson 
21399a2dd95SBruce Richardson 	return res;
21499a2dd95SBruce Richardson }
21599a2dd95SBruce Richardson 
21699a2dd95SBruce Richardson #endif /* _RTE_ATOMIC_X86_64_H_ */
217