xref: /linux/arch/sparc/lib/atomic32.c (revision a9f6a0dd54efea2a5d57a27e6c232f9197c25154)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * atomic32.c: 32-bit atomic_t implementation
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Copyright (C) 2004 Keith M Wesolowski
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Based on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf
71da177e4SLinus Torvalds  */
81da177e4SLinus Torvalds 
91da177e4SLinus Torvalds #include <asm/atomic.h>
101da177e4SLinus Torvalds #include <linux/spinlock.h>
111da177e4SLinus Torvalds #include <linux/module.h>
121da177e4SLinus Torvalds 
131da177e4SLinus Torvalds #ifdef CONFIG_SMP
141da177e4SLinus Torvalds #define ATOMIC_HASH_SIZE	4
151da177e4SLinus Torvalds #define ATOMIC_HASH(a)	(&__atomic_hash[(((unsigned long)a)>>8) & (ATOMIC_HASH_SIZE-1)])
161da177e4SLinus Torvalds 
171da177e4SLinus Torvalds spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = {
181da177e4SLinus Torvalds 	[0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED
191da177e4SLinus Torvalds };
201da177e4SLinus Torvalds 
211da177e4SLinus Torvalds #else /* SMP */
221da177e4SLinus Torvalds 
23*a9f6a0ddSIngo Molnar static DEFINE_SPINLOCK(dummy);
241da177e4SLinus Torvalds #define ATOMIC_HASH_SIZE	1
251da177e4SLinus Torvalds #define ATOMIC_HASH(a)		(&dummy)
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds #endif /* SMP */
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds int __atomic_add_return(int i, atomic_t *v)
301da177e4SLinus Torvalds {
311da177e4SLinus Torvalds 	int ret;
321da177e4SLinus Torvalds 	unsigned long flags;
331da177e4SLinus Torvalds 	spin_lock_irqsave(ATOMIC_HASH(v), flags);
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds 	ret = (v->counter += i);
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds 	spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
381da177e4SLinus Torvalds 	return ret;
391da177e4SLinus Torvalds }
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds void atomic_set(atomic_t *v, int i)
421da177e4SLinus Torvalds {
431da177e4SLinus Torvalds 	unsigned long flags;
441da177e4SLinus Torvalds 	spin_lock_irqsave(ATOMIC_HASH(v), flags);
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds 	v->counter = i;
471da177e4SLinus Torvalds 
481da177e4SLinus Torvalds 	spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
491da177e4SLinus Torvalds }
501da177e4SLinus Torvalds 
511da177e4SLinus Torvalds EXPORT_SYMBOL(__atomic_add_return);
521da177e4SLinus Torvalds EXPORT_SYMBOL(atomic_set);
531da177e4SLinus Torvalds 
54