numam-dpdk/lib/librte_eal/x86/include/rte_atomic_64.h

219 lines
4.1 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2010-2014 Intel Corporation.
*/
/*
* Inspired from FreeBSD src/sys/amd64/include/atomic.h
* Copyright (c) 1998 Doug Rabson
* Copyright (c) 2019 Intel Corporation
* All rights reserved.
*/
#ifndef _RTE_ATOMIC_X86_H_
#error do not include this file directly, use <rte_atomic.h> instead
#endif
#ifndef _RTE_ATOMIC_X86_64_H_
#define _RTE_ATOMIC_X86_64_H_
#include <stdint.h>
#include <rte_common.h>
#include <rte_compat.h>
#include <rte_atomic.h>
/*------------------------- 64 bit atomic operations -------------------------*/
#ifndef RTE_FORCE_INTRINSICS
static inline int
rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src)
{
uint8_t res;
asm volatile(
MPLOCKED
"cmpxchgq %[src], %[dst];"
"sete %[res];"
: [res] "=a" (res), /* output */
[dst] "=m" (*dst)
: [src] "r" (src), /* input */
"a" (exp),
"m" (*dst)
: "memory"); /* no-clobber list */
return res;
}
static inline uint64_t
rte_atomic64_exchange(volatile uint64_t *dst, uint64_t val)
{
asm volatile(
MPLOCKED
"xchgq %0, %1;"
: "=r" (val), "=m" (*dst)
: "0" (val), "m" (*dst)
: "memory"); /* no-clobber list */
return val;
}
static inline void
rte_atomic64_init(rte_atomic64_t *v)
{
v->cnt = 0;
}
static inline int64_t
rte_atomic64_read(rte_atomic64_t *v)
{
return v->cnt;
}
static inline void
rte_atomic64_set(rte_atomic64_t *v, int64_t new_value)
{
v->cnt = new_value;
}
static inline void
rte_atomic64_add(rte_atomic64_t *v, int64_t inc)
{
asm volatile(
MPLOCKED
"addq %[inc], %[cnt]"
: [cnt] "=m" (v->cnt) /* output */
: [inc] "ir" (inc), /* input */
"m" (v->cnt)
);
}
static inline void
rte_atomic64_sub(rte_atomic64_t *v, int64_t dec)
{
asm volatile(
MPLOCKED
"subq %[dec], %[cnt]"
: [cnt] "=m" (v->cnt) /* output */
: [dec] "ir" (dec), /* input */
"m" (v->cnt)
);
}
static inline void
rte_atomic64_inc(rte_atomic64_t *v)
{
asm volatile(
MPLOCKED
"incq %[cnt]"
: [cnt] "=m" (v->cnt) /* output */
: "m" (v->cnt) /* input */
);
}
static inline void
rte_atomic64_dec(rte_atomic64_t *v)
{
asm volatile(
MPLOCKED
"decq %[cnt]"
: [cnt] "=m" (v->cnt) /* output */
: "m" (v->cnt) /* input */
);
}
static inline int64_t
rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc)
{
int64_t prev = inc;
asm volatile(
MPLOCKED
"xaddq %[prev], %[cnt]"
: [prev] "+r" (prev), /* output */
[cnt] "=m" (v->cnt)
: "m" (v->cnt) /* input */
);
return prev + inc;
}
static inline int64_t
rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec)
{
return rte_atomic64_add_return(v, -dec);
}
static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v)
{
uint8_t ret;
asm volatile(
MPLOCKED
"incq %[cnt] ; "
"sete %[ret]"
: [cnt] "+m" (v->cnt), /* output */
[ret] "=qm" (ret)
);
return ret != 0;
}
static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v)
{
uint8_t ret;
asm volatile(
MPLOCKED
"decq %[cnt] ; "
"sete %[ret]"
: [cnt] "+m" (v->cnt), /* output */
[ret] "=qm" (ret)
);
return ret != 0;
}
static inline int rte_atomic64_test_and_set(rte_atomic64_t *v)
{
return rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, 0, 1);
}
static inline void rte_atomic64_clear(rte_atomic64_t *v)
{
v->cnt = 0;
}
#endif
/*------------------------ 128 bit atomic operations -------------------------*/
enforce experimental tag at beginning of declarations Putting a '__attribute__((deprecated))' in the middle of a function prototype does not result in the expected result with gcc (while clang is fine with this syntax). $ cat deprecated.c void * __attribute__((deprecated)) incorrect() { return 0; } __attribute__((deprecated)) void *correct(void) { return 0; } int main(int argc, char *argv[]) { incorrect(); correct(); return 0; } $ gcc -o deprecated.o -c deprecated.c deprecated.c: In function ‘main’: deprecated.c:3:1: warning: ‘correct’ is deprecated (declared at deprecated.c:2) [-Wdeprecated-declarations] int main(int argc, char *argv[]) { incorrect(); correct(); return 0; } ^ Move the tag on a separate line and make it the first thing of function prototypes. This is not perfect but we will trust reviewers to catch the other not so easy to detect patterns. sed -i \ -e '/^\([^#].*\)\?__rte_experimental */{' \ -e 's//\1/; s/ *$//; i\' \ -e __rte_experimental \ -e '/^$/d}' \ $(git grep -l __rte_experimental -- '*.h') Special mention for rte_mbuf_data_addr_default(): There is either a bug or a (not yet understood) issue with gcc. gcc won't drop this inline when unused and rte_mbuf_data_addr_default() calls rte_mbuf_buf_addr() which itself is experimental. This results in a build warning when not accepting experimental apis from sources just including rte_mbuf.h. For this specific case, we hide the call to rte_mbuf_buf_addr() under the ALLOW_EXPERIMENTAL_API flag. Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com> Signed-off-by: David Marchand <david.marchand@redhat.com>
2019-06-29 13:58:53 +02:00
__rte_experimental
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)
{
RTE_SET_USED(weak);
RTE_SET_USED(success);
RTE_SET_USED(failure);
uint8_t res;
asm volatile (
MPLOCKED
"cmpxchg16b %[dst];"
" sete %[res]"
: [dst] "=m" (dst->val[0]),
"=a" (exp->val[0]),
"=d" (exp->val[1]),
[res] "=r" (res)
: "b" (src->val[0]),
"c" (src->val[1]),
"a" (exp->val[0]),
"d" (exp->val[1]),
"m" (dst->val[0])
: "memory");
return res;
}
#endif /* _RTE_ATOMIC_X86_64_H_ */