1 /*
   2  * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  *
  22  */
  23 
  24 #ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAH_PHASER_HPP
  25 #define SHARE_VM_GC_SHENANDOAH_SHENANDOAH_PHASER_HPP
  26 
  27 #include "memory/allocation.hpp"
  28 
  29 /**
  30  * This is an implementation of simplified java.util.concurrent.Phaser
  31  */
  32 
  33 class ShenandoahPhaser : public CHeapObj<mtGC> {
  34 private:
  35   enum {
  36     MAX_PARTIES     = 0xffff,
  37     MAX_PHASE       = 2147483647,
  38     PARTIES_SHIFT   = 16,
  39     PHASE_SHIFT     = 32,
  40     ONE_ARRIVAL     = 1,
  41     ONE_PARTY       = 1 << PARTIES_SHIFT,
  42     ONE_DEREGISTER  = ONE_ARRIVAL|ONE_PARTY,
  43     EMPTY           = 1
  44   };
  45 
  46   static const jlong PARTIES_MARK     = 0xffff0000L;
  47   static const jlong UNARRIVED_MASK   = 0x0000ffffL;
  48   static const jlong COUNTS_MARK      = 0xffffffffL;
  49   static const jlong TERMINATION_BIT  = 1L << 63;
  50   
  51 private:
  52   volatile  jlong  _state;
  53 
  54 public:
  55   ShenandoahPhaser(int parties = 1);
  56 
  57   inline int register_party() { return do_register(1); }  
  58 
  59   inline bool is_terminated() const { return _state < 0L; }
  60 
  61   int arrive() { return do_arrive(ONE_ARRIVAL); }
  62   int arriveAndAwaitAdvance();
  63   int arriveAndDeregister() { return do_arrive(ONE_DEREGISTER); }
  64  
  65   inline int  get_registered_parties() const {
  66     return parties_of(_state);
  67   }
  68 
  69   inline int get_arrived_parties() const {
  70     return arrived_of(_state);
  71   }
  72 
  73 protected:
  74   // Termination condition 
  75   virtual bool onAdvance(int phase, int registeredParties) = 0;
  76   
  77   // barrier
  78   virtual int  blockWaiters(int phase) = 0;
  79   virtual void releaseWaiters(int phase) = 0;
  80 
  81 private:
  82   int do_register(int registrations);
  83   int do_arrive(int adjust);
  84 
  85   inline int parties_of(jlong s) const { return (int)((unsigned jlong)s & PARTIES_MARK) >> PARTIES_SHIFT; }
  86   inline int phase_of(jlong s)   const { return (int)(s >> PHASE_SHIFT); }
  87   inline int arrived_of(jlong s) const {
  88     int counts = (int)s;
  89     return (counts == EMPTY) ? 0 :
  90       (int)(((unsigned int)counts) >> PARTIES_SHIFT) - (counts & UNARRIVED_MASK);
  91   }
  92   inline int unarrived_of(jlong s) const {
  93     int counts = (int)s;
  94     return (counts == EMPTY) ? 0 : (counts & UNARRIVED_MASK);
  95   }
  96 
  97 };
  98 
  99 #endif // SHARE_VM_GC_SHENANDOAH_SHENANDOAH_PHASER_HPP