atomic.h revision 137222
1129198Scognet/* $NetBSD: atomic.h,v 1.1 2002/10/19 12:22:34 bsh Exp $ */ 2129198Scognet 3129198Scognet/* 4129198Scognet * Copyright (C) 2003-2004 Olivier Houchard 5129198Scognet * Copyright (C) 1994-1997 Mark Brinicombe 6129198Scognet * Copyright (C) 1994 Brini 7129198Scognet * All rights reserved. 8129198Scognet * 9129198Scognet * This code is derived from software written for Brini by Mark Brinicombe 10129198Scognet * 11129198Scognet * Redistribution and use in source and binary forms, with or without 12129198Scognet * modification, are permitted provided that the following conditions 13129198Scognet * are met: 14129198Scognet * 1. Redistributions of source code must retain the above copyright 15129198Scognet * notice, this list of conditions and the following disclaimer. 16129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 17129198Scognet * notice, this list of conditions and the following disclaimer in the 18129198Scognet * documentation and/or other materials provided with the distribution. 19129198Scognet * 3. All advertising materials mentioning features or use of this software 20129198Scognet * must display the following acknowledgement: 21129198Scognet * This product includes software developed by Brini. 22129198Scognet * 4. The name of Brini may not be used to endorse or promote products 23129198Scognet * derived from this software without specific prior written permission. 24129198Scognet * 25129198Scognet * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR 26129198Scognet * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27129198Scognet * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28129198Scognet * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29129198Scognet * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 30129198Scognet * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 31129198Scognet * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32129198Scognet * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 33129198Scognet * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 34129198Scognet * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35129198Scognet * 36129198Scognet * $FreeBSD: head/sys/arm/include/atomic.h 137222 2004-11-04 19:14:50Z cognet $ 37129198Scognet */ 38129198Scognet 39129198Scognet#ifndef _MACHINE_ATOMIC_H_ 40129198Scognet#define _MACHINE_ATOMIC_H_ 41129198Scognet 42129198Scognet 43129198Scognet 44129198Scognet#ifndef _LOCORE 45129198Scognet 46129198Scognet#include <sys/types.h> 47129198Scognet 48129198Scognet#ifndef I32_bit 49129198Scognet#define I32_bit (1 << 7) /* IRQ disable */ 50129198Scognet#endif 51129198Scognet#ifndef F32_bit 52129198Scognet#define F32_bit (1 << 6) /* FIQ disable */ 53129198Scognet#endif 54129198Scognet 55129198Scognet#define __with_interrupts_disabled(expr) \ 56129198Scognet do { \ 57129198Scognet u_int cpsr_save, tmp; \ 58129198Scognet \ 59129198Scognet __asm __volatile( \ 60129198Scognet "mrs %0, cpsr;" \ 61129198Scognet "orr %1, %0, %2;" \ 62129198Scognet "msr cpsr_all, %1;" \ 63129198Scognet : "=r" (cpsr_save), "=r" (tmp) \ 64129198Scognet : "I" (I32_bit) \ 65129198Scognet : "cc" ); \ 66129198Scognet (expr); \ 67129198Scognet __asm __volatile( \ 68129198Scognet "msr cpsr_all, %0" \ 69129198Scognet : /* no output */ \ 70129198Scognet : "r" (cpsr_save) \ 71129198Scognet : "cc" ); \ 72129198Scognet } while(0) 73129198Scognet 74137222Scognetstatic __inline uint32_t 75137222Scognet__swp(uint32_t val, volatile uint32_t *ptr) 76129198Scognet{ 77137222Scognet __asm __volatile("swp %0, %1, [%2]" 78137222Scognet : "=r" (val) : "r" (val) , "r" (ptr) : "memory"); 79137222Scognet return (val); 80129198Scognet} 81129198Scognet 82137222Scognet 83137222Scognet#define atomic_op(v, op, p) ({ \ 84137222Scognet uint32_t e, r, s; \ 85137222Scognet for (e = *(volatile uint32_t *)p;; e = r) { \ 86137222Scognet s = e op v; \ 87137222Scognet r = __swp(s, p); \ 88137222Scognet if (r == e) \ 89137222Scognet break; \ 90137222Scognet } \ 91137222Scognet e; \ 92137222Scognet}) 93129198Scognetstatic __inline void 94137222Scognetatomic_set_32(volatile uint32_t *address, uint32_t setmask) 95129198Scognet{ 96137222Scognet atomic_op(setmask, |, address); 97129198Scognet} 98129198Scognet 99129198Scognetstatic __inline void 100129198Scognetatomic_clear_32(volatile uint32_t *address, uint32_t clearmask) 101129198Scognet{ 102137222Scognet atomic_op(clearmask, &~, address); 103129198Scognet} 104129198Scognet 105129198Scognetstatic __inline int 106137222Scognetatomic_load_32(volatile uint32_t *v) 107129198Scognet{ 108129198Scognet 109137222Scognet return (__swp(*v, v)); 110129198Scognet} 111129198Scognet 112129198Scognetstatic __inline void 113129198Scognetatomic_store_32(volatile uint32_t *dst, uint32_t src) 114129198Scognet{ 115137222Scognet __swp(src, dst); 116129198Scognet} 117129198Scognet 118129198Scognetstatic __inline uint32_t 119129198Scognetatomic_readandclear_32(volatile u_int32_t *p) 120129198Scognet{ 121129198Scognet 122137222Scognet return (__swp(0, p)); 123129198Scognet} 124129198Scognet 125129198Scognetstatic __inline u_int32_t 126129198Scognetatomic_cmpset_32(volatile u_int32_t *p, u_int32_t cmpval, u_int32_t newval) 127129198Scognet{ 128137222Scognet uint32_t r, e; 129137222Scognet 130137222Scognet for (e = *p;; e = r) { 131137222Scognet if (*p == cmpval) { 132137222Scognet r = __swp(newval, p); 133137222Scognet if (r == e) 134137222Scognet return (1); 135137222Scognet } else 136137222Scognet return (0); 137137222Scognet } 138129198Scognet} 139129198Scognet 140129198Scognetstatic __inline void 141129198Scognetatomic_add_32(volatile u_int32_t *p, u_int32_t val) 142129198Scognet{ 143137222Scognet atomic_op(val, +, p); 144129198Scognet} 145129198Scognet 146129198Scognetstatic __inline void 147129198Scognetatomic_subtract_32(volatile u_int32_t *p, u_int32_t val) 148129198Scognet{ 149137222Scognet atomic_op(val, -, p); 150129198Scognet} 151129198Scognet 152137222Scognet#undef __with_interrupts_disabled 153129198Scognet 154137222Scognet#endif /* _LOCORE */ 155129198Scognet 156129198Scognet 157137222Scognet#define atomic_set_rel_int atomic_set_32 158137222Scognet#define atomic_set_int atomic_set_32 159137222Scognet#define atomic_readandclear_int atomic_readandclear_32 160137222Scognet#define atomic_clear_int atomic_clear_32 161137222Scognet#define atomic_subtract_int atomic_subtract_32 162137222Scognet#define atomic_subtract_rel_int atomic_subtract_32 163137222Scognet#define atomic_subtract_acq_int atomic_subtract_32 164137222Scognet#define atomic_add_int atomic_add_32 165137222Scognet#define atomic_add_rel_int atomic_add_32 166137222Scognet#define atomic_add_acq_int atomic_add_32 167137222Scognet#define atomic_cmpset_int atomic_cmpset_32 168137222Scognet#define atomic_cmpset_rel_int atomic_cmpset_32 169137222Scognet#define atomic_cmpset_rel_ptr atomic_cmpset_ptr 170137222Scognet#define atomic_cmpset_acq_int atomic_cmpset_32 171137222Scognet#define atomic_cmpset_acq_ptr atomic_cmpset_ptr 172137222Scognet#define atomic_store_rel_ptr atomic_store_ptr 173137222Scognet#define atomic_store_rel_int atomic_store_32 174137222Scognet#define atomic_cmpset_rel_32 atomic_cmpset_32 175137222Scognet#define atomic_smpset_rel_ptr atomic_cmpset_ptr 176137222Scognet#define atomic_load_acq_int atomic_load_32 177137222Scognet#define atomic_clear_ptr(ptr, bit) atomic_clear_32( \ 178137222Scognet (volatile uint32_t *)ptr, (uint32_t)bit) 179137222Scognet#define atomic_store_ptr(ptr, bit) atomic_store_32( \ 180137222Scognet (volatile uint32_t *)ptr, (uint32_t)bit) 181137222Scognet#define atomic_cmpset_ptr(dst, exp, s) atomic_cmpset_32( \ 182137222Scognet (volatile uint32_t *)dst, (uint32_t)exp, (uint32_t)s) 183137222Scognet#define atomic_set_ptr(ptr, src) atomic_set_32( \ 184137222Scognet (volatile uint32_t *)ptr, (uint32_t)src) 185129198Scognet 186129198Scognet#endif /* _MACHINE_ATOMIC_H_ */ 187