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
 127int _raw_read_trylock_retry(raw_rwlock_t *rw)
 128{
 129        unsigned int old;
 130        int count = spin_retry;
 131
 132        while (count-- > 0) {
 133                if (!__raw_read_can_lock(rw))
 134                        continue;
 135                old = rw->lock & 0x7fffffffU;
 136                if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
 137                        return 1;
 138        }
 139        return 0;
 140}
 141EXPORT_SYMBOL(_raw_read_trylock_retry);
 142
 143void _raw_write_lock_wait(raw_rwlock_t *rw)
 144{
 145        int count = spin_retry;
 146
 147        while (1) {
 148                if (count-- <= 0) {
 149                        _raw_yield();
 150                        count = spin_retry;
 151                }
 152                if (!__raw_write_can_lock(rw))
 153                        continue;
 154                if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
 155                        return;
 156        }
 157}
 158EXPORT_SYMBOL(_raw_write_lock_wait);
 159
 160int _raw_write_trylock_retry(raw_rwlock_t *rw)
 161{
 162        int count = spin_retry;
 163
 164        while (count-- > 0) {
 165                if (!__raw_write_can_lock(rw))
 166                        continue;
 167                if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
 168                        return 1;
 169        }
 170        return 0;
 171}
 172EXPORT_SYMBOL(_raw_write_trylock_retry);
 173