hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp
author apetrusenko
Wed, 16 Apr 2008 12:58:03 +0400
changeset 387 6b17ecb32336
parent 1 489c9b5090e2
child 5547 f4b087cbb361
permissions -rw-r--r--
Merge
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
#include "incls/_precompiled.incl"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    26
#include "incls/_gcTaskManager.cpp.incl"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    27
489c9b5090e2 Initial load
duke
parents:
diff changeset
    28
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    29
// GCTask
489c9b5090e2 Initial load
duke
parents:
diff changeset
    30
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    31
489c9b5090e2 Initial load
duke
parents:
diff changeset
    32
const char* GCTask::Kind::to_string(kind value) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    33
  const char* result = "unknown GCTask kind";
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
  switch (value) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
  default:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
    result = "unknown GCTask kind";
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
    break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
  case unknown_task:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
    result = "unknown task";
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
    break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
  case ordinary_task:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
    result = "ordinary task";
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
    break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
  case barrier_task:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
    result = "barrier task";
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
    break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
  case noop_task:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
    result = "noop task";
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
    break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
GCTask::GCTask() :
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
  _kind(Kind::ordinary_task),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
  _affinity(GCTaskManager::sentinel_worker()){
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
  initialize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
GCTask::GCTask(Kind::kind kind) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
  _kind(kind),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
  _affinity(GCTaskManager::sentinel_worker()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
  initialize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
GCTask::GCTask(uint affinity) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
  _kind(Kind::ordinary_task),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
  _affinity(affinity) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
  initialize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
GCTask::GCTask(Kind::kind kind, uint affinity) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
  _kind(kind),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
  _affinity(affinity) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
  initialize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
void GCTask::initialize() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
  _older = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
  _newer = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
void GCTask::destruct() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
  assert(older() == NULL, "shouldn't have an older task");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
  assert(newer() == NULL, "shouldn't have a newer task");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
  // Nothing to do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
void GCTask::print(const char* message) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
  tty->print(INTPTR_FORMAT " <- " INTPTR_FORMAT "(%u) -> " INTPTR_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
             newer(), this, affinity(), older());
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
// GCTaskQueue
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
GCTaskQueue* GCTaskQueue::create() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
  GCTaskQueue* result = new GCTaskQueue(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
  if (TraceGCTaskQueue) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
    tty->print_cr("GCTaskQueue::create()"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
                  " returns " INTPTR_FORMAT, result);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
GCTaskQueue* GCTaskQueue::create_on_c_heap() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
  GCTaskQueue* result = new(ResourceObj::C_HEAP) GCTaskQueue(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
  if (TraceGCTaskQueue) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
    tty->print_cr("GCTaskQueue::create_on_c_heap()"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
                  " returns " INTPTR_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
                  result);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
GCTaskQueue::GCTaskQueue(bool on_c_heap) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
  _is_c_heap_obj(on_c_heap) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
  initialize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
  if (TraceGCTaskQueue) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
    tty->print_cr("[" INTPTR_FORMAT "]"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
                  " GCTaskQueue::GCTaskQueue() constructor",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
                  this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
void GCTaskQueue::destruct() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
  // Nothing to do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
void GCTaskQueue::destroy(GCTaskQueue* that) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
  if (TraceGCTaskQueue) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
    tty->print_cr("[" INTPTR_FORMAT "]"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
                  " GCTaskQueue::destroy()"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
                  "  is_c_heap_obj:  %s",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
                  that,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
                  that->is_c_heap_obj() ? "true" : "false");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
  // That instance may have been allocated as a CHeapObj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
  // in which case we have to free it explicitly.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
  if (that != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
    that->destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
    assert(that->is_empty(), "should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
    if (that->is_c_heap_obj()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
      FreeHeap(that);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
void GCTaskQueue::initialize() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
  set_insert_end(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
  set_remove_end(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
  set_length(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
// Enqueue one task.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
void GCTaskQueue::enqueue(GCTask* task) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
  if (TraceGCTaskQueue) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
    tty->print_cr("[" INTPTR_FORMAT "]"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
                  " GCTaskQueue::enqueue(task: "
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
                  INTPTR_FORMAT ")",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
                  this, task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
    print("before:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
  assert(task != NULL, "shouldn't have null task");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
  assert(task->older() == NULL, "shouldn't be on queue");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
  assert(task->newer() == NULL, "shouldn't be on queue");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
  task->set_newer(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
  task->set_older(insert_end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
  if (is_empty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
    set_remove_end(task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
    insert_end()->set_newer(task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
  set_insert_end(task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
  increment_length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
  if (TraceGCTaskQueue) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
    print("after:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
// Enqueue a whole list of tasks.  Empties the argument list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
void GCTaskQueue::enqueue(GCTaskQueue* list) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
  if (TraceGCTaskQueue) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
    tty->print_cr("[" INTPTR_FORMAT "]"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
                  " GCTaskQueue::enqueue(list: "
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
                  INTPTR_FORMAT ")",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
                  this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
    print("before:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
    list->print("list:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
  if (list->is_empty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
    // Enqueuing the empty list: nothing to do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
  uint list_length = list->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
  if (is_empty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
    // Enqueuing to empty list: just acquire elements.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
    set_insert_end(list->insert_end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
    set_remove_end(list->remove_end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
    set_length(list_length);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
    // Prepend argument list to our queue.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
    list->remove_end()->set_older(insert_end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
    insert_end()->set_newer(list->remove_end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
    set_insert_end(list->insert_end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
    // empty the argument list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
  set_length(length() + list_length);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
  list->initialize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
  if (TraceGCTaskQueue) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
    print("after:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
    list->print("list:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
// Dequeue one task.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
GCTask* GCTaskQueue::dequeue() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
  if (TraceGCTaskQueue) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
    tty->print_cr("[" INTPTR_FORMAT "]"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
                  " GCTaskQueue::dequeue()", this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
    print("before:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
  assert(!is_empty(), "shouldn't dequeue from empty list");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
  GCTask* result = remove();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   228
  assert(result != NULL, "shouldn't have NULL task");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   229
  if (TraceGCTaskQueue) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   230
    tty->print_cr("    return: " INTPTR_FORMAT, result);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   231
    print("after:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   232
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   233
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   234
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   235
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
// Dequeue one task, preferring one with affinity.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
GCTask* GCTaskQueue::dequeue(uint affinity) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
  if (TraceGCTaskQueue) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
    tty->print_cr("[" INTPTR_FORMAT "]"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   240
                  " GCTaskQueue::dequeue(%u)", this, affinity);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
    print("before:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   243
  assert(!is_empty(), "shouldn't dequeue from empty list");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   244
  // Look down to the next barrier for a task with this affinity.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   245
  GCTask* result = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
  for (GCTask* element = remove_end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   247
       element != NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   248
       element = element->newer()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   249
    if (element->is_barrier_task()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   250
      // Don't consider barrier tasks, nor past them.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   251
      result = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   252
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   253
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   254
    if (element->affinity() == affinity) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   255
      result = remove(element);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
  // If we didn't find anything with affinity, just take the next task.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
  if (result == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
    result = remove();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   262
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
  if (TraceGCTaskQueue) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
    tty->print_cr("    return: " INTPTR_FORMAT, result);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
    print("after:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
GCTask* GCTaskQueue::remove() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
  // Dequeue from remove end.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
  GCTask* result = remove_end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
  assert(result != NULL, "shouldn't have null task");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
  assert(result->older() == NULL, "not the remove_end");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
  set_remove_end(result->newer());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
  if (remove_end() == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
    assert(insert_end() == result, "not a singleton");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
    set_insert_end(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
    remove_end()->set_older(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
  result->set_newer(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
  decrement_length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
  assert(result->newer() == NULL, "shouldn't be on queue");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
  assert(result->older() == NULL, "shouldn't be on queue");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
GCTask* GCTaskQueue::remove(GCTask* task) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
  // This is slightly more work, and has slightly fewer asserts
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
  // than removing from the remove end.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
  assert(task != NULL, "shouldn't have null task");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
  GCTask* result = task;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
  if (result->newer() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
    result->newer()->set_older(result->older());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
    assert(insert_end() == result, "not youngest");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
    set_insert_end(result->older());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
  if (result->older() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
    result->older()->set_newer(result->newer());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
    assert(remove_end() == result, "not oldest");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
    set_remove_end(result->newer());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
  result->set_newer(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
  result->set_older(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
  decrement_length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   309
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
void GCTaskQueue::print(const char* message) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
  tty->print_cr("[" INTPTR_FORMAT "] GCTaskQueue:"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
                "  insert_end: " INTPTR_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   316
                "  remove_end: " INTPTR_FORMAT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   317
                "  %s",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   318
                this, insert_end(), remove_end(), message);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   319
  for (GCTask* element = insert_end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
       element != NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   321
       element = element->older()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   322
    element->print("    ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   323
    tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
489c9b5090e2 Initial load
duke
parents:
diff changeset
   328
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   329
// SynchronizedGCTaskQueue
489c9b5090e2 Initial load
duke
parents:
diff changeset
   330
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   331
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
SynchronizedGCTaskQueue::SynchronizedGCTaskQueue(GCTaskQueue* queue_arg,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   333
                                                 Monitor *       lock_arg) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
  _unsynchronized_queue(queue_arg),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
  _lock(lock_arg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
  assert(unsynchronized_queue() != NULL, "null queue");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
  assert(lock() != NULL, "null lock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
SynchronizedGCTaskQueue::~SynchronizedGCTaskQueue() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
  // Nothing to do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
// GCTaskManager
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
GCTaskManager::GCTaskManager(uint workers) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
  _workers(workers),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
  _ndc(NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
  initialize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
GCTaskManager::GCTaskManager(uint workers, NotifyDoneClosure* ndc) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
  _workers(workers),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
  _ndc(ndc) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
  initialize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
void GCTaskManager::initialize() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
  if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
    tty->print_cr("GCTaskManager::initialize: workers: %u", workers());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
  assert(workers() != 0, "no workers");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
  _monitor = new Monitor(Mutex::barrier,                // rank
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
                         "GCTaskManager monitor",       // name
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
                         Mutex::_allow_vm_block_flag);  // allow_vm_block
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
  // The queue for the GCTaskManager must be a CHeapObj.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
  GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
  _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
  _noop_task = NoopGCTask::create_on_c_heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
  _resource_flag = NEW_C_HEAP_ARRAY(bool, workers());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
    // Set up worker threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
    //     Distribute the workers among the available processors,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
    //     unless we were told not to, or if the os doesn't want to.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
    uint* processor_assignment = NEW_C_HEAP_ARRAY(uint, workers());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
    if (!BindGCTaskThreadsToCPUs ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
        !os::distribute_processes(workers(), processor_assignment)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
      for (uint a = 0; a < workers(); a += 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
        processor_assignment[a] = sentinel_worker();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
    _thread = NEW_C_HEAP_ARRAY(GCTaskThread*, workers());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
    for (uint t = 0; t < workers(); t += 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
      set_thread(t, GCTaskThread::create(this, t, processor_assignment[t]));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   386
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   387
    if (TraceGCTaskThread) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   388
      tty->print("GCTaskManager::initialize: distribution:");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   389
      for (uint t = 0; t < workers(); t += 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   390
        tty->print("  %u", processor_assignment[t]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   391
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   392
      tty->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   393
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
    FREE_C_HEAP_ARRAY(uint, processor_assignment);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
  reset_busy_workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
  set_unblocked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
  for (uint w = 0; w < workers(); w += 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
    set_resource_flag(w, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   401
  reset_delivered_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   402
  reset_completed_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   403
  reset_noop_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   404
  reset_barriers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   405
  reset_emptied_queue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   406
  for (uint s = 0; s < workers(); s += 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   407
    thread(s)->start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   408
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   409
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   410
489c9b5090e2 Initial load
duke
parents:
diff changeset
   411
GCTaskManager::~GCTaskManager() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   412
  assert(busy_workers() == 0, "still have busy workers");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   413
  assert(queue()->is_empty(), "still have queued work");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   414
  NoopGCTask::destroy(_noop_task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   415
  _noop_task = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   416
  if (_thread != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   417
    for (uint i = 0; i < workers(); i += 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   418
      GCTaskThread::destroy(thread(i));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   419
      set_thread(i, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   420
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   421
    FREE_C_HEAP_ARRAY(GCTaskThread*, _thread);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   422
    _thread = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   423
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   424
  if (_resource_flag != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   425
    FREE_C_HEAP_ARRAY(bool, _resource_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   426
    _resource_flag = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   427
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   428
  if (queue() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   429
    GCTaskQueue* unsynchronized_queue = queue()->unsynchronized_queue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   430
    GCTaskQueue::destroy(unsynchronized_queue);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   431
    SynchronizedGCTaskQueue::destroy(queue());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   432
    _queue = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   433
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   434
  if (monitor() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   435
    delete monitor();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   436
    _monitor = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   437
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   438
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   439
489c9b5090e2 Initial load
duke
parents:
diff changeset
   440
void GCTaskManager::print_task_time_stamps() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   441
  for(uint i=0; i<ParallelGCThreads; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   442
    GCTaskThread* t = thread(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   443
    t->print_task_time_stamps();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   444
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   445
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   446
489c9b5090e2 Initial load
duke
parents:
diff changeset
   447
void GCTaskManager::print_threads_on(outputStream* st) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   448
  uint num_thr = workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   449
  for (uint i = 0; i < num_thr; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   450
    thread(i)->print_on(st);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   451
    st->cr();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   452
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   453
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   454
489c9b5090e2 Initial load
duke
parents:
diff changeset
   455
void GCTaskManager::threads_do(ThreadClosure* tc) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   456
  assert(tc != NULL, "Null ThreadClosure");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   457
  uint num_thr = workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   458
  for (uint i = 0; i < num_thr; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   459
    tc->do_thread(thread(i));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   460
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   461
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   462
489c9b5090e2 Initial load
duke
parents:
diff changeset
   463
GCTaskThread* GCTaskManager::thread(uint which) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   464
  assert(which < workers(), "index out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   465
  assert(_thread[which] != NULL, "shouldn't have null thread");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   466
  return _thread[which];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   467
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   468
489c9b5090e2 Initial load
duke
parents:
diff changeset
   469
void GCTaskManager::set_thread(uint which, GCTaskThread* value) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   470
  assert(which < workers(), "index out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   471
  assert(value != NULL, "shouldn't have null thread");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   472
  _thread[which] = value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   473
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   474
489c9b5090e2 Initial load
duke
parents:
diff changeset
   475
void GCTaskManager::add_task(GCTask* task) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   476
  assert(task != NULL, "shouldn't have null task");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   477
  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   478
  if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   479
    tty->print_cr("GCTaskManager::add_task(" INTPTR_FORMAT " [%s])",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   480
                  task, GCTask::Kind::to_string(task->kind()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   481
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   482
  queue()->enqueue(task);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   483
  // Notify with the lock held to avoid missed notifies.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   484
  if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   485
    tty->print_cr("    GCTaskManager::add_task (%s)->notify_all",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   486
                  monitor()->name());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   487
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   488
  (void) monitor()->notify_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   489
  // Release monitor().
489c9b5090e2 Initial load
duke
parents:
diff changeset
   490
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   491
489c9b5090e2 Initial load
duke
parents:
diff changeset
   492
void GCTaskManager::add_list(GCTaskQueue* list) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   493
  assert(list != NULL, "shouldn't have null task");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   494
  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   495
  if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   496
    tty->print_cr("GCTaskManager::add_list(%u)", list->length());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   497
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   498
  queue()->enqueue(list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   499
  // Notify with the lock held to avoid missed notifies.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   500
  if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   501
    tty->print_cr("    GCTaskManager::add_list (%s)->notify_all",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   502
                  monitor()->name());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   503
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   504
  (void) monitor()->notify_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   505
  // Release monitor().
489c9b5090e2 Initial load
duke
parents:
diff changeset
   506
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   507
489c9b5090e2 Initial load
duke
parents:
diff changeset
   508
GCTask* GCTaskManager::get_task(uint which) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   509
  GCTask* result = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   510
  // Grab the queue lock.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   511
  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   512
  // Wait while the queue is block or
489c9b5090e2 Initial load
duke
parents:
diff changeset
   513
  // there is nothing to do, except maybe release resources.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   514
  while (is_blocked() ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   515
         (queue()->is_empty() && !should_release_resources(which))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   516
    if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   517
      tty->print_cr("GCTaskManager::get_task(%u)"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   518
                    "  blocked: %s"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   519
                    "  empty: %s"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   520
                    "  release: %s",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   521
                    which,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   522
                    is_blocked() ? "true" : "false",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   523
                    queue()->is_empty() ? "true" : "false",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   524
                    should_release_resources(which) ? "true" : "false");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   525
      tty->print_cr("    => (%s)->wait()",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   526
                    monitor()->name());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   527
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   528
    monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   529
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   530
  // We've reacquired the queue lock here.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   531
  // Figure out which condition caused us to exit the loop above.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   532
  if (!queue()->is_empty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   533
    if (UseGCTaskAffinity) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   534
      result = queue()->dequeue(which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   535
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   536
      result = queue()->dequeue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   537
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   538
    if (result->is_barrier_task()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   539
      assert(which != sentinel_worker(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   540
             "blocker shouldn't be bogus");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   541
      set_blocking_worker(which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   542
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   543
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   544
    // The queue is empty, but we were woken up.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   545
    // Just hand back a Noop task,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   546
    // in case someone wanted us to release resources, or whatever.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   547
    result = noop_task();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   548
    increment_noop_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   549
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   550
  assert(result != NULL, "shouldn't have null task");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   551
  if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   552
    tty->print_cr("GCTaskManager::get_task(%u) => " INTPTR_FORMAT " [%s]",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   553
                  which, result, GCTask::Kind::to_string(result->kind()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   554
    tty->print_cr("     %s", result->name());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   555
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   556
  increment_busy_workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   557
  increment_delivered_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   558
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   559
  // Release monitor().
489c9b5090e2 Initial load
duke
parents:
diff changeset
   560
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   561
489c9b5090e2 Initial load
duke
parents:
diff changeset
   562
void GCTaskManager::note_completion(uint which) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   563
  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   564
  if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   565
    tty->print_cr("GCTaskManager::note_completion(%u)", which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   566
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   567
  // If we are blocked, check if the completing thread is the blocker.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   568
  if (blocking_worker() == which) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   569
    assert(blocking_worker() != sentinel_worker(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   570
           "blocker shouldn't be bogus");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   571
    increment_barriers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   572
    set_unblocked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   573
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   574
  increment_completed_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   575
  uint active = decrement_busy_workers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   576
  if ((active == 0) && (queue()->is_empty())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   577
    increment_emptied_queue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   578
    if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   579
      tty->print_cr("    GCTaskManager::note_completion(%u) done", which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   580
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   581
    // Notify client that we are done.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   582
    NotifyDoneClosure* ndc = notify_done_closure();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   583
    if (ndc != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   584
      ndc->notify(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   585
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   586
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   587
  if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   588
    tty->print_cr("    GCTaskManager::note_completion(%u) (%s)->notify_all",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   589
                  which, monitor()->name());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   590
    tty->print_cr("  "
489c9b5090e2 Initial load
duke
parents:
diff changeset
   591
                  "  blocked: %s"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   592
                  "  empty: %s"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   593
                  "  release: %s",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   594
                  is_blocked() ? "true" : "false",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   595
                  queue()->is_empty() ? "true" : "false",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   596
                  should_release_resources(which) ? "true" : "false");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   597
    tty->print_cr("  "
489c9b5090e2 Initial load
duke
parents:
diff changeset
   598
                  "  delivered: %u"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   599
                  "  completed: %u"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   600
                  "  barriers: %u"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   601
                  "  emptied: %u",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   602
                  delivered_tasks(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   603
                  completed_tasks(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   604
                  barriers(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   605
                  emptied_queue());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   606
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   607
  // Tell everyone that a task has completed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   608
  (void) monitor()->notify_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   609
  // Release monitor().
489c9b5090e2 Initial load
duke
parents:
diff changeset
   610
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   611
489c9b5090e2 Initial load
duke
parents:
diff changeset
   612
uint GCTaskManager::increment_busy_workers() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   613
  assert(queue()->own_lock(), "don't own the lock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   614
  _busy_workers += 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   615
  return _busy_workers;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   616
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   617
489c9b5090e2 Initial load
duke
parents:
diff changeset
   618
uint GCTaskManager::decrement_busy_workers() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   619
  assert(queue()->own_lock(), "don't own the lock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   620
  _busy_workers -= 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   621
  return _busy_workers;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   622
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   623
489c9b5090e2 Initial load
duke
parents:
diff changeset
   624
void GCTaskManager::release_all_resources() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   625
  // If you want this to be done atomically, do it in a BarrierGCTask.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   626
  for (uint i = 0; i < workers(); i += 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   627
    set_resource_flag(i, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   628
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   629
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   630
489c9b5090e2 Initial load
duke
parents:
diff changeset
   631
bool GCTaskManager::should_release_resources(uint which) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   632
  // This can be done without a lock because each thread reads one element.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   633
  return resource_flag(which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   634
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   635
489c9b5090e2 Initial load
duke
parents:
diff changeset
   636
void GCTaskManager::note_release(uint which) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   637
  // This can be done without a lock because each thread writes one element.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   638
  set_resource_flag(which, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   639
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   640
489c9b5090e2 Initial load
duke
parents:
diff changeset
   641
void GCTaskManager::execute_and_wait(GCTaskQueue* list) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   642
  WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   643
  list->enqueue(fin);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   644
  add_list(list);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   645
  fin->wait_for();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   646
  // We have to release the barrier tasks!
489c9b5090e2 Initial load
duke
parents:
diff changeset
   647
  WaitForBarrierGCTask::destroy(fin);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   648
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   649
489c9b5090e2 Initial load
duke
parents:
diff changeset
   650
bool GCTaskManager::resource_flag(uint which) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   651
  assert(which < workers(), "index out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   652
  return _resource_flag[which];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   653
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   654
489c9b5090e2 Initial load
duke
parents:
diff changeset
   655
void GCTaskManager::set_resource_flag(uint which, bool value) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   656
  assert(which < workers(), "index out of bounds");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   657
  _resource_flag[which] = value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   658
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   659
489c9b5090e2 Initial load
duke
parents:
diff changeset
   660
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   661
// NoopGCTask
489c9b5090e2 Initial load
duke
parents:
diff changeset
   662
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   663
489c9b5090e2 Initial load
duke
parents:
diff changeset
   664
NoopGCTask* NoopGCTask::create() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   665
  NoopGCTask* result = new NoopGCTask(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   666
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   667
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   668
489c9b5090e2 Initial load
duke
parents:
diff changeset
   669
NoopGCTask* NoopGCTask::create_on_c_heap() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   670
  NoopGCTask* result = new(ResourceObj::C_HEAP) NoopGCTask(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   671
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   672
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   673
489c9b5090e2 Initial load
duke
parents:
diff changeset
   674
void NoopGCTask::destroy(NoopGCTask* that) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   675
  if (that != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   676
    that->destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   677
    if (that->is_c_heap_obj()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   678
      FreeHeap(that);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   679
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   680
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   681
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   682
489c9b5090e2 Initial load
duke
parents:
diff changeset
   683
void NoopGCTask::destruct() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   684
  // This has to know it's superclass structure, just like the constructor.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   685
  this->GCTask::destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   686
  // Nothing else to do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   687
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   688
489c9b5090e2 Initial load
duke
parents:
diff changeset
   689
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   690
// BarrierGCTask
489c9b5090e2 Initial load
duke
parents:
diff changeset
   691
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   692
489c9b5090e2 Initial load
duke
parents:
diff changeset
   693
void BarrierGCTask::do_it(GCTaskManager* manager, uint which) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   694
  // Wait for this to be the only busy worker.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   695
  // ??? I thought of having a StackObj class
489c9b5090e2 Initial load
duke
parents:
diff changeset
   696
  //     whose constructor would grab the lock and come to the barrier,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   697
  //     and whose destructor would release the lock,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   698
  //     but that seems like too much mechanism for two lines of code.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   699
  MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   700
  do_it_internal(manager, which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   701
  // Release manager->lock().
489c9b5090e2 Initial load
duke
parents:
diff changeset
   702
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   703
489c9b5090e2 Initial load
duke
parents:
diff changeset
   704
void BarrierGCTask::do_it_internal(GCTaskManager* manager, uint which) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   705
  // Wait for this to be the only busy worker.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   706
  assert(manager->monitor()->owned_by_self(), "don't own the lock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   707
  assert(manager->is_blocked(), "manager isn't blocked");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   708
  while (manager->busy_workers() > 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   709
    if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   710
      tty->print_cr("BarrierGCTask::do_it(%u) waiting on %u workers",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   711
                    which, manager->busy_workers());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   712
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   713
    manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   714
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   715
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   716
489c9b5090e2 Initial load
duke
parents:
diff changeset
   717
void BarrierGCTask::destruct() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   718
  this->GCTask::destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   719
  // Nothing else to do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   720
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   721
489c9b5090e2 Initial load
duke
parents:
diff changeset
   722
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   723
// ReleasingBarrierGCTask
489c9b5090e2 Initial load
duke
parents:
diff changeset
   724
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   725
489c9b5090e2 Initial load
duke
parents:
diff changeset
   726
void ReleasingBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   727
  MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   728
  do_it_internal(manager, which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   729
  manager->release_all_resources();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   730
  // Release manager->lock().
489c9b5090e2 Initial load
duke
parents:
diff changeset
   731
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   732
489c9b5090e2 Initial load
duke
parents:
diff changeset
   733
void ReleasingBarrierGCTask::destruct() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   734
  this->BarrierGCTask::destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   735
  // Nothing else to do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   736
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   737
489c9b5090e2 Initial load
duke
parents:
diff changeset
   738
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   739
// NotifyingBarrierGCTask
489c9b5090e2 Initial load
duke
parents:
diff changeset
   740
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   741
489c9b5090e2 Initial load
duke
parents:
diff changeset
   742
void NotifyingBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   743
  MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   744
  do_it_internal(manager, which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   745
  NotifyDoneClosure* ndc = notify_done_closure();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   746
  if (ndc != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   747
    ndc->notify(manager);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   748
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   749
  // Release manager->lock().
489c9b5090e2 Initial load
duke
parents:
diff changeset
   750
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   751
489c9b5090e2 Initial load
duke
parents:
diff changeset
   752
void NotifyingBarrierGCTask::destruct() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   753
  this->BarrierGCTask::destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   754
  // Nothing else to do.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   755
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   756
489c9b5090e2 Initial load
duke
parents:
diff changeset
   757
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   758
// WaitForBarrierGCTask
489c9b5090e2 Initial load
duke
parents:
diff changeset
   759
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   760
WaitForBarrierGCTask* WaitForBarrierGCTask::create() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   761
  WaitForBarrierGCTask* result = new WaitForBarrierGCTask(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   762
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   763
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   764
489c9b5090e2 Initial load
duke
parents:
diff changeset
   765
WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   766
  WaitForBarrierGCTask* result = new WaitForBarrierGCTask(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   767
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   768
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   769
489c9b5090e2 Initial load
duke
parents:
diff changeset
   770
WaitForBarrierGCTask::WaitForBarrierGCTask(bool on_c_heap) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   771
  _is_c_heap_obj(on_c_heap) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   772
  _monitor = MonitorSupply::reserve();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   773
  set_should_wait(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   774
  if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   775
    tty->print_cr("[" INTPTR_FORMAT "]"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   776
                  " WaitForBarrierGCTask::WaitForBarrierGCTask()"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   777
                  "  monitor: " INTPTR_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   778
                  this, monitor());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   779
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   780
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   781
489c9b5090e2 Initial load
duke
parents:
diff changeset
   782
void WaitForBarrierGCTask::destroy(WaitForBarrierGCTask* that) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   783
  if (that != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   784
    if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   785
      tty->print_cr("[" INTPTR_FORMAT "]"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   786
                    " WaitForBarrierGCTask::destroy()"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   787
                    "  is_c_heap_obj: %s"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   788
                    "  monitor: " INTPTR_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   789
                    that,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   790
                    that->is_c_heap_obj() ? "true" : "false",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   791
                    that->monitor());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   792
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   793
    that->destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   794
    if (that->is_c_heap_obj()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   795
      FreeHeap(that);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   796
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   797
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   798
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   799
489c9b5090e2 Initial load
duke
parents:
diff changeset
   800
void WaitForBarrierGCTask::destruct() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   801
  assert(monitor() != NULL, "monitor should not be NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   802
  if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   803
    tty->print_cr("[" INTPTR_FORMAT "]"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   804
                  " WaitForBarrierGCTask::destruct()"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   805
                  "  monitor: " INTPTR_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   806
                  this, monitor());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   807
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   808
  this->BarrierGCTask::destruct();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   809
  // Clean up that should be in the destructor,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   810
  // except that ResourceMarks don't call destructors.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   811
   if (monitor() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   812
     MonitorSupply::release(monitor());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   813
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   814
  _monitor = (Monitor*) 0xDEAD000F;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   815
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   816
489c9b5090e2 Initial load
duke
parents:
diff changeset
   817
void WaitForBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   818
  if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   819
    tty->print_cr("[" INTPTR_FORMAT "]"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   820
                  " WaitForBarrierGCTask::do_it() waiting for idle"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   821
                  "  monitor: " INTPTR_FORMAT,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   822
                  this, monitor());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   823
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   824
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   825
    // First, wait for the barrier to arrive.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   826
    MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   827
    do_it_internal(manager, which);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   828
    // Release manager->lock().
489c9b5090e2 Initial load
duke
parents:
diff changeset
   829
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   830
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   831
    // Then notify the waiter.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   832
    MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   833
    set_should_wait(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   834
    // Waiter doesn't miss the notify in the wait_for method
489c9b5090e2 Initial load
duke
parents:
diff changeset
   835
    // since it checks the flag after grabbing the monitor.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   836
    if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   837
      tty->print_cr("[" INTPTR_FORMAT "]"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   838
                    " WaitForBarrierGCTask::do_it()"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   839
                    "  [" INTPTR_FORMAT "] (%s)->notify_all()",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   840
                    this, monitor(), monitor()->name());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   841
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   842
    monitor()->notify_all();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   843
    // Release monitor().
489c9b5090e2 Initial load
duke
parents:
diff changeset
   844
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   845
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   846
489c9b5090e2 Initial load
duke
parents:
diff changeset
   847
void WaitForBarrierGCTask::wait_for() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   848
  if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   849
    tty->print_cr("[" INTPTR_FORMAT "]"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   850
                  " WaitForBarrierGCTask::wait_for()"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   851
      "  should_wait: %s",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   852
      this, should_wait() ? "true" : "false");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   853
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   854
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   855
    // Grab the lock and check again.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   856
    MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   857
    while (should_wait()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   858
      if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   859
        tty->print_cr("[" INTPTR_FORMAT "]"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   860
                      " WaitForBarrierGCTask::wait_for()"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   861
          "  [" INTPTR_FORMAT "] (%s)->wait()",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   862
          this, monitor(), monitor()->name());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   863
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   864
      monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   865
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   866
    // Reset the flag in case someone reuses this task.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   867
    set_should_wait(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   868
    if (TraceGCTaskManager) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   869
      tty->print_cr("[" INTPTR_FORMAT "]"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   870
                    " WaitForBarrierGCTask::wait_for() returns"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   871
        "  should_wait: %s",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   872
        this, should_wait() ? "true" : "false");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   873
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   874
    // Release monitor().
489c9b5090e2 Initial load
duke
parents:
diff changeset
   875
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   876
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   877
489c9b5090e2 Initial load
duke
parents:
diff changeset
   878
Mutex*                   MonitorSupply::_lock     = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   879
GrowableArray<Monitor*>* MonitorSupply::_freelist = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   880
489c9b5090e2 Initial load
duke
parents:
diff changeset
   881
Monitor* MonitorSupply::reserve() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   882
  Monitor* result = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   883
  // Lazy initialization: possible race.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   884
  if (lock() == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   885
    _lock = new Mutex(Mutex::barrier,                  // rank
489c9b5090e2 Initial load
duke
parents:
diff changeset
   886
                      "MonitorSupply mutex",           // name
489c9b5090e2 Initial load
duke
parents:
diff changeset
   887
                      Mutex::_allow_vm_block_flag);    // allow_vm_block
489c9b5090e2 Initial load
duke
parents:
diff changeset
   888
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   889
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   890
    MutexLockerEx ml(lock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   891
    // Lazy initialization.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   892
    if (freelist() == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   893
      _freelist =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   894
        new(ResourceObj::C_HEAP) GrowableArray<Monitor*>(ParallelGCThreads,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   895
                                                         true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   896
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   897
    if (! freelist()->is_empty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   898
      result = freelist()->pop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   899
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   900
      result = new Monitor(Mutex::barrier,                  // rank
489c9b5090e2 Initial load
duke
parents:
diff changeset
   901
                           "MonitorSupply monitor",         // name
489c9b5090e2 Initial load
duke
parents:
diff changeset
   902
                           Mutex::_allow_vm_block_flag);    // allow_vm_block
489c9b5090e2 Initial load
duke
parents:
diff changeset
   903
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   904
    guarantee(result != NULL, "shouldn't return NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   905
    assert(!result->is_locked(), "shouldn't be locked");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   906
    // release lock().
489c9b5090e2 Initial load
duke
parents:
diff changeset
   907
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   908
  return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   909
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   910
489c9b5090e2 Initial load
duke
parents:
diff changeset
   911
void MonitorSupply::release(Monitor* instance) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   912
  assert(instance != NULL, "shouldn't release NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   913
  assert(!instance->is_locked(), "shouldn't be locked");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   914
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   915
    MutexLockerEx ml(lock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   916
    freelist()->push(instance);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   917
    // release lock().
489c9b5090e2 Initial load
duke
parents:
diff changeset
   918
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   919
}