From 5b296f846d13196c8f82db291fcadd9dd89d7121 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Thu, 26 Jun 2008 23:06:52 +0000 Subject: [PATCH] Add additional atomic ops from FreeBSD. Obtained-from: FreeBSD --- sys/cpu/i386/include/atomic.h | 163 +++++++++++++++++++++++++++++++++- sys/sys/limits.h | 38 ++++++++ sys/sys/refcount.h | 57 ++++++++++++ 3 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 sys/sys/limits.h create mode 100644 sys/sys/refcount.h diff --git a/sys/cpu/i386/include/atomic.h b/sys/cpu/i386/include/atomic.h index fbc5f36a56..e05d664250 100644 --- a/sys/cpu/i386/include/atomic.h +++ b/sys/cpu/i386/include/atomic.h @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/include/atomic.h,v 1.9.2.1 2000/07/07 00:38:47 obrien Exp $ - * $DragonFly: src/sys/cpu/i386/include/atomic.h,v 1.24 2007/11/07 17:42:50 dillon Exp $ + * $DragonFly: src/sys/cpu/i386/include/atomic.h,v 1.25 2008/06/26 23:06:50 dillon Exp $ */ #ifndef _CPU_ATOMIC_H_ #define _CPU_ATOMIC_H_ @@ -346,8 +346,13 @@ atomic_intr_cond_exit(__atomic_intr_t *p, void (*func)(void *), void *arg) * Returns 0 on failure, non-zero on success */ #if defined(KLD_MODULE) + extern int atomic_cmpset_int(volatile u_int *_dst, u_int _old, u_int _new); +extern int atomic_cmpset_long(volatile u_long *dst, u_long exp, u_long src); +extern u_int atomic_fetchadd_int(volatile u_int *p, u_int v); + #else + static __inline int atomic_cmpset_int(volatile u_int *_dst, u_int _old, u_int _new) { @@ -361,6 +366,162 @@ atomic_cmpset_int(volatile u_int *_dst, u_int _old, u_int _new) : "memory"); return res; } + +static __inline int +atomic_cmpset_long(volatile u_long *dst, u_long exp, u_long src) +{ + return (atomic_cmpset_int((volatile u_int *)dst, (u_int)exp, + (u_int)src)); +} + +/* + * Atomically add the value of v to the integer pointed to by p and return + * the previous value of *p. + */ +static __inline u_int +atomic_fetchadd_int(volatile u_int *p, u_int v) +{ + __asm __volatile(MPLOCKED "xaddl %0,%1; " \ + : "+r" (v), "=m" (*p) \ + : "m" (*p) \ + : "memory"); + return (v); +} + #endif /* KLD_MODULE */ +/* Acquire and release variants are identical to the normal ones. */ +#define atomic_set_acq_char atomic_set_char +#define atomic_set_rel_char atomic_set_char +#define atomic_clear_acq_char atomic_clear_char +#define atomic_clear_rel_char atomic_clear_char +#define atomic_add_acq_char atomic_add_char +#define atomic_add_rel_char atomic_add_char +#define atomic_subtract_acq_char atomic_subtract_char +#define atomic_subtract_rel_char atomic_subtract_char + +#define atomic_set_acq_short atomic_set_short +#define atomic_set_rel_short atomic_set_short +#define atomic_clear_acq_short atomic_clear_short +#define atomic_clear_rel_short atomic_clear_short +#define atomic_add_acq_short atomic_add_short +#define atomic_add_rel_short atomic_add_short +#define atomic_subtract_acq_short atomic_subtract_short +#define atomic_subtract_rel_short atomic_subtract_short + +#define atomic_set_acq_int atomic_set_int +#define atomic_set_rel_int atomic_set_int +#define atomic_clear_acq_int atomic_clear_int +#define atomic_clear_rel_int atomic_clear_int +#define atomic_add_acq_int atomic_add_int +#define atomic_add_rel_int atomic_add_int +#define atomic_subtract_acq_int atomic_subtract_int +#define atomic_subtract_rel_int atomic_subtract_int +#define atomic_cmpset_acq_int atomic_cmpset_int +#define atomic_cmpset_rel_int atomic_cmpset_int + +#define atomic_set_acq_long atomic_set_long +#define atomic_set_rel_long atomic_set_long +#define atomic_clear_acq_long atomic_clear_long +#define atomic_clear_rel_long atomic_clear_long +#define atomic_add_acq_long atomic_add_long +#define atomic_add_rel_long atomic_add_long +#define atomic_subtract_acq_long atomic_subtract_long +#define atomic_subtract_rel_long atomic_subtract_long +#define atomic_cmpset_acq_long atomic_cmpset_long +#define atomic_cmpset_rel_long atomic_cmpset_long + +/* Operations on 8-bit bytes. */ +#define atomic_set_8 atomic_set_char +#define atomic_set_acq_8 atomic_set_acq_char +#define atomic_set_rel_8 atomic_set_rel_char +#define atomic_clear_8 atomic_clear_char +#define atomic_clear_acq_8 atomic_clear_acq_char +#define atomic_clear_rel_8 atomic_clear_rel_char +#define atomic_add_8 atomic_add_char +#define atomic_add_acq_8 atomic_add_acq_char +#define atomic_add_rel_8 atomic_add_rel_char +#define atomic_subtract_8 atomic_subtract_char +#define atomic_subtract_acq_8 atomic_subtract_acq_char +#define atomic_subtract_rel_8 atomic_subtract_rel_char +#define atomic_load_acq_8 atomic_load_acq_char +#define atomic_store_rel_8 atomic_store_rel_char + +/* Operations on 16-bit words. */ +#define atomic_set_16 atomic_set_short +#define atomic_set_acq_16 atomic_set_acq_short +#define atomic_set_rel_16 atomic_set_rel_short +#define atomic_clear_16 atomic_clear_short +#define atomic_clear_acq_16 atomic_clear_acq_short +#define atomic_clear_rel_16 atomic_clear_rel_short +#define atomic_add_16 atomic_add_short +#define atomic_add_acq_16 atomic_add_acq_short +#define atomic_add_rel_16 atomic_add_rel_short +#define atomic_subtract_16 atomic_subtract_short +#define atomic_subtract_acq_16 atomic_subtract_acq_short +#define atomic_subtract_rel_16 atomic_subtract_rel_short +#define atomic_load_acq_16 atomic_load_acq_short +#define atomic_store_rel_16 atomic_store_rel_short + +/* Operations on 32-bit double words. */ +#define atomic_set_32 atomic_set_int +#define atomic_set_acq_32 atomic_set_acq_int +#define atomic_set_rel_32 atomic_set_rel_int +#define atomic_clear_32 atomic_clear_int +#define atomic_clear_acq_32 atomic_clear_acq_int +#define atomic_clear_rel_32 atomic_clear_rel_int +#define atomic_add_32 atomic_add_int +#define atomic_add_acq_32 atomic_add_acq_int +#define atomic_add_rel_32 atomic_add_rel_int +#define atomic_subtract_32 atomic_subtract_int +#define atomic_subtract_acq_32 atomic_subtract_acq_int +#define atomic_subtract_rel_32 atomic_subtract_rel_int +#define atomic_load_acq_32 atomic_load_acq_int +#define atomic_store_rel_32 atomic_store_rel_int +#define atomic_cmpset_32 atomic_cmpset_int +#define atomic_cmpset_acq_32 atomic_cmpset_acq_int +#define atomic_cmpset_rel_32 atomic_cmpset_rel_int +#define atomic_readandclear_32 atomic_readandclear_int +#define atomic_fetchadd_32 atomic_fetchadd_int + +/* Operations on pointers. */ +#define atomic_set_ptr(p, v) \ + atomic_set_int((volatile u_int *)(p), (u_int)(v)) +#define atomic_set_acq_ptr(p, v) \ + atomic_set_acq_int((volatile u_int *)(p), (u_int)(v)) +#define atomic_set_rel_ptr(p, v) \ + atomic_set_rel_int((volatile u_int *)(p), (u_int)(v)) +#define atomic_clear_ptr(p, v) \ + atomic_clear_int((volatile u_int *)(p), (u_int)(v)) +#define atomic_clear_acq_ptr(p, v) \ + atomic_clear_acq_int((volatile u_int *)(p), (u_int)(v)) +#define atomic_clear_rel_ptr(p, v) \ + atomic_clear_rel_int((volatile u_int *)(p), (u_int)(v)) +#define atomic_add_ptr(p, v) \ + atomic_add_int((volatile u_int *)(p), (u_int)(v)) +#define atomic_add_acq_ptr(p, v) \ + atomic_add_acq_int((volatile u_int *)(p), (u_int)(v)) +#define atomic_add_rel_ptr(p, v) \ + atomic_add_rel_int((volatile u_int *)(p), (u_int)(v)) +#define atomic_subtract_ptr(p, v) \ + atomic_subtract_int((volatile u_int *)(p), (u_int)(v)) +#define atomic_subtract_acq_ptr(p, v) \ + atomic_subtract_acq_int((volatile u_int *)(p), (u_int)(v)) +#define atomic_subtract_rel_ptr(p, v) \ + atomic_subtract_rel_int((volatile u_int *)(p), (u_int)(v)) +#define atomic_load_acq_ptr(p) \ + atomic_load_acq_int((volatile u_int *)(p)) +#define atomic_store_rel_ptr(p, v) \ + atomic_store_rel_int((volatile u_int *)(p), (v)) +#define atomic_cmpset_ptr(dst, old, new) \ + atomic_cmpset_int((volatile u_int *)(dst), (u_int)(old), (u_int)(new)) +#define atomic_cmpset_acq_ptr(dst, old, new) \ + atomic_cmpset_acq_int((volatile u_int *)(dst), (u_int)(old), \ + (u_int)(new)) +#define atomic_cmpset_rel_ptr(dst, old, new) \ + atomic_cmpset_rel_int((volatile u_int *)(dst), (u_int)(old), \ + (u_int)(new)) +#define atomic_readandclear_ptr(p) \ + atomic_readandclear_int((volatile u_int *)(p)) + #endif /* ! _CPU_ATOMIC_H_ */ diff --git a/sys/sys/limits.h b/sys/sys/limits.h new file mode 100644 index 0000000000..3ddda63c3f --- /dev/null +++ b/sys/sys/limits.h @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/limits.h,v 1.10 2005/12/02 07:45:28 davidxu Exp $ + * $DragonFly: src/sys/sys/limits.h,v 1.1 2008/06/26 23:06:52 dillon Exp $ + */ + +#ifndef _SYS_LIMITS_H_ +#define _SYS_LIMITS_H_ + +#include + +#endif /* !_SYS_LIMITS_H_ */ diff --git a/sys/sys/refcount.h b/sys/sys/refcount.h new file mode 100644 index 0000000000..33cf35f1d0 --- /dev/null +++ b/sys/sys/refcount.h @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 2005 John Baldwin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/refcount.h,v 1.1 2005/09/27 18:01:33 jhb Exp $ + * $DragonFly: src/sys/sys/refcount.h,v 1.1 2008/06/26 23:06:52 dillon Exp $ + */ + +#ifndef __SYS_REFCOUNT_H__ +#define __SYS_REFCOUNT_H__ + +#include + +static __inline void +refcount_init(volatile u_int *count, u_int value) +{ + *count = value; +} + +static __inline void +refcount_acquire(volatile u_int *count) +{ + atomic_add_acq_int(count, 1); +} + +static __inline int +refcount_release(volatile u_int *count) +{ + /* XXX: Should this have a rel membar? */ + return (atomic_fetchadd_int(count, -1) == 1); +} + +#endif /* ! __SYS_REFCOUNT_H__ */ -- 2.41.0