1 /*
   2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_GC_G1_G1REDIRTYCARDSQUEUE_HPP
  26 #define SHARE_GC_G1_G1REDIRTYCARDSQUEUE_HPP
  27 
  28 #include "gc/g1/g1BufferNodeList.hpp"
  29 #include "gc/shared/ptrQueue.hpp"
  30 #include "memory/allocation.hpp"
  31 #include "memory/padded.hpp"
  32 
  33 class G1CardTableEntryClosure;
  34 class G1RedirtyCardsQueue;
  35 class G1RedirtyCardsQueueSet;
  36 
  37 // Provide G1RedirtyCardsQueue with a thread-local qset.  It provides an
  38 // uncontended staging area for completed buffers, to be flushed to the
  39 // shared qset en masse.  Using the "base from member" idiom so the local
  40 // qset is constructed before being passed to the PtrQueue constructor.
  41 class G1RedirtyCardsQueueBase {
  42   friend class G1RedirtyCardsQueue;
  43   friend class G1RedirtyCardsQueueSet;
  44 
  45   class LocalQSet : public PtrQueueSet {
  46     G1RedirtyCardsQueueSet* _shared_qset;
  47     G1BufferNodeList _buffers;
  48 
  49   public:
  50     LocalQSet(G1RedirtyCardsQueueSet* shared_qset);
  51     ~LocalQSet();
  52 
  53     // Add the buffer to the local list.
  54     virtual void enqueue_completed_buffer(BufferNode* node);
  55 
  56     // Transfer all completed buffers to the shared qset.
  57     void flush();
  58 
  59     G1BufferNodeList take_all_completed_buffers();
  60   };
  61 
  62   G1RedirtyCardsQueueBase(G1RedirtyCardsQueueSet* shared_qset) :
  63     _local_qset(shared_qset) {}
  64 
  65   ~G1RedirtyCardsQueueBase() {}
  66 
  67   LocalQSet _local_qset;
  68 };
  69 
  70 // Worker-local queues of card table entries.
  71 class G1RedirtyCardsQueue : private G1RedirtyCardsQueueBase, public PtrQueue {
  72 protected:
  73   virtual void handle_completed_buffer();
  74 
  75 public:
  76   G1RedirtyCardsQueue(G1RedirtyCardsQueueSet* qset);
  77 
  78   // Flushes the queue.
  79   ~G1RedirtyCardsQueue();
  80 
  81   // Flushes all enqueued cards to qset.
  82   void flush();
  83 };
  84 
  85 // Card table entries to be redirtied and the cards reprocessed later.
  86 // Has two phases, collecting and processing.  During the collecting
  87 // phase buffers are added to the set.  Once collecting is complete and
  88 // processing starts, buffers can no longer be added.  Taking all the
  89 // collected (and processed) buffers reverts back to collecting, allowing
  90 // the set to be reused for another round of redirtying.
  91 class G1RedirtyCardsQueueSet : public PtrQueueSet {
  92   DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0);
  93   BufferNode::Stack _list;
  94   DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(size_t));
  95   volatile size_t _entry_count;
  96   DEFINE_PAD_MINUS_SIZE(3, DEFAULT_CACHE_LINE_SIZE, sizeof(BufferNode*));
  97   BufferNode* _tail;
  98   DEBUG_ONLY(mutable bool _collecting;)
  99 
 100   typedef G1RedirtyCardsQueueBase::LocalQSet LocalQSet;
 101 
 102   void update_tail(BufferNode* node);
 103 
 104 public:
 105   G1RedirtyCardsQueueSet(BufferNode::Allocator* allocator);
 106   ~G1RedirtyCardsQueueSet();
 107 
 108   void verify_empty() const NOT_DEBUG_RETURN;
 109 
 110   // Collect buffers.  These functions are thread-safe.
 111   // precondition: Must not be concurrent with buffer processing.
 112   virtual void enqueue_completed_buffer(BufferNode* node);
 113   void merge_bufferlist(LocalQSet* src);
 114 
 115   // Processing phase operations.
 116   // precondition: Must not be concurrent with buffer collection.
 117   BufferNode* all_completed_buffers() const;
 118   G1BufferNodeList take_all_completed_buffers();
 119 };
 120 
 121 #endif // SHARE_GC_G1_G1REDIRTYCARDSQUEUE_HPP