blob: 8ff10300f7ee7afbf69f2ada83d387846aa60187 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * include/asm-s390/spinlock.h
3 *
4 * S390 version
5 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
7 *
8 * Derived from "include/asm-i386/spinlock.h"
9 */
10
11#ifndef __ASM_SPINLOCK_H
12#define __ASM_SPINLOCK_H
13
Martin Schwidefsky951f22d2005-07-27 11:44:57 -070014static inline int
15_raw_compare_and_swap(volatile unsigned int *lock,
16 unsigned int old, unsigned int new)
17{
18 asm volatile ("cs %0,%3,0(%4)"
19 : "=d" (old), "=m" (*lock)
20 : "0" (old), "d" (new), "a" (lock), "m" (*lock)
21 : "cc", "memory" );
22 return old;
23}
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
25/*
26 * Simple spin lock operations. There are two variants, one clears IRQ's
27 * on the local processor, one does not.
28 *
29 * We make no fairness assumptions. They have a cost.
30 */
31
32typedef struct {
33 volatile unsigned int lock;
34#ifdef CONFIG_PREEMPT
35 unsigned int break_lock;
36#endif
37} __attribute__ ((aligned (4))) spinlock_t;
38
Martin Schwidefsky951f22d2005-07-27 11:44:57 -070039#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
40#define spin_lock_init(lp) do { (lp)->lock = 0; } while(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#define spin_unlock_wait(lp) do { barrier(); } while(((volatile spinlock_t *)(lp))->lock)
Martin Schwidefsky951f22d2005-07-27 11:44:57 -070042#define spin_is_locked(x) ((x)->lock != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
44
Martin Schwidefsky951f22d2005-07-27 11:44:57 -070045extern void _raw_spin_lock_wait(spinlock_t *lp, unsigned int pc);
46extern int _raw_spin_trylock_retry(spinlock_t *lp, unsigned int pc);
47
48static inline void _raw_spin_lock(spinlock_t *lp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070049{
Martin Schwidefsky951f22d2005-07-27 11:44:57 -070050 unsigned long pc = (unsigned long) __builtin_return_address(0);
51
52 if (unlikely(_raw_compare_and_swap(&lp->lock, 0, pc) != 0))
53 _raw_spin_lock_wait(lp, pc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070054}
55
Martin Schwidefsky951f22d2005-07-27 11:44:57 -070056static inline int _raw_spin_trylock(spinlock_t *lp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070057{
Martin Schwidefsky951f22d2005-07-27 11:44:57 -070058 unsigned long pc = (unsigned long) __builtin_return_address(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Martin Schwidefsky951f22d2005-07-27 11:44:57 -070060 if (likely(_raw_compare_and_swap(&lp->lock, 0, pc) == 0))
61 return 1;
62 return _raw_spin_trylock_retry(lp, pc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070063}
64
Martin Schwidefsky951f22d2005-07-27 11:44:57 -070065static inline void _raw_spin_unlock(spinlock_t *lp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070066{
Martin Schwidefsky951f22d2005-07-27 11:44:57 -070067 _raw_compare_and_swap(&lp->lock, lp->lock, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068}
69
70/*
71 * Read-write spinlocks, allowing multiple readers
72 * but only one writer.
73 *
74 * NOTE! it is quite common to have readers in interrupts
75 * but no interrupt writers. For those circumstances we
76 * can "mix" irq-safe locks - any writer needs to get a
77 * irq-safe write-lock, but readers can get non-irqsafe
78 * read-locks.
79 */
80typedef struct {
Martin Schwidefsky951f22d2005-07-27 11:44:57 -070081 volatile unsigned int lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 volatile unsigned long owner_pc;
83#ifdef CONFIG_PREEMPT
84 unsigned int break_lock;
85#endif
86} rwlock_t;
87
88#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
89
90#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
91
92/**
93 * read_can_lock - would read_trylock() succeed?
94 * @lock: the rwlock in question.
95 */
96#define read_can_lock(x) ((int)(x)->lock >= 0)
97
98/**
99 * write_can_lock - would write_trylock() succeed?
100 * @lock: the rwlock in question.
101 */
102#define write_can_lock(x) ((x)->lock == 0)
103
Martin Schwidefsky951f22d2005-07-27 11:44:57 -0700104extern void _raw_read_lock_wait(rwlock_t *lp);
105extern int _raw_read_trylock_retry(rwlock_t *lp);
106extern void _raw_write_lock_wait(rwlock_t *lp);
107extern int _raw_write_trylock_retry(rwlock_t *lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
Martin Schwidefsky951f22d2005-07-27 11:44:57 -0700109static inline void _raw_read_lock(rwlock_t *rw)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110{
Martin Schwidefsky951f22d2005-07-27 11:44:57 -0700111 unsigned int old;
112 old = rw->lock & 0x7fffffffU;
113 if (_raw_compare_and_swap(&rw->lock, old, old + 1) != old)
114 _raw_read_lock_wait(rw);
115}
116
117static inline void _raw_read_unlock(rwlock_t *rw)
118{
119 unsigned int old, cmp;
120
121 old = rw->lock;
122 do {
123 cmp = old;
124 old = _raw_compare_and_swap(&rw->lock, old, old - 1);
125 } while (cmp != old);
126}
127
128static inline void _raw_write_lock(rwlock_t *rw)
129{
130 if (unlikely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) != 0))
131 _raw_write_lock_wait(rw);
132}
133
134static inline void _raw_write_unlock(rwlock_t *rw)
135{
136 _raw_compare_and_swap(&rw->lock, 0x80000000, 0);
137}
138
139static inline int _raw_read_trylock(rwlock_t *rw)
140{
141 unsigned int old;
142 old = rw->lock & 0x7fffffffU;
143 if (likely(_raw_compare_and_swap(&rw->lock, old, old + 1) == old))
144 return 1;
145 return _raw_read_trylock_retry(rw);
146}
147
148static inline int _raw_write_trylock(rwlock_t *rw)
149{
150 if (likely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0))
151 return 1;
152 return _raw_write_trylock_retry(rw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153}
154
155#endif /* __ASM_SPINLOCK_H */