/* * \brief Linux kernel API * \author Norman Feske * \author Sebastian Sumpf * \author Josef Soentgen * \date 2014-08-21 * * Based on the prototypes found in the Linux kernel's 'include/'. */ /* * Copyright (C) 2014 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ /******************* ** asm/cmpxchg.h ** *******************/ #define cmpxchg(ptr, o, n) ({ \ typeof(*ptr) prev = *ptr; \ *ptr = (*ptr == o) ? n : *ptr; \ prev;\ }) #define xchg(ptr, x) ({ \ typeof(*ptr) old = *ptr; \ *ptr = x; \ old; \ }) #define atomic_xchg(ptr, v) (xchg(&(ptr)->counter, (v))) /****************** ** asm/atomic.h ** ******************/ #include #define ATOMIC_INIT(i) { (i) } typedef struct atomic { long counter; } atomic_t; typedef atomic_t atomic_long_t; static inline int atomic_read(const atomic_t *p) { return p->counter; } static inline void atomic_set(atomic_t *p, int i) { p->counter = i; } static inline void atomic_sub(int i, atomic_t *p) { p->counter -= i; } static inline void atomic_add(int i, atomic_t *p) { p->counter += i; } static inline int atomic_sub_return(int i, atomic_t *p) { p->counter -= i; return p->counter; } static inline int atomic_add_return(int i, atomic_t *p) { p->counter += i; return p->counter; } static inline int atomic_sub_and_test(int i, atomic_t *p) { return atomic_sub_return(i, p) == 0; } static inline void atomic_dec(atomic_t *p) { atomic_sub(1, p); } static inline void atomic_inc(atomic_t *p) { atomic_add(1, p); } static inline int atomic_dec_return(atomic_t *p) { return atomic_sub_return(1, p); } static inline int atomic_inc_return(atomic_t *p) { return atomic_add_return(1, p); } static inline int atomic_dec_and_test(atomic_t *p) { return atomic_sub_and_test(1, p); } static inline int atomic_inc_not_zero(atomic_t *p) { return p->counter ? atomic_inc_return(p) : 0; } static inline void atomic_long_inc(atomic_long_t *p) { atomic_add(1, p); } static inline void atomic_long_sub(int i, atomic_long_t *p) { atomic_sub(i, p); } static inline long atomic_long_add_return(long i, atomic_long_t *p) { return atomic_add_return(i, p); } static inline long atomic_long_read(atomic_long_t *p) { return atomic_read(p); } static inline int atomic_cmpxchg(atomic_t *v, int old, int n) { return cmpxchg(&v->counter, old, n); } static inline int atomic_inc_not_zero_hint(atomic_t *v, int hint) { int val, c = hint; /* sanity test, should be removed by compiler if hint is a constant */ if (!hint) return atomic_inc_not_zero(v); do { val = atomic_cmpxchg(v, c, c + 1); if (val == c) return 1; c = val; } while (c); return 0; } static inline int atomic_add_unless(atomic_t *v, int a, int u) { int ret; unsigned long flags; (void)flags; ret = v->counter; if (ret != u) v->counter += a; return ret != u; } #define smp_mb__before_atomic_dec() /******************************* ** asm-generic/atomic-long.h ** *******************************/ #define ATOMIC_LONG_INIT(i) ATOMIC_INIT(i)