1 /* src/threads/lockword.hpp - lockword implementation
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
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;
42 static const uintptr_t THIN_UNLOCKED = 0;
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);
49 static const int THIN_LOCK_COUNT_MASK = (THIN_LOCK_COUNT_MAX << THIN_LOCK_COUNT_SHIFT);
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);
55 // The actual lockword.
59 Lockword(uintptr_t lockword) : _lockword(lockword) {}
62 Lockword() : _lockword(THIN_UNLOCKED) {}
64 void init() { _lockword = THIN_UNLOCKED; } // REMOVEME
66 static inline uintptr_t pre_compute_thinlock(int32_t index);
68 inline bool is_thin_lock () const;
69 inline bool is_fat_lock () const;
71 inline bool is_unlocked() const;
72 inline bool lock (uintptr_t thinlock);
73 inline void unlock ();
75 inline uintptr_t get_thin_lock () const;
76 inline uintptr_t get_thin_lock_without_count() const;
77 inline int32_t get_thin_lock_count () const;
78 inline int32_t get_thin_lock_thread_index () const;
79 inline struct lock_record_t* get_fat_lock () const;
81 inline void set(uintptr_t lockword);
82 inline void set(struct lock_record_t* lr);
84 inline bool is_max_thin_lock_count () const;
85 inline void increase_thin_lock_count();
86 inline void decrease_thin_lock_count();
88 void inflate(struct lock_record_t* lr);
95 #include "threads/atomic.hpp"
99 * Pre-compute the thin lock value for a thread index.
101 * @param index The thead index (>= 1).
103 * @return The thin lock value for this thread index.
105 uintptr_t Lockword::pre_compute_thinlock(int32_t index)
107 return (index << THIN_LOCK_TID_SHIFT) | THIN_UNLOCKED;
111 bool Lockword::is_thin_lock() const
113 return ((_lockword & THIN_LOCK_SHAPE_BIT) == 0);
117 bool Lockword::is_fat_lock() const
119 return ((_lockword & THIN_LOCK_SHAPE_BIT) != 0);
124 * Check if the lockword is an unlocked thin-lock.
126 * @return true if unlocked, false otherwise.
128 bool Lockword::is_unlocked() const
130 return (_lockword == THIN_UNLOCKED);
135 * Try to lock the lockword with the given thin-lock value.
137 * @param thinlock Thin-lock value to store in the Lockword.
139 * @return true if lock was successful, false otherwise.
141 bool Lockword::lock(uintptr_t thinlock)
143 // Atomically exchange the lockword value.
144 uintptr_t oldlockword = Atomic::compare_and_swap(&_lockword, THIN_UNLOCKED, thinlock);
146 return Lockword(oldlockword).is_unlocked();
151 * Set the lockword to THIN_UNLOCKED.
153 void Lockword::unlock()
155 _lockword = THIN_UNLOCKED;
159 uintptr_t Lockword::get_thin_lock() const
165 uintptr_t Lockword::get_thin_lock_without_count() const
167 return (_lockword & ~THIN_LOCK_COUNT_MASK);
171 int32_t Lockword::get_thin_lock_count() const
173 return (int32_t) (_lockword & THIN_LOCK_COUNT_MASK) >> THIN_LOCK_COUNT_SHIFT;
177 int32_t Lockword::get_thin_lock_thread_index() const
179 return (int32_t) (_lockword >> THIN_LOCK_TID_SHIFT);
183 struct lock_record_t* Lockword::get_fat_lock() const
185 return (struct lock_record_t*) (_lockword & ~THIN_LOCK_SHAPE_BIT);
189 void Lockword::set(uintptr_t lockword)
191 _lockword = lockword;
195 void Lockword::set(struct lock_record_t* lr)
197 _lockword = ((uintptr_t) lr) | THIN_LOCK_SHAPE_BIT;
201 bool Lockword::is_max_thin_lock_count() const
203 return (get_thin_lock_count() >= THIN_LOCK_COUNT_MAX);
207 void Lockword::increase_thin_lock_count()
210 assert(get_thin_lock_count() < THIN_LOCK_COUNT_MAX);
212 _lockword += (1 << THIN_LOCK_COUNT_SHIFT);
216 void Lockword::decrease_thin_lock_count()
219 assert(get_thin_lock_count() > 0);
221 _lockword -= (1 << THIN_LOCK_COUNT_SHIFT);
226 // This structure must have the same layout as the C++ class above.
227 typedef struct Lockword {
233 #endif // _LOCKWORD_HPP
237 * These are local overrides for various environment variables in Emacs.
238 * Please do not remove this and leave it at the end of the file, where
239 * Emacs will automagically detect them.
240 * ---------------------------------------------------------------------
243 * indent-tabs-mode: t
247 * vim:noexpandtab:sw=4:ts=4: