Line data Source code
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 "config.h"
30 : #include <stdint.h>
31 : #include <assert.h>
32 : #include "threads/atomic.hpp"
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 9512443 : Lockword(uintptr_t& lockword) : _lockword(lockword) {}
60 :
61 2189723 : 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 : /**
90 : * Pre-compute the thin lock value for a thread index.
91 : *
92 : * @param index The thead index (>= 1).
93 : *
94 : * @return The thin lock value for this thread index.
95 : */
96 793 : uintptr_t Lockword::pre_compute_thinlock(int32_t index)
97 : {
98 793 : return (index << THIN_LOCK_TID_SHIFT) | THIN_UNLOCKED;
99 : }
100 :
101 :
102 6 : bool Lockword::is_thin_lock() const
103 : {
104 6 : return ((_lockword & THIN_LOCK_SHAPE_BIT) == 0);
105 : }
106 :
107 :
108 131861 : bool Lockword::is_fat_lock() const
109 : {
110 131861 : return ((_lockword & THIN_LOCK_SHAPE_BIT) != 0);
111 : }
112 :
113 :
114 : /**
115 : * Check if the lockword is an unlocked thin-lock.
116 : *
117 : * @return true if unlocked, false otherwise.
118 : */
119 1422600 : bool Lockword::is_unlocked() const
120 : {
121 1422600 : return (_lockword == THIN_UNLOCKED);
122 : }
123 :
124 :
125 : /**
126 : * Try to lock the lockword with the given thin-lock value.
127 : *
128 : * @param thinlock Thin-lock value to store in the Lockword.
129 : *
130 : * @return true if lock was successful, false otherwise.
131 : */
132 1422594 : bool Lockword::lock(uintptr_t thinlock)
133 : {
134 : // Atomically exchange the lockword value.
135 1422594 : uintptr_t oldlockword = Atomic::compare_and_swap(&_lockword, THIN_UNLOCKED, thinlock);
136 :
137 1422601 : return Lockword(oldlockword).is_unlocked();
138 : }
139 :
140 :
141 : /**
142 : * Set the lockword to THIN_UNLOCKED.
143 : */
144 1215125 : void Lockword::unlock()
145 : {
146 1215125 : _lockword = THIN_UNLOCKED;
147 1215125 : }
148 :
149 :
150 1422596 : uintptr_t Lockword::get_thin_lock() const
151 : {
152 1422596 : return _lockword;
153 : }
154 :
155 :
156 435204 : uintptr_t Lockword::get_thin_lock_without_count() const
157 : {
158 435204 : return (_lockword & ~THIN_LOCK_COUNT_MASK);
159 : }
160 :
161 :
162 530678 : int32_t Lockword::get_thin_lock_count() const
163 : {
164 530678 : return (int32_t) (_lockword & THIN_LOCK_COUNT_MASK) >> THIN_LOCK_COUNT_SHIFT;
165 : }
166 :
167 :
168 9 : int32_t Lockword::get_thin_lock_thread_index() const
169 : {
170 9 : return (int32_t) (_lockword >> THIN_LOCK_TID_SHIFT);
171 : }
172 :
173 :
174 71657 : struct lock_record_t* Lockword::get_fat_lock() const
175 : {
176 71657 : return (struct lock_record_t*) (_lockword & ~THIN_LOCK_SHAPE_BIT);
177 : }
178 :
179 :
180 : void Lockword::set(uintptr_t lockword)
181 : {
182 : _lockword = lockword;
183 : }
184 :
185 :
186 20007 : void Lockword::set(struct lock_record_t* lr)
187 : {
188 20007 : _lockword = ((uintptr_t) lr) | THIN_LOCK_SHAPE_BIT;
189 20007 : }
190 :
191 :
192 170224 : bool Lockword::is_max_thin_lock_count() const
193 : {
194 170224 : return (get_thin_lock_count() >= THIN_LOCK_COUNT_MAX);
195 : }
196 :
197 :
198 170224 : void Lockword::increase_thin_lock_count()
199 : {
200 : // Sanity check.
201 170224 : assert(get_thin_lock_count() < THIN_LOCK_COUNT_MAX);
202 :
203 170224 : _lockword += (1 << THIN_LOCK_COUNT_SHIFT);
204 170224 : }
205 :
206 :
207 170223 : void Lockword::decrease_thin_lock_count()
208 : {
209 : // Sanity check.
210 170223 : assert(get_thin_lock_count() > 0);
211 :
212 170223 : _lockword -= (1 << THIN_LOCK_COUNT_SHIFT);
213 170223 : }
214 :
215 : #endif // _LOCKWORD_HPP
216 :
217 :
218 : /*
219 : * These are local overrides for various environment variables in Emacs.
220 : * Please do not remove this and leave it at the end of the file, where
221 : * Emacs will automagically detect them.
222 : * ---------------------------------------------------------------------
223 : * Local variables:
224 : * mode: c++
225 : * indent-tabs-mode: t
226 : * c-basic-offset: 4
227 : * tab-width: 4
228 : * End:
229 : * vim:noexpandtab:sw=4:ts=4:
230 : */
|