src/share/vm/utilities/taskqueue.cpp

Tue, 30 Sep 2008 12:20:22 -0700

author
jcoomes
date
Tue, 30 Sep 2008 12:20:22 -0700
changeset 810
81cd571500b0
parent 777
37f87013dfd8
child 905
ad8c8ca4ab0f
permissions
-rw-r--r--

6725697: par compact - rename class ChunkData to RegionData
Reviewed-by: iveresov, tonyp

duke@435 1 /*
duke@435 2 * Copyright 2001-2006 Sun Microsystems, Inc. All Rights Reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
duke@435 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@435 20 * CA 95054 USA or visit www.sun.com if you need additional information or
duke@435 21 * have any questions.
duke@435 22 *
duke@435 23 */
duke@435 24
duke@435 25 # include "incls/_precompiled.incl"
duke@435 26 # include "incls/_taskqueue.cpp.incl"
duke@435 27
duke@435 28 bool TaskQueueSuper::peek() {
duke@435 29 return _bottom != _age.top();
duke@435 30 }
duke@435 31
duke@435 32 int TaskQueueSetSuper::randomParkAndMiller(int *seed0) {
duke@435 33 const int a = 16807;
duke@435 34 const int m = 2147483647;
duke@435 35 const int q = 127773; /* m div a */
duke@435 36 const int r = 2836; /* m mod a */
duke@435 37 assert(sizeof(int) == 4, "I think this relies on that");
duke@435 38 int seed = *seed0;
duke@435 39 int hi = seed / q;
duke@435 40 int lo = seed % q;
duke@435 41 int test = a * lo - r * hi;
duke@435 42 if (test > 0)
duke@435 43 seed = test;
duke@435 44 else
duke@435 45 seed = test + m;
duke@435 46 *seed0 = seed;
duke@435 47 return seed;
duke@435 48 }
duke@435 49
duke@435 50 ParallelTaskTerminator::
duke@435 51 ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set) :
duke@435 52 _n_threads(n_threads),
duke@435 53 _queue_set(queue_set),
duke@435 54 _offered_termination(0) {}
duke@435 55
duke@435 56 bool ParallelTaskTerminator::peek_in_queue_set() {
duke@435 57 return _queue_set->peek();
duke@435 58 }
duke@435 59
duke@435 60 void ParallelTaskTerminator::yield() {
duke@435 61 os::yield();
duke@435 62 }
duke@435 63
duke@435 64 void ParallelTaskTerminator::sleep(uint millis) {
duke@435 65 os::sleep(Thread::current(), millis, false);
duke@435 66 }
duke@435 67
ysr@777 68 bool
ysr@777 69 ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) {
duke@435 70 Atomic::inc(&_offered_termination);
duke@435 71
duke@435 72 juint yield_count = 0;
duke@435 73 while (true) {
duke@435 74 if (_offered_termination == _n_threads) {
duke@435 75 //inner_termination_loop();
duke@435 76 return true;
duke@435 77 } else {
duke@435 78 if (yield_count <= WorkStealingYieldsBeforeSleep) {
duke@435 79 yield_count++;
duke@435 80 yield();
duke@435 81 } else {
duke@435 82 if (PrintGCDetails && Verbose) {
duke@435 83 gclog_or_tty->print_cr("ParallelTaskTerminator::offer_termination() "
duke@435 84 "thread %d sleeps after %d yields",
duke@435 85 Thread::current(), yield_count);
duke@435 86 }
duke@435 87 yield_count = 0;
duke@435 88 // A sleep will cause this processor to seek work on another processor's
duke@435 89 // runqueue, if it has nothing else to run (as opposed to the yield
duke@435 90 // which may only move the thread to the end of the this processor's
duke@435 91 // runqueue).
duke@435 92 sleep(WorkStealingSleepMillis);
duke@435 93 }
duke@435 94
ysr@777 95 if (peek_in_queue_set() ||
ysr@777 96 (terminator != NULL && terminator->should_exit_termination())) {
duke@435 97 Atomic::dec(&_offered_termination);
duke@435 98 return false;
duke@435 99 }
duke@435 100 }
duke@435 101 }
duke@435 102 }
duke@435 103
duke@435 104 void ParallelTaskTerminator::reset_for_reuse() {
duke@435 105 if (_offered_termination != 0) {
duke@435 106 assert(_offered_termination == _n_threads,
duke@435 107 "Terminator may still be in use");
duke@435 108 _offered_termination = 0;
duke@435 109 }
duke@435 110 }
duke@435 111
jcoomes@810 112 bool RegionTaskQueueWithOverflow::is_empty() {
jcoomes@810 113 return (_region_queue.size() == 0) &&
duke@435 114 (_overflow_stack->length() == 0);
duke@435 115 }
duke@435 116
jcoomes@810 117 bool RegionTaskQueueWithOverflow::stealable_is_empty() {
jcoomes@810 118 return _region_queue.size() == 0;
duke@435 119 }
duke@435 120
jcoomes@810 121 bool RegionTaskQueueWithOverflow::overflow_is_empty() {
duke@435 122 return _overflow_stack->length() == 0;
duke@435 123 }
duke@435 124
jcoomes@810 125 void RegionTaskQueueWithOverflow::initialize() {
jcoomes@810 126 _region_queue.initialize();
duke@435 127 assert(_overflow_stack == 0, "Creating memory leak");
duke@435 128 _overflow_stack =
jcoomes@810 129 new (ResourceObj::C_HEAP) GrowableArray<RegionTask>(10, true);
duke@435 130 }
duke@435 131
jcoomes@810 132 void RegionTaskQueueWithOverflow::save(RegionTask t) {
jcoomes@810 133 if (TraceRegionTasksQueuing && Verbose) {
duke@435 134 gclog_or_tty->print_cr("CTQ: save " PTR_FORMAT, t);
duke@435 135 }
jcoomes@810 136 if(!_region_queue.push(t)) {
duke@435 137 _overflow_stack->push(t);
duke@435 138 }
duke@435 139 }
duke@435 140
jcoomes@810 141 // Note that using this method will retrieve all regions
duke@435 142 // that have been saved but that it will always check
duke@435 143 // the overflow stack. It may be more efficient to
duke@435 144 // check the stealable queue and the overflow stack
duke@435 145 // separately.
jcoomes@810 146 bool RegionTaskQueueWithOverflow::retrieve(RegionTask& region_task) {
jcoomes@810 147 bool result = retrieve_from_overflow(region_task);
duke@435 148 if (!result) {
jcoomes@810 149 result = retrieve_from_stealable_queue(region_task);
duke@435 150 }
jcoomes@810 151 if (TraceRegionTasksQueuing && Verbose && result) {
duke@435 152 gclog_or_tty->print_cr(" CTQ: retrieve " PTR_FORMAT, result);
duke@435 153 }
duke@435 154 return result;
duke@435 155 }
duke@435 156
jcoomes@810 157 bool RegionTaskQueueWithOverflow::retrieve_from_stealable_queue(
jcoomes@810 158 RegionTask& region_task) {
jcoomes@810 159 bool result = _region_queue.pop_local(region_task);
jcoomes@810 160 if (TraceRegionTasksQueuing && Verbose) {
jcoomes@810 161 gclog_or_tty->print_cr("CTQ: retrieve_stealable " PTR_FORMAT, region_task);
duke@435 162 }
duke@435 163 return result;
duke@435 164 }
duke@435 165
jcoomes@810 166 bool
jcoomes@810 167 RegionTaskQueueWithOverflow::retrieve_from_overflow(RegionTask& region_task) {
duke@435 168 bool result;
duke@435 169 if (!_overflow_stack->is_empty()) {
jcoomes@810 170 region_task = _overflow_stack->pop();
duke@435 171 result = true;
duke@435 172 } else {
jcoomes@810 173 region_task = (RegionTask) NULL;
duke@435 174 result = false;
duke@435 175 }
jcoomes@810 176 if (TraceRegionTasksQueuing && Verbose) {
jcoomes@810 177 gclog_or_tty->print_cr("CTQ: retrieve_stealable " PTR_FORMAT, region_task);
duke@435 178 }
duke@435 179 return result;
duke@435 180 }

mercurial