hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.hpp
author duke
Sat, 01 Dec 2007 00:00:00 +0000
changeset 1 489c9b5090e2
child 5547 f4b087cbb361
permissions -rw-r--r--
Initial load
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
489c9b5090e2 Initial load
duke
parents:
diff changeset
     2
 * Copyright 2002-2007 Sun Microsystems, Inc.  All Rights Reserved.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    19
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    20
 * CA 95054 USA or visit www.sun.com if you need additional information or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    21
 * have any questions.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
489c9b5090e2 Initial load
duke
parents:
diff changeset
    25
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    26
// The GCTaskManager is a queue of GCTasks, and accessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
    27
// to allow the queue to be accessed from many threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    28
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    29
489c9b5090e2 Initial load
duke
parents:
diff changeset
    30
// Forward declarations of types defined in this file.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    31
class GCTask;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    32
class GCTaskQueue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    33
class SynchronizedGCTaskQueue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
class GCTaskManager;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
class NotifyDoneClosure;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
// Some useful subclasses of GCTask.  You can also make up your own.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
class NoopGCTask;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
class BarrierGCTask;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
class ReleasingBarrierGCTask;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
class NotifyingBarrierGCTask;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
class WaitForBarrierGCTask;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
// A free list of Monitor*'s.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
class MonitorSupply;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
// Forward declarations of classes referenced in this file via pointer.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
class GCTaskThread;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
class Mutex;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
class Monitor;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
class ThreadClosure;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
// The abstract base GCTask.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
class GCTask : public ResourceObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
  // Known kinds of GCTasks, for predicates.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
  class Kind : AllStatic {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
  public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
    enum kind {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
      unknown_task,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
      ordinary_task,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
      barrier_task,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
      noop_task
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
    };
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
    static const char* to_string(kind value);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
  // Instance state.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
  const Kind::kind _kind;               // For runtime type checking.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
  const uint       _affinity;           // Which worker should run task.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
  GCTask*          _newer;              // Tasks are on doubly-linked ...
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
  GCTask*          _older;              // ... lists.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
  virtual char* name() { return (char *)"task"; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
  // Abstract do_it method
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
  virtual void do_it(GCTaskManager* manager, uint which) = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
  // Accessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
  Kind::kind kind() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
    return _kind;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
  uint affinity() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
    return _affinity;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
  GCTask* newer() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
    return _newer;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
  void set_newer(GCTask* n) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
    _newer = n;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
  GCTask* older() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
    return _older;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
  void set_older(GCTask* p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
    _older = p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
  // Predicates.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
  bool is_ordinary_task() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
    return kind()==Kind::ordinary_task;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
  bool is_barrier_task() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
    return kind()==Kind::barrier_task;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
  bool is_noop_task() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
    return kind()==Kind::noop_task;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
  void print(const char* message) const PRODUCT_RETURN;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
  // Constructors: Only create subclasses.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
  //     An ordinary GCTask.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
  GCTask();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
  //     A GCTask of a particular kind, usually barrier or noop.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
  GCTask(Kind::kind kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
  //     An ordinary GCTask with an affinity.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
  GCTask(uint affinity);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
  //     A GCTask of a particular kind, with and affinity.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
  GCTask(Kind::kind kind, uint affinity);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
  // We want a virtual destructor because virtual methods,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
  // but since ResourceObj's don't have their destructors
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
  // called, we don't have one at all.  Instead we have
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
  // this method, which gets called by subclasses to clean up.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
  virtual void destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
  // Methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
  void initialize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
// A doubly-linked list of GCTasks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
// The list is not synchronized, because sometimes we want to
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
// build up a list and then make it available to other threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
// See also: SynchronizedGCTaskQueue.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
class GCTaskQueue : public ResourceObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
  // Instance state.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
  GCTask*    _insert_end;               // Tasks are enqueued at this end.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
  GCTask*    _remove_end;               // Tasks are dequeued from this end.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
  uint       _length;                   // The current length of the queue.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
  const bool _is_c_heap_obj;            // Is this a CHeapObj?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
  // Factory create and destroy methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
  //     Create as ResourceObj.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
  static GCTaskQueue* create();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
  //     Create as CHeapObj.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
  static GCTaskQueue* create_on_c_heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
  //     Destroyer.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
  static void destroy(GCTaskQueue* that);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
  // Accessors.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
  //     These just examine the state of the queue.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
  bool is_empty() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
    assert(((insert_end() == NULL && remove_end() == NULL) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
            (insert_end() != NULL && remove_end() != NULL)),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
           "insert_end and remove_end don't match");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
    return insert_end() == NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
  uint length() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
    return _length;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
  // Methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
  //     Enqueue one task.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
  void enqueue(GCTask* task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
  //     Enqueue a list of tasks.  Empties the argument list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
  void enqueue(GCTaskQueue* list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
  //     Dequeue one task.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
  GCTask* dequeue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
  //     Dequeue one task, preferring one with affinity.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
  GCTask* dequeue(uint affinity);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
  // Constructor. Clients use factory, but there might be subclasses.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
  GCTaskQueue(bool on_c_heap);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
  // Destructor-like method.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
  // Because ResourceMark doesn't call destructors.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
  // This method cleans up like one.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
  virtual void destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
  // Accessors.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
  GCTask* insert_end() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
    return _insert_end;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
  void set_insert_end(GCTask* value) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
    _insert_end = value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
  GCTask* remove_end() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
    return _remove_end;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
  void set_remove_end(GCTask* value) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
    _remove_end = value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
  void increment_length() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
    _length += 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
  void decrement_length() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
    _length -= 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
  void set_length(uint value) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
    _length = value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
  bool is_c_heap_obj() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
    return _is_c_heap_obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
  // Methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
  void initialize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
  GCTask* remove();                     // Remove from remove end.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
  GCTask* remove(GCTask* task);         // Remove from the middle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
  void print(const char* message) const PRODUCT_RETURN;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
// A GCTaskQueue that can be synchronized.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
// This "has-a" GCTaskQueue and a mutex to do the exclusion.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
class SynchronizedGCTaskQueue : public CHeapObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
  // Instance state.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
  GCTaskQueue* _unsynchronized_queue;   // Has-a unsynchronized queue.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
  Monitor *    _lock;                   // Lock to control access.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
  // Factory create and destroy methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
  static SynchronizedGCTaskQueue* create(GCTaskQueue* queue, Monitor * lock) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
    return new SynchronizedGCTaskQueue(queue, lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
  static void destroy(SynchronizedGCTaskQueue* that) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
    if (that != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
      delete that;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
  // Accessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
  GCTaskQueue* unsynchronized_queue() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
    return _unsynchronized_queue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
  Monitor * lock() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
    return _lock;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
  // GCTaskQueue wrapper methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   228
  // These check that you hold the lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
   229
  // and then call the method on the queue.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   230
  bool is_empty() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   231
    guarantee(own_lock(), "don't own the lock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   232
    return unsynchronized_queue()->is_empty();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   233
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   234
  void enqueue(GCTask* task) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   235
    guarantee(own_lock(), "don't own the lock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
    unsynchronized_queue()->enqueue(task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
  void enqueue(GCTaskQueue* list) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
    guarantee(own_lock(), "don't own the lock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   240
    unsynchronized_queue()->enqueue(list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
  GCTask* dequeue() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   243
    guarantee(own_lock(), "don't own the lock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   244
    return unsynchronized_queue()->dequeue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   245
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
  GCTask* dequeue(uint affinity) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   247
    guarantee(own_lock(), "don't own the lock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   248
    return unsynchronized_queue()->dequeue(affinity);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   249
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   250
  uint length() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   251
    guarantee(own_lock(), "don't own the lock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   252
    return unsynchronized_queue()->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   253
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   254
  // For guarantees.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   255
  bool own_lock() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
    return lock()->owned_by_self();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
  // Constructor.  Clients use factory, but there might be subclasses.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
  SynchronizedGCTaskQueue(GCTaskQueue* queue, Monitor * lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
  // Destructor.  Not virtual because no virtuals.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   262
  ~SynchronizedGCTaskQueue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
// This is an abstract base class for getting notifications
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
// when a GCTaskManager is done.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
class NotifyDoneClosure : public CHeapObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
  // The notification callback method.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
  virtual void notify(GCTaskManager* manager) = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
  // Constructor.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
  NotifyDoneClosure() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
    // Nothing to do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
  // Virtual destructor because virtual methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
  virtual ~NotifyDoneClosure() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
    // Nothing to do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
class GCTaskManager : public CHeapObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
 friend class ParCompactionManager;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
 friend class PSParallelCompact;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
 friend class PSScavenge;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
 friend class PSRefProcTaskExecutor;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
 friend class RefProcTaskExecutor;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
  // Instance state.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
  NotifyDoneClosure*        _ndc;               // Notify on completion.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
  const uint                _workers;           // Number of workers.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
  Monitor*                  _monitor;           // Notification of changes.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
  SynchronizedGCTaskQueue*  _queue;             // Queue of tasks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
  GCTaskThread**            _thread;            // Array of worker threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
  uint                      _busy_workers;      // Number of busy workers.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
  uint                      _blocking_worker;   // The worker that's blocking.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
  bool*                     _resource_flag;     // Array of flag per threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
  uint                      _delivered_tasks;   // Count of delivered tasks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
  uint                      _completed_tasks;   // Count of completed tasks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
  uint                      _barriers;          // Count of barrier tasks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
  uint                      _emptied_queue;     // Times we emptied the queue.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
  NoopGCTask*               _noop_task;         // The NoopGCTask instance.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
  uint                      _noop_tasks;        // Count of noop tasks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
  // Factory create and destroy methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
  static GCTaskManager* create(uint workers) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
    return new GCTaskManager(workers);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   309
  static GCTaskManager* create(uint workers, NotifyDoneClosure* ndc) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
    return new GCTaskManager(workers, ndc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
  static void destroy(GCTaskManager* that) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
    if (that != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
      delete that;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   316
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   317
  // Accessors.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   318
  uint busy_workers() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   319
    return _busy_workers;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   321
  //     Pun between Monitor* and Mutex*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   322
  Monitor* monitor() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   323
    return _monitor;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
  Monitor * lock() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
    return _monitor;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   328
  // Methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   329
  //     Add the argument task to be run.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   330
  void add_task(GCTask* task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   331
  //     Add a list of tasks.  Removes task from the argument list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
  void add_list(GCTaskQueue* list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   333
  //     Claim a task for argument worker.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
  GCTask* get_task(uint which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
  //     Note the completion of a task by the argument worker.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
  void note_completion(uint which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
  //     Is the queue blocked from handing out new tasks?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
  bool is_blocked() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
    return (blocking_worker() != sentinel_worker());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
  //     Request that all workers release their resources.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
  void release_all_resources();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
  //     Ask if a particular worker should release its resources.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
  bool should_release_resources(uint which); // Predicate.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
  //     Note the release of resources by the argument worker.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
  void note_release(uint which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
  // Constants.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
  //     A sentinel worker identifier.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
  static uint sentinel_worker() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
    return (uint) -1;                   // Why isn't there a max_uint?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
  //     Execute the task queue and wait for the completion.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
  void execute_and_wait(GCTaskQueue* list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
  void print_task_time_stamps();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
  void print_threads_on(outputStream* st);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
  void threads_do(ThreadClosure* tc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
  // Constructors.  Clients use factory, but there might be subclasses.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
  //     Create a GCTaskManager with the appropriate number of workers.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
  GCTaskManager(uint workers);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
  //     Create a GCTaskManager that calls back when there's no more work.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
  GCTaskManager(uint workers, NotifyDoneClosure* ndc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
  //     Make virtual if necessary.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
  ~GCTaskManager();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
  // Accessors.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
  uint workers() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
    return _workers;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
  NotifyDoneClosure* notify_done_closure() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
    return _ndc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
  SynchronizedGCTaskQueue* queue() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
    return _queue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
  NoopGCTask* noop_task() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
    return _noop_task;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
  //     Bounds-checking per-thread data accessors.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
  GCTaskThread* thread(uint which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
  void set_thread(uint which, GCTaskThread* value);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
  bool resource_flag(uint which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
  void set_resource_flag(uint which, bool value);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   386
  // Modifier methods with some semantics.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   387
  //     Is any worker blocking handing out new tasks?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   388
  uint blocking_worker() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   389
    return _blocking_worker;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   390
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   391
  void set_blocking_worker(uint value) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   392
    _blocking_worker = value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   393
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
  void set_unblocked() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
    set_blocking_worker(sentinel_worker());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
  //     Count of busy workers.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
  void reset_busy_workers() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
    _busy_workers = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   401
  uint increment_busy_workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   402
  uint decrement_busy_workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   403
  //     Count of tasks delivered to workers.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   404
  uint delivered_tasks() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   405
    return _delivered_tasks;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   406
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   407
  void increment_delivered_tasks() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   408
    _delivered_tasks += 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   409
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   410
  void reset_delivered_tasks() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   411
    _delivered_tasks = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   412
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   413
  //     Count of tasks completed by workers.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   414
  uint completed_tasks() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   415
    return _completed_tasks;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   416
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   417
  void increment_completed_tasks() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   418
    _completed_tasks += 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   419
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   420
  void reset_completed_tasks() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   421
    _completed_tasks = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   422
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   423
  //     Count of barrier tasks completed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   424
  uint barriers() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   425
    return _barriers;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   426
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   427
  void increment_barriers() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   428
    _barriers += 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   429
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   430
  void reset_barriers() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   431
    _barriers = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   432
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   433
  //     Count of how many times the queue has emptied.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   434
  uint emptied_queue() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   435
    return _emptied_queue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   436
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   437
  void increment_emptied_queue() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   438
    _emptied_queue += 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   439
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   440
  void reset_emptied_queue() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   441
    _emptied_queue = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   442
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   443
  //     Count of the number of noop tasks we've handed out,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   444
  //     e.g., to handle resource release requests.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   445
  uint noop_tasks() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   446
    return _noop_tasks;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   447
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   448
  void increment_noop_tasks() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   449
    _noop_tasks += 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   450
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   451
  void reset_noop_tasks() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   452
    _noop_tasks = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   453
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   454
  // Other methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   455
  void initialize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   456
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   457
489c9b5090e2 Initial load
duke
parents:
diff changeset
   458
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   459
// Some exemplary GCTasks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   460
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   461
489c9b5090e2 Initial load
duke
parents:
diff changeset
   462
// A noop task that does nothing,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   463
// except take us around the GCTaskThread loop.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   464
class NoopGCTask : public GCTask {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   465
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   466
  const bool _is_c_heap_obj;            // Is this a CHeapObj?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   467
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   468
  // Factory create and destroy methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   469
  static NoopGCTask* create();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   470
  static NoopGCTask* create_on_c_heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   471
  static void destroy(NoopGCTask* that);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   472
  // Methods from GCTask.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   473
  void do_it(GCTaskManager* manager, uint which) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   474
    // Nothing to do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   475
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   476
protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   477
  // Constructor.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   478
  NoopGCTask(bool on_c_heap) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   479
    GCTask(GCTask::Kind::noop_task),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   480
    _is_c_heap_obj(on_c_heap) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   481
    // Nothing to do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   482
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   483
  // Destructor-like method.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   484
  void destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   485
  // Accessors.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   486
  bool is_c_heap_obj() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   487
    return _is_c_heap_obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   488
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   489
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   490
489c9b5090e2 Initial load
duke
parents:
diff changeset
   491
// A BarrierGCTask blocks other tasks from starting,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   492
// and waits until it is the only task running.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   493
class BarrierGCTask : public GCTask {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   494
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   495
  // Factory create and destroy methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   496
  static BarrierGCTask* create() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   497
    return new BarrierGCTask();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   498
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   499
  static void destroy(BarrierGCTask* that) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   500
    if (that != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   501
      that->destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   502
      delete that;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   503
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   504
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   505
  // Methods from GCTask.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   506
  void do_it(GCTaskManager* manager, uint which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   507
protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   508
  // Constructor.  Clients use factory, but there might be subclasses.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   509
  BarrierGCTask() :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   510
    GCTask(GCTask::Kind::barrier_task) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   511
    // Nothing to do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   512
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   513
  // Destructor-like method.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   514
  void destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   515
  // Methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   516
  //     Wait for this to be the only task running.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   517
  void do_it_internal(GCTaskManager* manager, uint which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   518
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   519
489c9b5090e2 Initial load
duke
parents:
diff changeset
   520
// A ReleasingBarrierGCTask is a BarrierGCTask
489c9b5090e2 Initial load
duke
parents:
diff changeset
   521
// that tells all the tasks to release their resource areas.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   522
class ReleasingBarrierGCTask : public BarrierGCTask {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   523
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   524
  // Factory create and destroy methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   525
  static ReleasingBarrierGCTask* create() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   526
    return new ReleasingBarrierGCTask();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   527
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   528
  static void destroy(ReleasingBarrierGCTask* that) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   529
    if (that != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   530
      that->destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   531
      delete that;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   532
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   533
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   534
  // Methods from GCTask.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   535
  void do_it(GCTaskManager* manager, uint which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   536
protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   537
  // Constructor.  Clients use factory, but there might be subclasses.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   538
  ReleasingBarrierGCTask() :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   539
    BarrierGCTask() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   540
    // Nothing to do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   541
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   542
  // Destructor-like method.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   543
  void destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   544
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   545
489c9b5090e2 Initial load
duke
parents:
diff changeset
   546
// A NotifyingBarrierGCTask is a BarrierGCTask
489c9b5090e2 Initial load
duke
parents:
diff changeset
   547
// that calls a notification method when it is the only task running.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   548
class NotifyingBarrierGCTask : public BarrierGCTask {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   549
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   550
  // Instance state.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   551
  NotifyDoneClosure* _ndc;              // The callback object.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   552
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   553
  // Factory create and destroy methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   554
  static NotifyingBarrierGCTask* create(NotifyDoneClosure* ndc) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   555
    return new NotifyingBarrierGCTask(ndc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   556
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   557
  static void destroy(NotifyingBarrierGCTask* that) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   558
    if (that != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   559
      that->destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   560
      delete that;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   561
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   562
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   563
  // Methods from GCTask.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   564
  void do_it(GCTaskManager* manager, uint which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   565
protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   566
  // Constructor.  Clients use factory, but there might be subclasses.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   567
  NotifyingBarrierGCTask(NotifyDoneClosure* ndc) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   568
    BarrierGCTask(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   569
    _ndc(ndc) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   570
    assert(notify_done_closure() != NULL, "can't notify on NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   571
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   572
  // Destructor-like method.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   573
  void destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   574
  // Accessor.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   575
  NotifyDoneClosure* notify_done_closure() const { return _ndc; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   576
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   577
489c9b5090e2 Initial load
duke
parents:
diff changeset
   578
// A WaitForBarrierGCTask is a BarrierGCTask
489c9b5090e2 Initial load
duke
parents:
diff changeset
   579
// with a method you can call to wait until
489c9b5090e2 Initial load
duke
parents:
diff changeset
   580
// the BarrierGCTask is done.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   581
// This may cover many of the uses of NotifyingBarrierGCTasks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   582
class WaitForBarrierGCTask : public BarrierGCTask {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   583
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   584
  // Instance state.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   585
  Monitor*   _monitor;                  // Guard and notify changes.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   586
  bool       _should_wait;              // true=>wait, false=>proceed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   587
  const bool _is_c_heap_obj;            // Was allocated on the heap.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   588
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   589
  virtual char* name() { return (char *) "waitfor-barrier-task"; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   590
489c9b5090e2 Initial load
duke
parents:
diff changeset
   591
  // Factory create and destroy methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   592
  static WaitForBarrierGCTask* create();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   593
  static WaitForBarrierGCTask* create_on_c_heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   594
  static void destroy(WaitForBarrierGCTask* that);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   595
  // Methods.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   596
  void     do_it(GCTaskManager* manager, uint which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   597
  void     wait_for();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   598
protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   599
  // Constructor.  Clients use factory, but there might be subclasses.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   600
  WaitForBarrierGCTask(bool on_c_heap);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   601
  // Destructor-like method.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   602
  void destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   603
  // Accessors.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   604
  Monitor* monitor() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   605
    return _monitor;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   606
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   607
  bool should_wait() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   608
    return _should_wait;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   609
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   610
  void set_should_wait(bool value) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   611
    _should_wait = value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   612
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   613
  bool is_c_heap_obj() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   614
    return _is_c_heap_obj;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   615
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   616
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   617
489c9b5090e2 Initial load
duke
parents:
diff changeset
   618
class MonitorSupply : public AllStatic {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   619
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   620
  // State.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   621
  //     Control multi-threaded access.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   622
  static Mutex*                   _lock;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   623
  //     The list of available Monitor*'s.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   624
  static GrowableArray<Monitor*>* _freelist;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   625
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   626
  // Reserve a Monitor*.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   627
  static Monitor* reserve();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   628
  // Release a Monitor*.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   629
  static void release(Monitor* instance);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   630
private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   631
  // Accessors.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   632
  static Mutex* lock() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   633
    return _lock;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   634
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   635
  static GrowableArray<Monitor*>* freelist() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   636
    return _freelist;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   637
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   638
};