LCOV - code coverage report
Current view: top level - threads - lockword.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 39 39 100.0 %
Date: 2017-07-14 10:03:36 Functions: 17 17 100.0 %

          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             :  */

Generated by: LCOV version 1.11