genode/repos/dde_linux/src/include/lx_emul/atomic.h

112 lines
3.2 KiB
C

/*
* \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 <asm-generic/atomic64.h>
#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)