68 bool |
74 bool |
69 ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) { |
75 ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) { |
70 Atomic::inc(&_offered_termination); |
76 Atomic::inc(&_offered_termination); |
71 |
77 |
72 uint yield_count = 0; |
78 uint yield_count = 0; |
|
79 // Number of hard spin loops done since last yield |
|
80 uint hard_spin_count = 0; |
|
81 // Number of iterations in the hard spin loop. |
|
82 uint hard_spin_limit = WorkStealingHardSpins; |
|
83 |
|
84 // If WorkStealingSpinToYieldRatio is 0, no hard spinning is done. |
|
85 // If it is greater than 0, then start with a small number |
|
86 // of spins and increase number with each turn at spinning until |
|
87 // the count of hard spins exceeds WorkStealingSpinToYieldRatio. |
|
88 // Then do a yield() call and start spinning afresh. |
|
89 if (WorkStealingSpinToYieldRatio > 0) { |
|
90 hard_spin_limit = WorkStealingHardSpins >> WorkStealingSpinToYieldRatio; |
|
91 hard_spin_limit = MAX2(hard_spin_limit, 1U); |
|
92 } |
|
93 // Remember the initial spin limit. |
|
94 uint hard_spin_start = hard_spin_limit; |
|
95 |
|
96 // Loop waiting for all threads to offer termination or |
|
97 // more work. |
73 while (true) { |
98 while (true) { |
|
99 // Are all threads offering termination? |
74 if (_offered_termination == _n_threads) { |
100 if (_offered_termination == _n_threads) { |
75 //inner_termination_loop(); |
|
76 return true; |
101 return true; |
77 } else { |
102 } else { |
|
103 // Look for more work. |
|
104 // Periodically sleep() instead of yield() to give threads |
|
105 // waiting on the cores the chance to grab this code |
78 if (yield_count <= WorkStealingYieldsBeforeSleep) { |
106 if (yield_count <= WorkStealingYieldsBeforeSleep) { |
|
107 // Do a yield or hardspin. For purposes of deciding whether |
|
108 // to sleep, count this as a yield. |
79 yield_count++; |
109 yield_count++; |
80 yield(); |
110 |
|
111 // Periodically call yield() instead spinning |
|
112 // After WorkStealingSpinToYieldRatio spins, do a yield() call |
|
113 // and reset the counts and starting limit. |
|
114 if (hard_spin_count > WorkStealingSpinToYieldRatio) { |
|
115 yield(); |
|
116 hard_spin_count = 0; |
|
117 hard_spin_limit = hard_spin_start; |
|
118 #ifdef TRACESPINNING |
|
119 _total_yields++; |
|
120 #endif |
|
121 } else { |
|
122 // Hard spin this time |
|
123 // Increase the hard spinning period but only up to a limit. |
|
124 hard_spin_limit = MIN2(2*hard_spin_limit, |
|
125 (uint) WorkStealingHardSpins); |
|
126 for (uint j = 0; j < hard_spin_limit; j++) { |
|
127 SpinPause(); |
|
128 } |
|
129 hard_spin_count++; |
|
130 #ifdef TRACESPINNING |
|
131 _total_spins++; |
|
132 #endif |
|
133 } |
81 } else { |
134 } else { |
82 if (PrintGCDetails && Verbose) { |
135 if (PrintGCDetails && Verbose) { |
83 gclog_or_tty->print_cr("ParallelTaskTerminator::offer_termination() " |
136 gclog_or_tty->print_cr("ParallelTaskTerminator::offer_termination() " |
84 "thread %d sleeps after %d yields", |
137 "thread %d sleeps after %d yields", |
85 Thread::current(), yield_count); |
138 Thread::current(), yield_count); |
90 // which may only move the thread to the end of the this processor's |
143 // which may only move the thread to the end of the this processor's |
91 // runqueue). |
144 // runqueue). |
92 sleep(WorkStealingSleepMillis); |
145 sleep(WorkStealingSleepMillis); |
93 } |
146 } |
94 |
147 |
|
148 #ifdef TRACESPINNING |
|
149 _total_peeks++; |
|
150 #endif |
95 if (peek_in_queue_set() || |
151 if (peek_in_queue_set() || |
96 (terminator != NULL && terminator->should_exit_termination())) { |
152 (terminator != NULL && terminator->should_exit_termination())) { |
97 Atomic::dec(&_offered_termination); |
153 Atomic::dec(&_offered_termination); |
98 return false; |
154 return false; |
99 } |
155 } |
100 } |
156 } |
101 } |
157 } |
102 } |
158 } |
|
159 |
|
160 #ifdef TRACESPINNING |
|
161 void ParallelTaskTerminator::print_termination_counts() { |
|
162 gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: %lld " |
|
163 "Total spins: %lld Total peeks: %lld", |
|
164 total_yields(), |
|
165 total_spins(), |
|
166 total_peeks()); |
|
167 } |
|
168 #endif |
103 |
169 |
104 void ParallelTaskTerminator::reset_for_reuse() { |
170 void ParallelTaskTerminator::reset_for_reuse() { |
105 if (_offered_termination != 0) { |
171 if (_offered_termination != 0) { |
106 assert(_offered_termination == _n_threads, |
172 assert(_offered_termination == _n_threads, |
107 "Terminator may still be in use"); |
173 "Terminator may still be in use"); |