linux/arch/s390/lib/spinlock.c
<<
>>
Prefs
   1/*
   2 *  arch/s390/lib/spinlock.c
   3 *    Out of line spinlock code.
   4 *
   5 *    Copyright (C) IBM Corp. 2004, 2006
   6 *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
   7 */
   8
   9#include <linux/types.h>
  10#include <linux/module.h>
  11#include <linux/spinlock.h>
  12#include <linux/init.h>
  13#include <asm/io.h>
  14
  15int spin_retry = 1000;
  16
  17/**
  18 * spin_retry= parameter
  19 */
  20static int __init spin_retry_setup(char *str)
  21{
  22        spin_retry = simple_strtoul(str, &str, 0);
  23        return 1;
  24}
  25__setup("spin_retry=", spin_retry_setup);
  26
  27static inline void _raw_yield(void)
  28{
  29        if (MACHINE_HAS_DIAG44)
  30                asm volatile("diag 0,0,0x44");
  31}
  32
  33static inline void _raw_yield_cpu(int cpu)
  34{
  35        if (MACHINE_HAS_DIAG9C)
  36                asm volatile("diag %0,0,0x9c"
  37                             : : "d" (__cpu_logical_map[cpu]));
  38        else
  39                _raw_yield();
  40}
  41
  42void _raw_spin_lock_wait(raw_spinlock_t *lp)
  43{
  44        int count = spin_retry;
  45        unsigned int cpu = ~smp_processor_id();
  46
  47        while (1) {
  48                if (count-- <= 0) {
  49                        unsigned int owner = lp->owner_cpu;
  50                        if (owner != 0)
  51                                _raw_yield_cpu(~owner);
  52                        count = spin_retry;
  53                }
  54                if (__raw_spin_is_locked(lp))
  55                        continue;
  56                if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0)
  57                        return;
  58        }
  59}
  60EXPORT_SYMBOL(_raw_spin_lock_wait);
  61
  62void _raw_spin_lock_wait_flags(raw_spinlock_t *lp, unsigned long flags)
  63{
  64        int count = spin_retry;
  65        unsigned int cpu = ~smp_processor_id();
  66
  67        local_irq_restore(flags);
  68        while (1) {
  69                if (count-- <= 0) {
  70                        unsigned int owner = lp->owner_cpu;
  71                        if (owner != 0)
  72                                _raw_yield_cpu(~owner);
  73                        count = spin_retry;
  74                }
  75                if (__raw_spin_is_locked(lp))
  76                        continue;
  77                local_irq_disable();
  78                if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0)
  79                        return;
  80                local_irq_restore(flags);
  81        }
  82}
  83EXPORT_SYMBOL(_raw_spin_lock_wait_flags);
  84
  85int _raw_spin_trylock_retry(raw_spinlock_t *lp)
  86{
  87        unsigned int cpu = ~smp_processor_id();
  88        int count;
  89
  90        for (count = spin_retry; count > 0; count--) {
  91                if (__raw_spin_is_locked(lp))
  92                        continue;
  93                if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0)
  94                        return 1;
  95        }
  96        return 0;
  97}
  98EXPORT_SYMBOL(_raw_spin_trylock_retry);
  99
 100void _raw_spin_relax(raw_spinlock_t *lock)
 101{
 102        unsigned int cpu = lock->owner_cpu;
 103        if (cpu != 0)
 104                _raw_yield_cpu(~cpu);
 105}
 106EXPORT_SYMBOL(_raw_spin_relax);
 107
 108void _raw_read_lock_wait(raw_rwlock_t *rw)
 109{
 110        unsigned int old;
 111        int count = spin_retry;
 112
 113        while (1) {
 114                if (count-- <= 0) {
 115                        _raw_yield();
 116                        count = spin_retry;
 117                }
 118                if (!__raw_read_can_lock(rw))
 119                        continue;
 120                old = rw->lock & 0x7fffffffU;
 121                if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
 122                        return;
 123        }
 124}
 125EXPORT_SYMBOL(_raw_read_lock_wait);
 126
 127void _raw_read_lock_wait_flags(raw_rwlock_t *rw, unsigned long flags)
 128{
 129        unsigned int old;
 130        int count = spin_retry;
 131
 132        local_irq_restore(flags);
 133        while (1) {
 134                if (count-- <= 0) {
 135                        _raw_yield();
 136                        count = spin_retry;
 137                }
 138                if (!__raw_read_can_lock(rw))
 139                        continue;
 140                old = rw->lock & 0x7fffffffU;
 141                local_irq_disable();
 142                if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
 143                        return;
 144        }
 145}
 146EXPORT_SYMBOL(_raw_read_lock_wait_flags);
 147
 148int _raw_read_trylock_retry(raw_rwlock_t *rw)
 149{
 150        unsigned int old;
 151        int count = spin_retry;
 152
 153        while (count-- > 0) {
 154                if (!__raw_read_can_lock(rw))
 155                        continue;
 156                old = rw->lock & 0x7fffffffU;
 157                if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
 158                        return 1;
 159        }
 160        return 0;
 161}
 162EXPORT_SYMBOL(_raw_read_trylock_retry);
 163
 164void _raw_write_lock_wait(raw_rwlock_t *rw)
 165{
 166        int count = spin_retry;
 167
 168        while (1) {
 169                if (count-- <= 0) {
 170                        _raw_yield();
 171                        count = spin_retry;
 172                }
 173                if (!__raw_write_can_lock(rw))
 174                        continue;
 175                if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
 176                        return;
 177        }
 178}
 179EXPORT_SYMBOL(_raw_write_lock_wait);
 180
 181void _raw_write_lock_wait_flags(raw_rwlock_t *rw, unsigned long flags)
 182{
 183        int count = spin_retry;
 184
 185        local_irq_restore(flags);
 186        while (1) {
 187                if (count-- <= 0) {
 188                        _raw_yield();
 189                        count = spin_retry;
 190                }
 191                if (!__raw_write_can_lock(rw))
 192                        continue;
 193                local_irq_disable();
 194                if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
 195                        return;
 196        }
 197}
 198EXPORT_SYMBOL(_raw_write_lock_wait_flags);
 199
 200int _raw_write_trylock_retry(raw_rwlock_t *rw)
 201{
 202        int count = spin_retry;
 203
 204        while (count-- > 0) {
 205                if (!__raw_write_can_lock(rw))
 206                        continue;
 207                if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
 208                        return 1;
 209        }
 210        return 0;
 211}
 212EXPORT_SYMBOL(_raw_write_trylock_retry);
 213