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