12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "memory/allocation.hpp"
27 #include "memory/allocation.inline.hpp"
28 #include "runtime/atomic.inline.hpp"
29 #include "runtime/os.hpp"
30 #include "utilities/workgroup.hpp"
31
32 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
33
34 // Definitions of WorkGang methods.
35
36 AbstractWorkGang::AbstractWorkGang(const char* name,
37 bool are_GC_task_threads,
38 bool are_ConcurrentGC_threads) :
39 _name(name),
40 _are_GC_task_threads(are_GC_task_threads),
41 _are_ConcurrentGC_threads(are_ConcurrentGC_threads) {
42
43 assert(!(are_GC_task_threads && are_ConcurrentGC_threads),
44 "They cannot both be STW GC and Concurrent threads" );
45
46 // Other initialization.
47 _monitor = new Monitor(/* priority */ Mutex::leaf,
48 /* name */ "WorkGroup monitor",
49 /* allow_vm_block */ are_GC_task_threads,
50 Monitor::_safepoint_check_sometimes);
51 assert(monitor() != NULL, "Failed to allocate monitor");
52 _terminate = false;
53 _task = NULL;
138 task->set_for_termination(no_of_parallel_workers);
139
140 // This thread is executed by the VM thread which does not block
141 // on ordinary MutexLocker's.
142 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
143 if (TraceWorkGang) {
144 tty->print_cr("Running work gang %s task %s", name(), task->name());
145 }
146 // Tell all the workers to run a task.
147 assert(task != NULL, "Running a null task");
148 // Initialize.
149 _task = task;
150 _sequence_number += 1;
151 _started_workers = 0;
152 _finished_workers = 0;
153 // Tell the workers to get to work.
154 monitor()->notify_all();
155 // Wait for them to be finished
156 while (finished_workers() < no_of_parallel_workers) {
157 if (TraceWorkGang) {
158 tty->print_cr("Waiting in work gang %s: %d/%d finished sequence %d",
159 name(), finished_workers(), no_of_parallel_workers,
160 _sequence_number);
161 }
162 monitor()->wait(/* no_safepoint_check */ true);
163 }
164 _task = NULL;
165 if (TraceWorkGang) {
166 tty->print_cr("\nFinished work gang %s: %d/%d sequence %d",
167 name(), finished_workers(), no_of_parallel_workers,
168 _sequence_number);
169 Thread* me = Thread::current();
170 tty->print_cr(" T: 0x%x VM_thread: %d", me, me->is_VM_thread());
171 }
172 }
173
174 void FlexibleWorkGang::run_task(AbstractGangTask* task) {
175 // If active_workers() is passed, _finished_workers
176 // must only be incremented for workers that find non_null
177 // work (as opposed to all those that just check that the
178 // task is not null).
179 WorkGang::run_task(task, (uint) active_workers());
180 }
181
182 void AbstractWorkGang::stop() {
183 // Tell all workers to terminate, then wait for them to become inactive.
184 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
185 if (TraceWorkGang) {
186 tty->print_cr("Stopping work gang %s task %s", name(), task()->name());
187 }
188 _task = NULL;
189 _terminate = true;
190 monitor()->notify_all();
191 while (finished_workers() < active_workers()) {
192 if (TraceWorkGang) {
193 tty->print_cr("Waiting in work gang %s: %d/%d finished",
194 name(), finished_workers(), active_workers());
195 }
196 monitor()->wait(/* no_safepoint_check */ true);
197 }
198 }
199
200 void AbstractWorkGang::internal_worker_poll(WorkData* data) const {
201 assert(monitor()->owned_by_self(), "worker_poll is an internal method");
202 assert(data != NULL, "worker data is null");
203 data->set_terminate(terminate());
204 data->set_task(task());
205 data->set_sequence_number(sequence_number());
206 }
207
208 void AbstractWorkGang::internal_note_start() {
209 assert(monitor()->owned_by_self(), "note_finish is an internal method");
210 _started_workers += 1;
211 }
212
213 void AbstractWorkGang::internal_note_finish() {
234 // GangWorker methods.
235
236 GangWorker::GangWorker(AbstractWorkGang* gang, uint id) {
237 _gang = gang;
238 set_id(id);
239 set_name("%s#%d", gang->name(), id);
240 }
241
242 void GangWorker::run() {
243 initialize();
244 loop();
245 }
246
247 void GangWorker::initialize() {
248 this->initialize_thread_local_storage();
249 this->record_stack_base_and_size();
250 this->initialize_named_thread();
251 assert(_gang != NULL, "No gang to run in");
252 os::set_priority(this, NearMaxPriority);
253 if (TraceWorkGang) {
254 tty->print_cr("Running gang worker for gang %s id %d",
255 gang()->name(), id());
256 }
257 // The VM thread should not execute here because MutexLocker's are used
258 // as (opposed to MutexLockerEx's).
259 assert(!Thread::current()->is_VM_thread(), "VM thread should not be part"
260 " of a work gang");
261 }
262
263 void GangWorker::loop() {
264 int previous_sequence_number = 0;
265 Monitor* gang_monitor = gang()->monitor();
266 for ( ; /* !terminate() */; ) {
267 WorkData data;
268 int part; // Initialized below.
269 {
270 // Grab the gang mutex.
271 MutexLocker ml(gang_monitor);
272 // Wait for something to do.
273 // Polling outside the while { wait } avoids missed notifies
274 // in the outer loop.
275 gang()->internal_worker_poll(&data);
276 if (TraceWorkGang) {
277 tty->print("Polled outside for work in gang %s worker %d",
278 gang()->name(), id());
279 tty->print(" terminate: %s",
280 data.terminate() ? "true" : "false");
281 tty->print(" sequence: %d (prev: %d)",
282 data.sequence_number(), previous_sequence_number);
283 if (data.task() != NULL) {
284 tty->print(" task: %s", data.task()->name());
285 } else {
286 tty->print(" task: NULL");
287 }
288 tty->cr();
289 }
290 for ( ; /* break or return */; ) {
291 // Terminate if requested.
292 if (data.terminate()) {
293 gang()->internal_note_finish();
294 gang_monitor->notify_all();
295 return;
296 }
297 // Check for new work.
298 if ((data.task() != NULL) &&
299 (data.sequence_number() != previous_sequence_number)) {
300 if (gang()->needs_more_workers()) {
301 gang()->internal_note_start();
302 gang_monitor->notify_all();
303 part = gang()->started_workers() - 1;
304 break;
305 }
306 }
307 // Nothing to do.
308 gang_monitor->wait(/* no_safepoint_check */ true);
309 gang()->internal_worker_poll(&data);
310 if (TraceWorkGang) {
311 tty->print("Polled inside for work in gang %s worker %d",
312 gang()->name(), id());
313 tty->print(" terminate: %s",
314 data.terminate() ? "true" : "false");
315 tty->print(" sequence: %d (prev: %d)",
316 data.sequence_number(), previous_sequence_number);
317 if (data.task() != NULL) {
318 tty->print(" task: %s", data.task()->name());
319 } else {
320 tty->print(" task: NULL");
321 }
322 tty->cr();
323 }
324 }
325 // Drop gang mutex.
326 }
327 if (TraceWorkGang) {
328 tty->print("Work for work gang %s id %d task %s part %d",
329 gang()->name(), id(), data.task()->name(), part);
330 }
331 assert(data.task() != NULL, "Got null task");
332 data.task()->work(part);
333 {
334 if (TraceWorkGang) {
335 tty->print("Finish for work gang %s id %d task %s part %d",
336 gang()->name(), id(), data.task()->name(), part);
337 }
338 // Grab the gang mutex.
339 MutexLocker ml(gang_monitor);
340 gang()->internal_note_finish();
341 // Tell the gang you are done.
342 gang_monitor->notify_all();
343 // Drop the gang mutex.
344 }
345 previous_sequence_number = data.sequence_number();
346 }
347 }
348
349 bool GangWorker::is_GC_task_thread() const {
350 return gang()->are_GC_task_threads();
351 }
352
353 bool GangWorker::is_ConcurrentGC_thread() const {
354 return gang()->are_ConcurrentGC_threads();
355 }
|
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "memory/allocation.hpp"
27 #include "memory/allocation.inline.hpp"
28 #include "runtime/atomic.inline.hpp"
29 #include "runtime/os.hpp"
30 #include "utilities/workgroup.hpp"
31
32 // Definitions of WorkGang methods.
33
34 AbstractWorkGang::AbstractWorkGang(const char* name,
35 bool are_GC_task_threads,
36 bool are_ConcurrentGC_threads) :
37 _name(name),
38 _are_GC_task_threads(are_GC_task_threads),
39 _are_ConcurrentGC_threads(are_ConcurrentGC_threads) {
40
41 assert(!(are_GC_task_threads && are_ConcurrentGC_threads),
42 "They cannot both be STW GC and Concurrent threads" );
43
44 // Other initialization.
45 _monitor = new Monitor(/* priority */ Mutex::leaf,
46 /* name */ "WorkGroup monitor",
47 /* allow_vm_block */ are_GC_task_threads,
48 Monitor::_safepoint_check_sometimes);
49 assert(monitor() != NULL, "Failed to allocate monitor");
50 _terminate = false;
51 _task = NULL;
136 task->set_for_termination(no_of_parallel_workers);
137
138 // This thread is executed by the VM thread which does not block
139 // on ordinary MutexLocker's.
140 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
141 if (TraceWorkGang) {
142 tty->print_cr("Running work gang %s task %s", name(), task->name());
143 }
144 // Tell all the workers to run a task.
145 assert(task != NULL, "Running a null task");
146 // Initialize.
147 _task = task;
148 _sequence_number += 1;
149 _started_workers = 0;
150 _finished_workers = 0;
151 // Tell the workers to get to work.
152 monitor()->notify_all();
153 // Wait for them to be finished
154 while (finished_workers() < no_of_parallel_workers) {
155 if (TraceWorkGang) {
156 tty->print_cr("Waiting in work gang %s: %u/%u finished sequence %d",
157 name(), finished_workers(), no_of_parallel_workers,
158 _sequence_number);
159 }
160 monitor()->wait(/* no_safepoint_check */ true);
161 }
162 _task = NULL;
163 if (TraceWorkGang) {
164 tty->print_cr("\nFinished work gang %s: %u/%u sequence %d",
165 name(), finished_workers(), no_of_parallel_workers,
166 _sequence_number);
167 Thread* me = Thread::current();
168 tty->print_cr(" T: " PTR_FORMAT " VM_thread: %d", p2i(me), me->is_VM_thread());
169 }
170 }
171
172 void FlexibleWorkGang::run_task(AbstractGangTask* task) {
173 // If active_workers() is passed, _finished_workers
174 // must only be incremented for workers that find non_null
175 // work (as opposed to all those that just check that the
176 // task is not null).
177 WorkGang::run_task(task, (uint) active_workers());
178 }
179
180 void AbstractWorkGang::stop() {
181 // Tell all workers to terminate, then wait for them to become inactive.
182 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
183 if (TraceWorkGang) {
184 tty->print_cr("Stopping work gang %s task %s", name(), task()->name());
185 }
186 _task = NULL;
187 _terminate = true;
188 monitor()->notify_all();
189 while (finished_workers() < active_workers()) {
190 if (TraceWorkGang) {
191 tty->print_cr("Waiting in work gang %s: %u/%u finished",
192 name(), finished_workers(), active_workers());
193 }
194 monitor()->wait(/* no_safepoint_check */ true);
195 }
196 }
197
198 void AbstractWorkGang::internal_worker_poll(WorkData* data) const {
199 assert(monitor()->owned_by_self(), "worker_poll is an internal method");
200 assert(data != NULL, "worker data is null");
201 data->set_terminate(terminate());
202 data->set_task(task());
203 data->set_sequence_number(sequence_number());
204 }
205
206 void AbstractWorkGang::internal_note_start() {
207 assert(monitor()->owned_by_self(), "note_finish is an internal method");
208 _started_workers += 1;
209 }
210
211 void AbstractWorkGang::internal_note_finish() {
232 // GangWorker methods.
233
234 GangWorker::GangWorker(AbstractWorkGang* gang, uint id) {
235 _gang = gang;
236 set_id(id);
237 set_name("%s#%d", gang->name(), id);
238 }
239
240 void GangWorker::run() {
241 initialize();
242 loop();
243 }
244
245 void GangWorker::initialize() {
246 this->initialize_thread_local_storage();
247 this->record_stack_base_and_size();
248 this->initialize_named_thread();
249 assert(_gang != NULL, "No gang to run in");
250 os::set_priority(this, NearMaxPriority);
251 if (TraceWorkGang) {
252 tty->print_cr("Running gang worker for gang %s id %u",
253 gang()->name(), id());
254 }
255 // The VM thread should not execute here because MutexLocker's are used
256 // as (opposed to MutexLockerEx's).
257 assert(!Thread::current()->is_VM_thread(), "VM thread should not be part"
258 " of a work gang");
259 }
260
261 void GangWorker::loop() {
262 int previous_sequence_number = 0;
263 Monitor* gang_monitor = gang()->monitor();
264 for ( ; /* !terminate() */; ) {
265 WorkData data;
266 int part; // Initialized below.
267 {
268 // Grab the gang mutex.
269 MutexLocker ml(gang_monitor);
270 // Wait for something to do.
271 // Polling outside the while { wait } avoids missed notifies
272 // in the outer loop.
273 gang()->internal_worker_poll(&data);
274 if (TraceWorkGang) {
275 tty->print("Polled outside for work in gang %s worker %u",
276 gang()->name(), id());
277 tty->print(" terminate: %s",
278 data.terminate() ? "true" : "false");
279 tty->print(" sequence: %d (prev: %d)",
280 data.sequence_number(), previous_sequence_number);
281 if (data.task() != NULL) {
282 tty->print(" task: %s", data.task()->name());
283 } else {
284 tty->print(" task: NULL");
285 }
286 tty->cr();
287 }
288 for ( ; /* break or return */; ) {
289 // Terminate if requested.
290 if (data.terminate()) {
291 gang()->internal_note_finish();
292 gang_monitor->notify_all();
293 return;
294 }
295 // Check for new work.
296 if ((data.task() != NULL) &&
297 (data.sequence_number() != previous_sequence_number)) {
298 if (gang()->needs_more_workers()) {
299 gang()->internal_note_start();
300 gang_monitor->notify_all();
301 part = gang()->started_workers() - 1;
302 break;
303 }
304 }
305 // Nothing to do.
306 gang_monitor->wait(/* no_safepoint_check */ true);
307 gang()->internal_worker_poll(&data);
308 if (TraceWorkGang) {
309 tty->print("Polled inside for work in gang %s worker %u",
310 gang()->name(), id());
311 tty->print(" terminate: %s",
312 data.terminate() ? "true" : "false");
313 tty->print(" sequence: %d (prev: %d)",
314 data.sequence_number(), previous_sequence_number);
315 if (data.task() != NULL) {
316 tty->print(" task: %s", data.task()->name());
317 } else {
318 tty->print(" task: NULL");
319 }
320 tty->cr();
321 }
322 }
323 // Drop gang mutex.
324 }
325 if (TraceWorkGang) {
326 tty->print("Work for work gang %s id %u task %s part %d",
327 gang()->name(), id(), data.task()->name(), part);
328 }
329 assert(data.task() != NULL, "Got null task");
330 data.task()->work(part);
331 {
332 if (TraceWorkGang) {
333 tty->print("Finish for work gang %s id %u task %s part %d",
334 gang()->name(), id(), data.task()->name(), part);
335 }
336 // Grab the gang mutex.
337 MutexLocker ml(gang_monitor);
338 gang()->internal_note_finish();
339 // Tell the gang you are done.
340 gang_monitor->notify_all();
341 // Drop the gang mutex.
342 }
343 previous_sequence_number = data.sequence_number();
344 }
345 }
346
347 bool GangWorker::is_GC_task_thread() const {
348 return gang()->are_GC_task_threads();
349 }
350
351 bool GangWorker::is_ConcurrentGC_thread() const {
352 return gang()->are_ConcurrentGC_threads();
353 }
|