18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _ASM_GENERIC_LOCAL64_H
38c2ecf20Sopenharmony_ci#define _ASM_GENERIC_LOCAL64_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/percpu.h>
68c2ecf20Sopenharmony_ci#include <asm/types.h>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci/*
98c2ecf20Sopenharmony_ci * A signed long type for operations which are atomic for a single CPU.
108c2ecf20Sopenharmony_ci * Usually used in combination with per-cpu variables.
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * This is the default implementation, which uses atomic64_t.  Which is
138c2ecf20Sopenharmony_ci * rather pointless.  The whole point behind local64_t is that some processors
148c2ecf20Sopenharmony_ci * can perform atomic adds and subtracts in a manner which is atomic wrt IRQs
158c2ecf20Sopenharmony_ci * running on this CPU.  local64_t allows exploitation of such capabilities.
168c2ecf20Sopenharmony_ci */
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/* Implement in terms of atomics. */
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#if BITS_PER_LONG == 64
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include <asm/local.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_citypedef struct {
258c2ecf20Sopenharmony_ci	local_t a;
268c2ecf20Sopenharmony_ci} local64_t;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#define LOCAL64_INIT(i)	{ LOCAL_INIT(i) }
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define local64_read(l)		local_read(&(l)->a)
318c2ecf20Sopenharmony_ci#define local64_set(l,i)	local_set((&(l)->a),(i))
328c2ecf20Sopenharmony_ci#define local64_inc(l)		local_inc(&(l)->a)
338c2ecf20Sopenharmony_ci#define local64_dec(l)		local_dec(&(l)->a)
348c2ecf20Sopenharmony_ci#define local64_add(i,l)	local_add((i),(&(l)->a))
358c2ecf20Sopenharmony_ci#define local64_sub(i,l)	local_sub((i),(&(l)->a))
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#define local64_sub_and_test(i, l) local_sub_and_test((i), (&(l)->a))
388c2ecf20Sopenharmony_ci#define local64_dec_and_test(l) local_dec_and_test(&(l)->a)
398c2ecf20Sopenharmony_ci#define local64_inc_and_test(l) local_inc_and_test(&(l)->a)
408c2ecf20Sopenharmony_ci#define local64_add_negative(i, l) local_add_negative((i), (&(l)->a))
418c2ecf20Sopenharmony_ci#define local64_add_return(i, l) local_add_return((i), (&(l)->a))
428c2ecf20Sopenharmony_ci#define local64_sub_return(i, l) local_sub_return((i), (&(l)->a))
438c2ecf20Sopenharmony_ci#define local64_inc_return(l)	local_inc_return(&(l)->a)
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#define local64_cmpxchg(l, o, n) local_cmpxchg((&(l)->a), (o), (n))
468c2ecf20Sopenharmony_ci#define local64_xchg(l, n)	local_xchg((&(l)->a), (n))
478c2ecf20Sopenharmony_ci#define local64_add_unless(l, _a, u) local_add_unless((&(l)->a), (_a), (u))
488c2ecf20Sopenharmony_ci#define local64_inc_not_zero(l)	local_inc_not_zero(&(l)->a)
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci/* Non-atomic variants, ie. preemption disabled and won't be touched
518c2ecf20Sopenharmony_ci * in interrupt, etc.  Some archs can optimize this case well. */
528c2ecf20Sopenharmony_ci#define __local64_inc(l)	local64_set((l), local64_read(l) + 1)
538c2ecf20Sopenharmony_ci#define __local64_dec(l)	local64_set((l), local64_read(l) - 1)
548c2ecf20Sopenharmony_ci#define __local64_add(i,l)	local64_set((l), local64_read(l) + (i))
558c2ecf20Sopenharmony_ci#define __local64_sub(i,l)	local64_set((l), local64_read(l) - (i))
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#else /* BITS_PER_LONG != 64 */
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#include <linux/atomic.h>
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/* Don't use typedef: don't want them to be mixed with atomic_t's. */
628c2ecf20Sopenharmony_citypedef struct {
638c2ecf20Sopenharmony_ci	atomic64_t a;
648c2ecf20Sopenharmony_ci} local64_t;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci#define LOCAL64_INIT(i)	{ ATOMIC_LONG_INIT(i) }
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci#define local64_read(l)		atomic64_read(&(l)->a)
698c2ecf20Sopenharmony_ci#define local64_set(l,i)	atomic64_set((&(l)->a),(i))
708c2ecf20Sopenharmony_ci#define local64_inc(l)		atomic64_inc(&(l)->a)
718c2ecf20Sopenharmony_ci#define local64_dec(l)		atomic64_dec(&(l)->a)
728c2ecf20Sopenharmony_ci#define local64_add(i,l)	atomic64_add((i),(&(l)->a))
738c2ecf20Sopenharmony_ci#define local64_sub(i,l)	atomic64_sub((i),(&(l)->a))
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci#define local64_sub_and_test(i, l) atomic64_sub_and_test((i), (&(l)->a))
768c2ecf20Sopenharmony_ci#define local64_dec_and_test(l) atomic64_dec_and_test(&(l)->a)
778c2ecf20Sopenharmony_ci#define local64_inc_and_test(l) atomic64_inc_and_test(&(l)->a)
788c2ecf20Sopenharmony_ci#define local64_add_negative(i, l) atomic64_add_negative((i), (&(l)->a))
798c2ecf20Sopenharmony_ci#define local64_add_return(i, l) atomic64_add_return((i), (&(l)->a))
808c2ecf20Sopenharmony_ci#define local64_sub_return(i, l) atomic64_sub_return((i), (&(l)->a))
818c2ecf20Sopenharmony_ci#define local64_inc_return(l)	atomic64_inc_return(&(l)->a)
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci#define local64_cmpxchg(l, o, n) atomic64_cmpxchg((&(l)->a), (o), (n))
848c2ecf20Sopenharmony_ci#define local64_xchg(l, n)	atomic64_xchg((&(l)->a), (n))
858c2ecf20Sopenharmony_ci#define local64_add_unless(l, _a, u) atomic64_add_unless((&(l)->a), (_a), (u))
868c2ecf20Sopenharmony_ci#define local64_inc_not_zero(l)	atomic64_inc_not_zero(&(l)->a)
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/* Non-atomic variants, ie. preemption disabled and won't be touched
898c2ecf20Sopenharmony_ci * in interrupt, etc.  Some archs can optimize this case well. */
908c2ecf20Sopenharmony_ci#define __local64_inc(l)	local64_set((l), local64_read(l) + 1)
918c2ecf20Sopenharmony_ci#define __local64_dec(l)	local64_set((l), local64_read(l) - 1)
928c2ecf20Sopenharmony_ci#define __local64_add(i,l)	local64_set((l), local64_read(l) + (i))
938c2ecf20Sopenharmony_ci#define __local64_sub(i,l)	local64_set((l), local64_read(l) - (i))
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci#endif /* BITS_PER_LONG != 64 */
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci#endif /* _ASM_GENERIC_LOCAL64_H */
98