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