home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-x86_64 / spinlock.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  3.1 KB  |  138 lines

  1. #ifndef __ASM_SPINLOCK_H
  2. #define __ASM_SPINLOCK_H
  3.  
  4. #include <asm/atomic.h>
  5. #include <asm/rwlock.h>
  6. #include <asm/page.h>
  7.  
  8. /*
  9.  * Your basic SMP spinlocks, allowing only a single CPU anywhere
  10.  *
  11.  * Simple spin lock operations.  There are two variants, one clears IRQ's
  12.  * on the local processor, one does not.
  13.  *
  14.  * We make no fairness assumptions. They have a cost.
  15.  *
  16.  * (the type definitions are in asm/spinlock_types.h)
  17.  */
  18.  
  19. #define __raw_spin_is_locked(x) \
  20.         (*(volatile signed int *)(&(x)->slock) <= 0)
  21.  
  22. #define __raw_spin_lock_string \
  23.     "\n1:\t" \
  24.     "lock ; decl %0\n\t" \
  25.     "js 2f\n" \
  26.     LOCK_SECTION_START("") \
  27.     "2:\t" \
  28.     "rep;nop\n\t" \
  29.     "cmpl $0,%0\n\t" \
  30.     "jle 2b\n\t" \
  31.     "jmp 1b\n" \
  32.     LOCK_SECTION_END
  33.  
  34. #define __raw_spin_lock_string_up \
  35.     "\n\tdecl %0"
  36.  
  37. #define __raw_spin_unlock_string \
  38.     "movl $1,%0" \
  39.         :"=m" (lock->slock) : : "memory"
  40.  
  41. static inline void __raw_spin_lock(raw_spinlock_t *lock)
  42. {
  43.     alternative_smp(
  44.         __raw_spin_lock_string,
  45.         __raw_spin_lock_string_up,
  46.         "=m" (lock->slock) : : "memory");
  47. }
  48.  
  49. #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
  50.  
  51. static inline int __raw_spin_trylock(raw_spinlock_t *lock)
  52. {
  53.     int oldval;
  54.  
  55.     __asm__ __volatile__(
  56.         "xchgl %0,%1"
  57.         :"=q" (oldval), "=m" (lock->slock)
  58.         :"0" (0) : "memory");
  59.  
  60.     return oldval > 0;
  61. }
  62.  
  63. static inline void __raw_spin_unlock(raw_spinlock_t *lock)
  64. {
  65.     __asm__ __volatile__(
  66.         __raw_spin_unlock_string
  67.     );
  68. }
  69.  
  70. #define __raw_spin_unlock_wait(lock) \
  71.     do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
  72.  
  73. /*
  74.  * Read-write spinlocks, allowing multiple readers
  75.  * but only one writer.
  76.  *
  77.  * NOTE! it is quite common to have readers in interrupts
  78.  * but no interrupt writers. For those circumstances we
  79.  * can "mix" irq-safe locks - any writer needs to get a
  80.  * irq-safe write-lock, but readers can get non-irqsafe
  81.  * read-locks.
  82.  *
  83.  * On x86, we implement read-write locks as a 32-bit counter
  84.  * with the high bit (sign) being the "contended" bit.
  85.  *
  86.  * The inline assembly is non-obvious. Think about it.
  87.  *
  88.  * Changed to use the same technique as rw semaphores.  See
  89.  * semaphore.h for details.  -ben
  90.  *
  91.  * the helpers are in arch/i386/kernel/semaphore.c
  92.  */
  93.  
  94. #define __raw_read_can_lock(x)        ((int)(x)->lock > 0)
  95. #define __raw_write_can_lock(x)        ((x)->lock == RW_LOCK_BIAS)
  96.  
  97. static inline void __raw_read_lock(raw_rwlock_t *rw)
  98. {
  99.     __build_read_lock(rw, "__read_lock_failed");
  100. }
  101.  
  102. static inline void __raw_write_lock(raw_rwlock_t *rw)
  103. {
  104.     __build_write_lock(rw, "__write_lock_failed");
  105. }
  106.  
  107. static inline int __raw_read_trylock(raw_rwlock_t *lock)
  108. {
  109.     atomic_t *count = (atomic_t *)lock;
  110.     atomic_dec(count);
  111.     if (atomic_read(count) >= 0)
  112.         return 1;
  113.     atomic_inc(count);
  114.     return 0;
  115. }
  116.  
  117. static inline int __raw_write_trylock(raw_rwlock_t *lock)
  118. {
  119.     atomic_t *count = (atomic_t *)lock;
  120.     if (atomic_sub_and_test(RW_LOCK_BIAS, count))
  121.         return 1;
  122.     atomic_add(RW_LOCK_BIAS, count);
  123.     return 0;
  124. }
  125.  
  126. static inline void __raw_read_unlock(raw_rwlock_t *rw)
  127. {
  128.     asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory");
  129. }
  130.  
  131. static inline void __raw_write_unlock(raw_rwlock_t *rw)
  132. {
  133.     asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0"
  134.                 : "=m" (rw->lock) : : "memory");
  135. }
  136.  
  137. #endif /* __ASM_SPINLOCK_H */
  138.