]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/spin_lock.cpp
Update
[l4.git] / kernel / fiasco / src / kern / spin_lock.cpp
1 INTERFACE:
2
3 #include "cpu_lock.h"
4 #include "types.h"
5
6 class Spin_lock_base : protected Cpu_lock
7 {
8 public:
9   enum Lock_init { Unlocked = 0 };
10 };
11
12 /**
13  * \brief Basic spin lock.
14  *
15  * Also disables lock IRQs for the time the lock is held.
16  * In the UP case it is in fact just the Cpu_lock.
17  */
18 template<typename Lock_t = Small_atomic_int>
19 class Spin_lock : public Spin_lock_base
20 {
21 };
22
23 //--------------------------------------------------------------------------
24 INTERFACE [!mp]:
25
26 EXTENSION class Spin_lock
27 {
28 public:
29   Spin_lock() {}
30   explicit Spin_lock(Lock_init) {}
31   void init() {}
32
33   using Cpu_lock::Status;
34   using Cpu_lock::test;
35   using Cpu_lock::lock;
36   using Cpu_lock::clear;
37   using Cpu_lock::test_and_set;
38   using Cpu_lock::set;
39
40 };
41
42 /**
43  * \brief Version of a spin lock that is colocated with another value.
44  */
45 template< typename T >
46 class Spin_lock_coloc : public Spin_lock<Mword>
47 {
48 private:
49   enum { Arch_lock = 1 };
50   Mword _lock;
51 };
52
53
54 //--------------------------------------------------------------------------
55 INTERFACE [mp]:
56
57 EXTENSION class Spin_lock
58 {
59 public:
60   typedef Mword Status;
61   Spin_lock() {}
62   explicit Spin_lock(Lock_init i) : _lock((i == Unlocked) ? 0 : Arch_lock) {}
63
64 protected:
65   Lock_t _lock;
66 };
67
68 /**
69  * \brief Version of a spin lock that is colocated with another value.
70  */
71 template< typename T >
72 class Spin_lock_coloc : public Spin_lock<Mword>
73 {
74 };
75
76 //--------------------------------------------------------------------------
77 IMPLEMENTATION:
78
79 PUBLIC inline
80 template< typename T >
81 Spin_lock_coloc<T>::Spin_lock_coloc() {}
82
83 PUBLIC inline
84 template< typename T >
85 Spin_lock_coloc<T>::Spin_lock_coloc(Lock_init i) : Spin_lock<Mword>(i) {}
86
87 PUBLIC inline
88 template< typename T >
89 T
90 Spin_lock_coloc<T>::get_unused() const
91 { return (T)(_lock & ~Arch_lock); }
92
93 PUBLIC inline
94 template< typename T >
95 void
96 Spin_lock_coloc<T>::set_unused(T val)
97 { _lock = (_lock & Arch_lock) | (Mword)val; }
98
99
100 //--------------------------------------------------------------------------
101 IMPLEMENTATION [mp]:
102
103 #include <cassert>
104 #include "mem.h"
105
106 PUBLIC template<typename Lock_t> inline
107 void
108 Spin_lock<Lock_t>::init()
109 {
110   _lock = 0;
111 }
112
113 PUBLIC template<typename Lock_t> inline
114 typename Spin_lock<Lock_t>::Status
115 Spin_lock<Lock_t>::test() const
116 {
117   return (!!cpu_lock.test()) | (_lock & Arch_lock);
118 }
119
120 PUBLIC template<typename Lock_t> inline NEEDS[<cassert>, Spin_lock::lock_arch, "mem.h"]
121 void
122 Spin_lock<Lock_t>::lock()
123 {
124   assert(!cpu_lock.test());
125   cpu_lock.lock();
126   lock_arch();
127   Mem::mp_mb();
128 }
129
130 PUBLIC template<typename Lock_t> inline NEEDS[Spin_lock::unlock_arch, "mem.h"]
131 void
132 Spin_lock<Lock_t>::clear()
133 {
134   Mem::mp_mb();
135   unlock_arch();
136   Cpu_lock::clear();
137 }
138
139 PUBLIC template<typename Lock_t> inline NEEDS[Spin_lock::lock_arch, "mem.h"]
140 typename Spin_lock<Lock_t>::Status
141 Spin_lock<Lock_t>::test_and_set()
142 {
143   Status s = !!cpu_lock.test();
144   cpu_lock.lock();
145   lock_arch();
146   Mem::mp_mb();
147   return s;
148 }
149
150 PUBLIC template<typename Lock_t> inline
151 void
152 Spin_lock<Lock_t>::set(Status s)
153 {
154   Mem::mp_mb();
155   if (!(s & Arch_lock))
156     unlock_arch();
157
158   if (!(s & 1))
159     cpu_lock.clear();
160 }
161
162