atomic-v6.h revision 129198
187866Ssheldonh/* $NetBSD: atomic.h,v 1.1 2002/10/19 12:22:34 bsh Exp $ */
295267Ssheldonh
387866Ssheldonh/*
487866Ssheldonh * Copyright (C) 2003-2004 Olivier Houchard
587866Ssheldonh * Copyright (C) 1994-1997 Mark Brinicombe
687866Ssheldonh * Copyright (C) 1994 Brini
787866Ssheldonh * All rights reserved.
887866Ssheldonh *
987866Ssheldonh * This code is derived from software written for Brini by Mark Brinicombe
1087866Ssheldonh *
1187866Ssheldonh * Redistribution and use in source and binary forms, with or without
1287866Ssheldonh * modification, are permitted provided that the following conditions
1387866Ssheldonh * are met:
1487866Ssheldonh * 1. Redistributions of source code must retain the above copyright
1587866Ssheldonh *    notice, this list of conditions and the following disclaimer.
1687866Ssheldonh * 2. Redistributions in binary form must reproduce the above copyright
1787866Ssheldonh *    notice, this list of conditions and the following disclaimer in the
1887866Ssheldonh *    documentation and/or other materials provided with the distribution.
1987866Ssheldonh * 3. All advertising materials mentioning features or use of this software
2087866Ssheldonh *    must display the following acknowledgement:
2187866Ssheldonh *	This product includes software developed by Brini.
2287866Ssheldonh * 4. The name of Brini may not be used to endorse or promote products
2387866Ssheldonh *    derived from this software without specific prior written permission.
2487866Ssheldonh *
2587866Ssheldonh * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR
2687866Ssheldonh * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2787866Ssheldonh * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2887866Ssheldonh * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2987866Ssheldonh * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
3087866Ssheldonh * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
3187866Ssheldonh * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
3295267Ssheldonh * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33113396Stjr * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3487866Ssheldonh * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3587866Ssheldonh *
3687866Ssheldonh * $FreeBSD: head/sys/arm/include/atomic.h 129198 2004-05-14 11:46:45Z cognet $
3787866Ssheldonh */
3887866Ssheldonh
3987866Ssheldonh#ifndef	_MACHINE_ATOMIC_H_
4087866Ssheldonh#define	_MACHINE_ATOMIC_H_
4187866Ssheldonh
4287866Ssheldonh
4387866Ssheldonh
4487866Ssheldonh#ifndef _LOCORE
4587866Ssheldonh
4687866Ssheldonh#include <sys/types.h>
4787866Ssheldonh
4887866Ssheldonh#ifndef I32_bit
4987866Ssheldonh#define I32_bit (1 << 7)        /* IRQ disable */
5087866Ssheldonh#endif
5187866Ssheldonh#ifndef F32_bit
5287866Ssheldonh#define F32_bit (1 << 6)        /* FIQ disable */
5387866Ssheldonh#endif
5487866Ssheldonh
5587866Ssheldonh#define __with_interrupts_disabled(expr) \
5687866Ssheldonh	do {						\
5787866Ssheldonh		u_int cpsr_save, tmp;			\
5887866Ssheldonh							\
5987866Ssheldonh		__asm __volatile(			\
6087866Ssheldonh			"mrs  %0, cpsr;"		\
6187866Ssheldonh			"orr  %1, %0, %2;"		\
6287866Ssheldonh			"msr  cpsr_all, %1;"		\
6387866Ssheldonh			: "=r" (cpsr_save), "=r" (tmp)	\
6487866Ssheldonh			: "I" (I32_bit)		\
6587866Ssheldonh		        : "cc" );		\
6687866Ssheldonh		(expr);				\
6787866Ssheldonh		 __asm __volatile(		\
6895267Ssheldonh			"msr  cpsr_all, %0"	\
6987866Ssheldonh			: /* no output */	\
7095267Ssheldonh			: "r" (cpsr_save)	\
7187866Ssheldonh			: "cc" );		\
7287866Ssheldonh	} while(0)
7387866Ssheldonh
7487866Ssheldonhstatic __inline void
7587866Ssheldonhatomic_set_32(volatile uint32_t *address, uint32_t setmask)
7687866Ssheldonh{
7787866Ssheldonh	__with_interrupts_disabled( *address |= setmask);
7887866Ssheldonh}
7987866Ssheldonh
8087866Ssheldonhstatic __inline void
8187866Ssheldonhatomic_set_ptr(volatile void *ptr, uint32_t src)
8287866Ssheldonh{
8387866Ssheldonh	atomic_set_32((volatile uint32_t *)ptr, (uint32_t)src);
8487866Ssheldonh}
8587866Ssheldonh
8687866Ssheldonh#define atomic_set_rel_int atomic_set_32
8787866Ssheldonh#define atomic_set_int atomic_set_32
8887866Ssheldonh#define atomic_readandclear_int atomic_readandclear_32
8987866Ssheldonhstatic __inline void
9087866Ssheldonhatomic_clear_32(volatile uint32_t *address, uint32_t clearmask)
9187866Ssheldonh{
9287866Ssheldonh	__with_interrupts_disabled( *address &= ~clearmask);
9387866Ssheldonh}
9487866Ssheldonh
9587866Ssheldonhstatic __inline void
9687866Ssheldonhatomic_clear_ptr(volatile void *ptr, uint32_t src)
9787866Ssheldonh{
9895267Ssheldonh	atomic_clear_32((volatile uint32_t *)ptr, (uint32_t)src);
9995267Ssheldonh}
10095267Ssheldonh
10195267Ssheldonhstatic __inline int
10295267Ssheldonhatomic_load_acq_int(volatile uint32_t *v)
10395267Ssheldonh{
10495267Ssheldonh	int bla;
10595267Ssheldonh
10687866Ssheldonh	__with_interrupts_disabled(bla = *v);
10787866Ssheldonh	return (bla);
10887866Ssheldonh}
10987866Ssheldonh
11087866Ssheldonh#define atomic_clear_int atomic_clear_32
11187866Ssheldonhstatic __inline void
11287866Ssheldonhatomic_store_32(volatile uint32_t *dst, uint32_t src)
11387866Ssheldonh{
11487866Ssheldonh	__with_interrupts_disabled(*dst = src);
11587866Ssheldonh}
11687866Ssheldonh
11787866Ssheldonhstatic __inline void
11887866Ssheldonhatomic_store_ptr(volatile void *dst, void *src)
11987866Ssheldonh{
12087866Ssheldonh	atomic_store_32((volatile uint32_t *)dst, (uint32_t) src);
12187866Ssheldonh}
12287866Ssheldonh
12387866Ssheldonh#define atomic_store_rel_ptr atomic_store_ptr
12487866Ssheldonh#define atomic_store_rel_int atomic_store_32
12587866Ssheldonh
12687866Ssheldonhstatic __inline uint32_t
12787866Ssheldonhatomic_readandclear_32(volatile u_int32_t *p)
12887866Ssheldonh{
12987866Ssheldonh	uint32_t ret;
13087866Ssheldonh
13187866Ssheldonh	__with_interrupts_disabled((ret = *p) != 0 ? *p = 0 : 0);
13287866Ssheldonh	return (ret);
13387866Ssheldonh}
13487866Ssheldonh
13587866Ssheldonhstatic __inline u_int32_t
13687866Ssheldonhatomic_cmpset_32(volatile u_int32_t *p, u_int32_t cmpval, u_int32_t newval)
13787866Ssheldonh{
13887866Ssheldonh	int done = 0;
13987866Ssheldonh	__with_interrupts_disabled(*p = (*p == cmpval ? newval + done++ : *p));
14087866Ssheldonh	return (done);
14187866Ssheldonh}
14287866Ssheldonh
14387866Ssheldonhstatic __inline void
14487866Ssheldonhatomic_add_32(volatile u_int32_t *p, u_int32_t val)
14587866Ssheldonh{
14687866Ssheldonh	__with_interrupts_disabled(*p += val);
14787866Ssheldonh}
14887866Ssheldonh
14987866Ssheldonhstatic __inline void
15087866Ssheldonhatomic_subtract_32(volatile u_int32_t *p, u_int32_t val)
15187866Ssheldonh{
15287866Ssheldonh	__with_interrupts_disabled(*p -= val);
15387866Ssheldonh}
15487866Ssheldonh
15587866Ssheldonh#define atomic_subtract_int atomic_subtract_32
15687866Ssheldonh#define atomic_subtract_rel_int atomic_subtract_32
15787866Ssheldonh#define atomic_subtract_acq_int atomic_subtract_32
15887866Ssheldonh#define atomic_add_int atomic_add_32
15987866Ssheldonh#define atomic_add_rel_int atomic_add_32
16087866Ssheldonh#define atomic_add_acq_int atomic_add_32
16187866Ssheldonh#define atomic_cmpset_int atomic_cmpset_32
16287866Ssheldonh#define atomic_cmpset_rel_int atomic_cmpset_32
16387866Ssheldonh#define atomic_cmpset_acq_int atomic_cmpset_32
16487866Ssheldonh
16587866Ssheldonhstatic __inline u_int32_t
16687866Ssheldonhatomic_cmpset_ptr(volatile void *dst, void *exp, void *src)
16787866Ssheldonh{
16887866Ssheldonh	return (atomic_cmpset_32((volatile u_int32_t *)dst, (u_int32_t)exp,
16987866Ssheldonh                (u_int32_t)src));
17087866Ssheldonh}
17187866Ssheldonh
17287866Ssheldonhstatic __inline u_int32_t
17387866Ssheldonhatomic_cmpset_rel_32(volatile u_int32_t *p, u_int32_t cmpval, u_int32_t newval)
17487866Ssheldonh{
17587866Ssheldonh	return (atomic_cmpset_32(p, cmpval, newval));
17687866Ssheldonh}
17787866Ssheldonh
17887866Ssheldonhstatic __inline u_int32_t
17987866Ssheldonhatomic_cmpset_rel_ptr(volatile void *dst, void *exp, void *src)
18087866Ssheldonh{
18187866Ssheldonh	return (atomic_cmpset_32((volatile u_int32_t *)dst,
18287866Ssheldonh	    (u_int32_t)exp, (u_int32_t)src));
18387866Ssheldonh}
18487866Ssheldonh
18587866Ssheldonh#define atomic_cmpset_acq_ptr atomic_cmpset_ptr
18687866Ssheldonh
18787866Ssheldonh#if !defined(ATOMIC_SET_BIT_NOINLINE)
18887866Ssheldonh
18987866Ssheldonh#define atomic_set_bit(a,m)   atomic_set_32(a,m)
19087866Ssheldonh#define atomic_clear_bit(a,m) atomic_clear_32(a,m)
19187866Ssheldonh
19287866Ssheldonh#endif
19387866Ssheldonh
19487866Ssheldonh#undef __with_interrupts_disabled
19587866Ssheldonh
19687866Ssheldonh#endif /* _LOCORE */
19787866Ssheldonh#endif /* _MACHINE_ATOMIC_H_ */
19887866Ssheldonh