1 /* src/threads/lockword.hpp - lockword implementation
3 Copyright (C) 2008-2010
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) {}
61 void init() { _lockword = THIN_UNLOCKED; } // REMOVEME
63 static inline uintptr_t pre_compute_thinlock(int32_t index);
65 inline bool is_thin_lock () const;
66 inline bool is_fat_lock () const;
68 inline bool is_unlocked() const;
69 inline bool lock (uintptr_t thinlock);
70 inline void unlock ();
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;
78 inline void set(uintptr_t lockword);
79 inline void set(struct lock_record_t* lr);
81 inline bool is_max_thin_lock_count () const;
82 inline void increase_thin_lock_count();
83 inline void decrease_thin_lock_count();
85 void inflate(struct lock_record_t* lr);
92 #include "threads/atomic.hpp"
96 * Pre-compute the thin lock value for a thread index.
98 * @param index The thead index (>= 1).
100 * @return The thin lock value for this thread index.
102 uintptr_t Lockword::pre_compute_thinlock(int32_t index)
104 return (index << THIN_LOCK_TID_SHIFT) | THIN_UNLOCKED;
108 bool Lockword::is_thin_lock() const
110 return ((_lockword & THIN_LOCK_SHAPE_BIT) == 0);
114 bool Lockword::is_fat_lock() const
116 return ((_lockword & THIN_LOCK_SHAPE_BIT) != 0);
121 * Check if the lockword is an unlocked thin-lock.
123 * @return true if unlocked, false otherwise.
125 bool Lockword::is_unlocked() const
127 return (_lockword == THIN_UNLOCKED);
132 * Try to lock the lockword with the given thin-lock value.
134 * @param thinlock Thin-lock value to store in the Lockword.
136 * @return true if lock was successful, false otherwise.
138 bool Lockword::lock(uintptr_t thinlock)
140 // Atomically exchange the lockword value.
141 uintptr_t oldlockword = Atomic::compare_and_swap(&_lockword, THIN_UNLOCKED, thinlock);
143 return Lockword(oldlockword).is_unlocked();
148 * Set the lockword to THIN_UNLOCKED.
150 void Lockword::unlock()
152 _lockword = THIN_UNLOCKED;
156 uintptr_t Lockword::get_thin_lock() const
162 uintptr_t Lockword::get_thin_lock_without_count() const
164 return (_lockword & ~THIN_LOCK_COUNT_MASK);
168 int32_t Lockword::get_thin_lock_count() const
170 return (int32_t) (_lockword & THIN_LOCK_COUNT_MASK) >> THIN_LOCK_COUNT_SHIFT;
174 int32_t Lockword::get_thin_lock_thread_index() const
176 return (int32_t) (_lockword >> THIN_LOCK_TID_SHIFT);
180 struct lock_record_t* Lockword::get_fat_lock() const
182 return (struct lock_record_t*) (_lockword & ~THIN_LOCK_SHAPE_BIT);
186 void Lockword::set(uintptr_t lockword)
188 _lockword = lockword;
192 void Lockword::set(struct lock_record_t* lr)
194 _lockword = ((uintptr_t) lr) | THIN_LOCK_SHAPE_BIT;
198 bool Lockword::is_max_thin_lock_count() const
200 return (get_thin_lock_count() >= THIN_LOCK_COUNT_MAX);
204 void Lockword::increase_thin_lock_count()
207 assert(get_thin_lock_count() < THIN_LOCK_COUNT_MAX);
209 _lockword += (1 << THIN_LOCK_COUNT_SHIFT);
213 void Lockword::decrease_thin_lock_count()
216 assert(get_thin_lock_count() > 0);
218 _lockword -= (1 << THIN_LOCK_COUNT_SHIFT);
223 // This structure must have the same layout as the C++ class above.
224 typedef struct Lockword {
230 #endif // _LOCKWORD_HPP
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 * ---------------------------------------------------------------------
240 * indent-tabs-mode: t
244 * vim:noexpandtab:sw=4:ts=4: