18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef __TOOLS_ASM_GENERIC_ATOMIC_H
38c2ecf20Sopenharmony_ci#define __TOOLS_ASM_GENERIC_ATOMIC_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/compiler.h>
68c2ecf20Sopenharmony_ci#include <linux/types.h>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci/*
98c2ecf20Sopenharmony_ci * Atomic operations that C can't guarantee us.  Useful for
108c2ecf20Sopenharmony_ci * resource counting etc..
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * Excerpts obtained from the Linux kernel sources.
138c2ecf20Sopenharmony_ci */
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#define ATOMIC_INIT(i)	{ (i) }
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/**
188c2ecf20Sopenharmony_ci * atomic_read - read atomic variable
198c2ecf20Sopenharmony_ci * @v: pointer of type atomic_t
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * Atomically reads the value of @v.
228c2ecf20Sopenharmony_ci */
238c2ecf20Sopenharmony_cistatic inline int atomic_read(const atomic_t *v)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	return READ_ONCE((v)->counter);
268c2ecf20Sopenharmony_ci}
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/**
298c2ecf20Sopenharmony_ci * atomic_set - set atomic variable
308c2ecf20Sopenharmony_ci * @v: pointer of type atomic_t
318c2ecf20Sopenharmony_ci * @i: required value
328c2ecf20Sopenharmony_ci *
338c2ecf20Sopenharmony_ci * Atomically sets the value of @v to @i.
348c2ecf20Sopenharmony_ci */
358c2ecf20Sopenharmony_cistatic inline void atomic_set(atomic_t *v, int i)
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci        v->counter = i;
388c2ecf20Sopenharmony_ci}
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci/**
418c2ecf20Sopenharmony_ci * atomic_inc - increment atomic variable
428c2ecf20Sopenharmony_ci * @v: pointer of type atomic_t
438c2ecf20Sopenharmony_ci *
448c2ecf20Sopenharmony_ci * Atomically increments @v by 1.
458c2ecf20Sopenharmony_ci */
468c2ecf20Sopenharmony_cistatic inline void atomic_inc(atomic_t *v)
478c2ecf20Sopenharmony_ci{
488c2ecf20Sopenharmony_ci	__sync_add_and_fetch(&v->counter, 1);
498c2ecf20Sopenharmony_ci}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci/**
528c2ecf20Sopenharmony_ci * atomic_dec_and_test - decrement and test
538c2ecf20Sopenharmony_ci * @v: pointer of type atomic_t
548c2ecf20Sopenharmony_ci *
558c2ecf20Sopenharmony_ci * Atomically decrements @v by 1 and
568c2ecf20Sopenharmony_ci * returns true if the result is 0, or false for all other
578c2ecf20Sopenharmony_ci * cases.
588c2ecf20Sopenharmony_ci */
598c2ecf20Sopenharmony_cistatic inline int atomic_dec_and_test(atomic_t *v)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	return __sync_sub_and_fetch(&v->counter, 1) == 0;
628c2ecf20Sopenharmony_ci}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci#define cmpxchg(ptr, oldval, newval) \
658c2ecf20Sopenharmony_ci	__sync_val_compare_and_swap(ptr, oldval, newval)
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistatic inline int atomic_cmpxchg(atomic_t *v, int oldval, int newval)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	return cmpxchg(&(v)->counter, oldval, newval);
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci#endif /* __TOOLS_ASM_GENERIC_ATOMIC_H */
73