234 char* const _end_addr;
235 size_t const _page_size;
236 public:
237 G1PretouchTask(char* start_address, char* end_address, size_t page_size) :
238 AbstractGangTask("G1 PreTouch",
239 Universe::is_fully_initialized() &&
240 Thread::current()->is_Named_thread() ? GCId::current_raw() :
241 // During VM initialization there is
242 // no GC cycle that this task can be
243 // associated with.
244 GCId::undefined()),
245 _cur_addr(start_address),
246 _start_addr(start_address),
247 _end_addr(end_address),
248 _page_size(page_size) {
249 }
250
251 virtual void work(uint worker_id) {
252 size_t const actual_chunk_size = MAX2(chunk_size(), _page_size);
253 while (true) {
254 char* touch_addr = (char*)Atomic::add_ptr((intptr_t)actual_chunk_size, (volatile void*) &_cur_addr) - actual_chunk_size;
255 if (touch_addr < _start_addr || touch_addr >= _end_addr) {
256 break;
257 }
258 char* end_addr = touch_addr + MIN2(actual_chunk_size, pointer_delta(_end_addr, touch_addr, sizeof(char)));
259 os::pretouch_memory(touch_addr, end_addr, _page_size);
260 }
261 }
262
263 static size_t chunk_size() { return PreTouchParallelChunkSize; }
264 };
265
266 void G1PageBasedVirtualSpace::pretouch(size_t start_page, size_t size_in_pages, WorkGang* pretouch_gang) {
267 G1PretouchTask cl(page_start(start_page), bounded_end_addr(start_page + size_in_pages), _page_size);
268
269 if (pretouch_gang != NULL) {
270 size_t num_chunks = MAX2((size_t)1, size_in_pages * _page_size / MAX2(G1PretouchTask::chunk_size(), _page_size));
271
272 uint num_workers = MIN2((uint)num_chunks, pretouch_gang->active_workers());
273 log_debug(gc, heap)("Running %s with %u workers for " SIZE_FORMAT " work units pre-touching " SIZE_FORMAT "B.",
274 cl.name(), num_workers, num_chunks, size_in_pages * _page_size);
|
234 char* const _end_addr;
235 size_t const _page_size;
236 public:
237 G1PretouchTask(char* start_address, char* end_address, size_t page_size) :
238 AbstractGangTask("G1 PreTouch",
239 Universe::is_fully_initialized() &&
240 Thread::current()->is_Named_thread() ? GCId::current_raw() :
241 // During VM initialization there is
242 // no GC cycle that this task can be
243 // associated with.
244 GCId::undefined()),
245 _cur_addr(start_address),
246 _start_addr(start_address),
247 _end_addr(end_address),
248 _page_size(page_size) {
249 }
250
251 virtual void work(uint worker_id) {
252 size_t const actual_chunk_size = MAX2(chunk_size(), _page_size);
253 while (true) {
254 char* touch_addr = (char*)Atomic::add(actual_chunk_size, &_cur_addr) - actual_chunk_size;
255 if (touch_addr < _start_addr || touch_addr >= _end_addr) {
256 break;
257 }
258 char* end_addr = touch_addr + MIN2(actual_chunk_size, pointer_delta(_end_addr, touch_addr, sizeof(char)));
259 os::pretouch_memory(touch_addr, end_addr, _page_size);
260 }
261 }
262
263 static size_t chunk_size() { return PreTouchParallelChunkSize; }
264 };
265
266 void G1PageBasedVirtualSpace::pretouch(size_t start_page, size_t size_in_pages, WorkGang* pretouch_gang) {
267 G1PretouchTask cl(page_start(start_page), bounded_end_addr(start_page + size_in_pages), _page_size);
268
269 if (pretouch_gang != NULL) {
270 size_t num_chunks = MAX2((size_t)1, size_in_pages * _page_size / MAX2(G1PretouchTask::chunk_size(), _page_size));
271
272 uint num_workers = MIN2((uint)num_chunks, pretouch_gang->active_workers());
273 log_debug(gc, heap)("Running %s with %u workers for " SIZE_FORMAT " work units pre-touching " SIZE_FORMAT "B.",
274 cl.name(), num_workers, num_chunks, size_in_pages * _page_size);
|