24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "gc/parallel/gcTaskManager.hpp" |
26 #include "gc/parallel/gcTaskManager.hpp" |
27 #include "gc/parallel/gcTaskThread.hpp" |
27 #include "gc/parallel/gcTaskThread.hpp" |
28 #include "gc/shared/gcId.hpp" |
28 #include "gc/shared/gcId.hpp" |
|
29 #include "logging/log.hpp" |
29 #include "memory/allocation.hpp" |
30 #include "memory/allocation.hpp" |
30 #include "memory/allocation.inline.hpp" |
31 #include "memory/allocation.inline.hpp" |
31 #include "memory/resourceArea.hpp" |
32 #include "memory/resourceArea.hpp" |
|
33 #include "runtime/atomic.inline.hpp" |
32 #include "runtime/handles.hpp" |
34 #include "runtime/handles.hpp" |
33 #include "runtime/handles.inline.hpp" |
35 #include "runtime/handles.inline.hpp" |
34 #include "runtime/os.hpp" |
36 #include "runtime/os.hpp" |
35 #include "runtime/thread.hpp" |
37 #include "runtime/thread.hpp" |
36 |
38 |
43 _time_stamp_index(0) |
45 _time_stamp_index(0) |
44 { |
46 { |
45 if (!os::create_thread(this, os::pgc_thread)) |
47 if (!os::create_thread(this, os::pgc_thread)) |
46 vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create GC thread. Out of system resources."); |
48 vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create GC thread. Out of system resources."); |
47 |
49 |
48 if (PrintGCTaskTimeStamps) { |
|
49 _time_stamps = NEW_C_HEAP_ARRAY(GCTaskTimeStamp, GCTaskTimeStampEntries, mtGC); |
|
50 |
|
51 guarantee(_time_stamps != NULL, "Sanity"); |
|
52 } |
|
53 set_id(which); |
50 set_id(which); |
54 set_name("ParGC Thread#%d", which); |
51 set_name("ParGC Thread#%d", which); |
55 } |
52 } |
56 |
53 |
57 GCTaskThread::~GCTaskThread() { |
54 GCTaskThread::~GCTaskThread() { |
64 os::start_thread(this); |
61 os::start_thread(this); |
65 } |
62 } |
66 |
63 |
67 GCTaskTimeStamp* GCTaskThread::time_stamp_at(uint index) { |
64 GCTaskTimeStamp* GCTaskThread::time_stamp_at(uint index) { |
68 guarantee(index < GCTaskTimeStampEntries, "increase GCTaskTimeStampEntries"); |
65 guarantee(index < GCTaskTimeStampEntries, "increase GCTaskTimeStampEntries"); |
|
66 if (_time_stamps == NULL) { |
|
67 // We allocate the _time_stamps array lazily since logging can be enabled dynamically |
|
68 GCTaskTimeStamp* time_stamps = NEW_C_HEAP_ARRAY(GCTaskTimeStamp, GCTaskTimeStampEntries, mtGC); |
|
69 void* old = Atomic::cmpxchg_ptr(time_stamps, &_time_stamps, NULL); |
|
70 if (old != NULL) { |
|
71 // Someone already setup the time stamps |
|
72 FREE_C_HEAP_ARRAY(GCTaskTimeStamp, time_stamps); |
|
73 } |
|
74 } |
69 |
75 |
70 return &(_time_stamps[index]); |
76 return &(_time_stamps[index]); |
71 } |
77 } |
72 |
78 |
73 void GCTaskThread::print_task_time_stamps() { |
79 void GCTaskThread::print_task_time_stamps() { |
74 assert(PrintGCTaskTimeStamps, "Sanity"); |
80 assert(log_is_enabled(Debug, gc, task, time), "Sanity"); |
75 assert(_time_stamps != NULL, "Sanity (Probably set PrintGCTaskTimeStamps late)"); |
81 assert(_time_stamps != NULL, "Sanity"); |
76 |
82 |
77 tty->print_cr("GC-Thread %u entries: %d", id(), _time_stamp_index); |
83 log_debug(gc, task, time)("GC-Thread %u entries: %d", id(), _time_stamp_index); |
78 for(uint i=0; i<_time_stamp_index; i++) { |
84 for(uint i=0; i<_time_stamp_index; i++) { |
79 GCTaskTimeStamp* time_stamp = time_stamp_at(i); |
85 GCTaskTimeStamp* time_stamp = time_stamp_at(i); |
80 tty->print_cr("\t[ %s " JLONG_FORMAT " " JLONG_FORMAT " ]", |
86 log_debug(gc, task, time)("\t[ %s " JLONG_FORMAT " " JLONG_FORMAT " ]", |
81 time_stamp->name(), |
87 time_stamp->name(), |
82 time_stamp->entry_time(), |
88 time_stamp->entry_time(), |
83 time_stamp->exit_time()); |
89 time_stamp->exit_time()); |
84 } |
90 } |
85 |
91 |
86 // Reset after dumping the data |
92 // Reset after dumping the data |
87 _time_stamp_index = 0; |
93 _time_stamp_index = 0; |
88 } |
94 } |
125 GCTask* task = manager()->get_task(which()); |
131 GCTask* task = manager()->get_task(which()); |
126 GCIdMark gc_id_mark(task->gc_id()); |
132 GCIdMark gc_id_mark(task->gc_id()); |
127 // Record if this is an idle task for later use. |
133 // Record if this is an idle task for later use. |
128 bool is_idle_task = task->is_idle_task(); |
134 bool is_idle_task = task->is_idle_task(); |
129 // In case the update is costly |
135 // In case the update is costly |
130 if (PrintGCTaskTimeStamps) { |
136 if (log_is_enabled(Debug, gc, task, time)) { |
131 timer.update(); |
137 timer.update(); |
132 } |
138 } |
133 |
139 |
134 jlong entry_time = timer.ticks(); |
140 jlong entry_time = timer.ticks(); |
135 char* name = task->name(); |
141 char* name = task->name(); |
141 // Use the saved value of is_idle_task because references |
147 // Use the saved value of is_idle_task because references |
142 // using "task" are not reliable for the barrier task. |
148 // using "task" are not reliable for the barrier task. |
143 if (!is_idle_task) { |
149 if (!is_idle_task) { |
144 manager()->note_completion(which()); |
150 manager()->note_completion(which()); |
145 |
151 |
146 if (PrintGCTaskTimeStamps) { |
152 if (log_is_enabled(Debug, gc, task, time)) { |
147 assert(_time_stamps != NULL, |
|
148 "Sanity (PrintGCTaskTimeStamps set late?)"); |
|
149 |
|
150 timer.update(); |
153 timer.update(); |
151 |
154 |
152 GCTaskTimeStamp* time_stamp = time_stamp_at(_time_stamp_index++); |
155 GCTaskTimeStamp* time_stamp = time_stamp_at(_time_stamp_index++); |
153 |
156 |
154 time_stamp->set_name(name); |
157 time_stamp->set_name(name); |