* src/vm/global.h: Made 'lockword' member of java_object_t a plain
[cacao.git] / src / threads / lockword.hpp
1 /* src/threads/lockword.hpp - lockword implementation
2
3    Copyright (C) 2008-2010
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #ifndef _LOCKWORD_HPP
27 #define _LOCKWORD_HPP
28
29 #include <stdint.h>
30
31
32 #ifdef __cplusplus
33
34 /**
35  * Lockword.
36  */
37 class Lockword {
38 private:
39         static const int       THIN_LOCK_WORD_SIZE   = SIZEOF_VOID_P * 8; // Pointer size multiplied by 8-bit.
40         static const int       THIN_LOCK_SHAPE_BIT   = 0x01;
41
42         static const uintptr_t THIN_UNLOCKED         = 0;
43
44         static const int       THIN_LOCK_COUNT_SHIFT = 1;
45         static const int       THIN_LOCK_COUNT_SIZE  = 8;
46         static const int       THIN_LOCK_COUNT_INCR  = (1 << THIN_LOCK_COUNT_SHIFT);
47         static const int       THIN_LOCK_COUNT_MAX   = ((1 << THIN_LOCK_COUNT_SIZE) - 1);
48
49         static const int       THIN_LOCK_COUNT_MASK  = (THIN_LOCK_COUNT_MAX << THIN_LOCK_COUNT_SHIFT);
50
51         static const int       THIN_LOCK_TID_SHIFT   = (THIN_LOCK_COUNT_SIZE + THIN_LOCK_COUNT_SHIFT);
52         static const int       THIN_LOCK_TID_SIZE    = (THIN_LOCK_WORD_SIZE - THIN_LOCK_TID_SHIFT);
53
54 private:
55         // The actual lockword.
56         uintptr_t& _lockword;
57
58 public:
59         Lockword(uintptr_t& lockword) : _lockword(lockword) {}
60
61         void init() { _lockword = THIN_UNLOCKED; } // REMOVEME
62
63         static inline uintptr_t pre_compute_thinlock(int32_t index);
64
65         inline bool is_thin_lock         () const;
66         inline bool is_fat_lock          () const;
67
68         inline bool is_unlocked() const;
69         inline bool lock       (uintptr_t thinlock);
70         inline void unlock     ();
71
72         inline uintptr_t             get_thin_lock              () const;
73         inline uintptr_t             get_thin_lock_without_count() const;
74         inline int32_t               get_thin_lock_count        () const;
75         inline int32_t               get_thin_lock_thread_index () const;
76         inline struct lock_record_t* get_fat_lock               () const;
77
78         inline void set(uintptr_t lockword);
79         inline void set(struct lock_record_t* lr);
80
81         inline bool is_max_thin_lock_count  () const;
82         inline void increase_thin_lock_count();
83         inline void decrease_thin_lock_count();
84
85         void inflate(struct lock_record_t* lr);
86 };
87
88
89 // Includes.
90 #include <assert.h>
91
92 #include "threads/atomic.hpp"
93
94
95 /**
96  * Pre-compute the thin lock value for a thread index.
97  *
98  * @param index The thead index (>= 1).
99  *
100  * @return The thin lock value for this thread index.
101  */
102 uintptr_t Lockword::pre_compute_thinlock(int32_t index)
103 {
104         return (index << THIN_LOCK_TID_SHIFT) | THIN_UNLOCKED;
105 }
106
107
108 bool Lockword::is_thin_lock() const
109 {
110         return ((_lockword & THIN_LOCK_SHAPE_BIT) == 0);
111 }
112
113
114 bool Lockword::is_fat_lock() const
115 {
116         return ((_lockword & THIN_LOCK_SHAPE_BIT) != 0);
117 }
118
119
120 /**
121  * Check if the lockword is an unlocked thin-lock.
122  *
123  * @return true if unlocked, false otherwise.
124  */
125 bool Lockword::is_unlocked() const
126 {
127         return (_lockword == THIN_UNLOCKED);
128 }
129
130
131 /**
132  * Try to lock the lockword with the given thin-lock value.
133  *
134  * @param thinlock Thin-lock value to store in the Lockword.
135  *
136  * @return true if lock was successful, false otherwise.
137  */
138 bool Lockword::lock(uintptr_t thinlock)
139 {
140         // Atomically exchange the lockword value.
141         uintptr_t oldlockword = Atomic::compare_and_swap(&_lockword, THIN_UNLOCKED, thinlock);
142
143         return Lockword(oldlockword).is_unlocked();
144 }
145
146
147 /**
148  * Set the lockword to THIN_UNLOCKED.
149  */
150 void Lockword::unlock()
151 {
152         _lockword = THIN_UNLOCKED;
153 }
154
155
156 uintptr_t Lockword::get_thin_lock() const
157 {
158         return _lockword;
159 }
160
161
162 uintptr_t Lockword::get_thin_lock_without_count() const
163 {
164         return (_lockword & ~THIN_LOCK_COUNT_MASK);
165 }
166
167
168 int32_t Lockword::get_thin_lock_count() const
169 {
170         return (int32_t) (_lockword & THIN_LOCK_COUNT_MASK) >> THIN_LOCK_COUNT_SHIFT;
171 }
172
173
174 int32_t Lockword::get_thin_lock_thread_index() const
175 {
176         return (int32_t) (_lockword >> THIN_LOCK_TID_SHIFT);
177 }
178
179
180 struct lock_record_t* Lockword::get_fat_lock() const
181 {
182         return (struct lock_record_t*) (_lockword & ~THIN_LOCK_SHAPE_BIT);
183 }
184
185
186 void Lockword::set(uintptr_t lockword)
187 {
188         _lockword = lockword;
189 }
190
191
192 void Lockword::set(struct lock_record_t* lr)
193 {
194         _lockword = ((uintptr_t) lr) | THIN_LOCK_SHAPE_BIT;
195 }
196
197
198 bool Lockword::is_max_thin_lock_count() const
199 {
200         return (get_thin_lock_count() >= THIN_LOCK_COUNT_MAX);
201 }
202
203
204 void Lockword::increase_thin_lock_count()
205 {
206         // Sanity check.
207         assert(get_thin_lock_count() < THIN_LOCK_COUNT_MAX);
208
209         _lockword += (1 << THIN_LOCK_COUNT_SHIFT);
210 }
211
212
213 void Lockword::decrease_thin_lock_count()
214 {
215         // Sanity check.
216         assert(get_thin_lock_count() > 0);
217
218         _lockword -= (1 << THIN_LOCK_COUNT_SHIFT);
219 }
220
221 #else
222
223 // This structure must have the same layout as the C++ class above.
224 typedef struct Lockword {
225         uintptr_t _lockword;
226 } Lockword;
227
228 #endif
229
230 #endif // _LOCKWORD_HPP
231
232
233 /*
234  * These are local overrides for various environment variables in Emacs.
235  * Please do not remove this and leave it at the end of the file, where
236  * Emacs will automagically detect them.
237  * ---------------------------------------------------------------------
238  * Local variables:
239  * mode: c++
240  * indent-tabs-mode: t
241  * c-basic-offset: 4
242  * tab-width: 4
243  * End:
244  * vim:noexpandtab:sw=4:ts=4:
245  */