at v2.6.13 1.8 kB view raw
1/* 2 * bitops.c: atomic operations which got too long to be inlined all over 3 * the place. 4 * 5 * Copyright 1999 Philipp Rumpf (prumpf@tux.org) 6 * Copyright 2000 Grant Grundler (grundler@cup.hp.com) 7 */ 8 9#include <linux/config.h> 10#include <linux/kernel.h> 11#include <linux/spinlock.h> 12#include <asm/system.h> 13#include <asm/atomic.h> 14 15#ifdef CONFIG_SMP 16spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = { 17 [0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED 18}; 19#endif 20 21#ifdef __LP64__ 22unsigned long __xchg64(unsigned long x, unsigned long *ptr) 23{ 24 unsigned long temp, flags; 25 26 _atomic_spin_lock_irqsave(ptr, flags); 27 temp = *ptr; 28 *ptr = x; 29 _atomic_spin_unlock_irqrestore(ptr, flags); 30 return temp; 31} 32#endif 33 34unsigned long __xchg32(int x, int *ptr) 35{ 36 unsigned long flags; 37 long temp; 38 39 _atomic_spin_lock_irqsave(ptr, flags); 40 temp = (long) *ptr; /* XXX - sign extension wanted? */ 41 *ptr = x; 42 _atomic_spin_unlock_irqrestore(ptr, flags); 43 return (unsigned long)temp; 44} 45 46 47unsigned long __xchg8(char x, char *ptr) 48{ 49 unsigned long flags; 50 long temp; 51 52 _atomic_spin_lock_irqsave(ptr, flags); 53 temp = (long) *ptr; /* XXX - sign extension wanted? */ 54 *ptr = x; 55 _atomic_spin_unlock_irqrestore(ptr, flags); 56 return (unsigned long)temp; 57} 58 59 60#ifdef __LP64__ 61unsigned long __cmpxchg_u64(volatile unsigned long *ptr, unsigned long old, unsigned long new) 62{ 63 unsigned long flags; 64 unsigned long prev; 65 66 _atomic_spin_lock_irqsave(ptr, flags); 67 if ((prev = *ptr) == old) 68 *ptr = new; 69 _atomic_spin_unlock_irqrestore(ptr, flags); 70 return prev; 71} 72#endif 73 74unsigned long __cmpxchg_u32(volatile unsigned int *ptr, unsigned int old, unsigned int new) 75{ 76 unsigned long flags; 77 unsigned int prev; 78 79 _atomic_spin_lock_irqsave(ptr, flags); 80 if ((prev = *ptr) == old) 81 *ptr = new; 82 _atomic_spin_unlock_irqrestore(ptr, flags); 83 return (unsigned long)prev; 84}