< prev index next >

src/share/vm/gc/g1/g1PageBasedVirtualSpace.cpp

Print this page
rev 12309 : [mq]: 8169703-crash-with-alwayspretouch


 218   if (_special) {
 219     // Mark that memory is dirty. If committed again the memory might
 220     // need to be cleared explicitly.
 221     _dirty.set_range(start_page, end_page);
 222   } else {
 223     uncommit_internal(start_page, end_page);
 224   }
 225 
 226   _committed.clear_range(start_page, end_page);
 227 }
 228 
 229 class G1PretouchTask : public AbstractGangTask {
 230 private:
 231   char* volatile _cur_addr;
 232   char* const _start_addr;
 233   char* const _end_addr;
 234   size_t const _page_size;
 235 public:
 236   G1PretouchTask(char* start_address, char* end_address, size_t page_size) :
 237     AbstractGangTask("G1 PreTouch",
 238                      Universe::is_fully_initialized() ? GCId::current_raw() :

 239                                                         // During VM initialization there is
 240                                                         // no GC cycle that this task can be
 241                                                         // associated with.
 242                                                         GCId::undefined()),
 243     _cur_addr(start_address),
 244     _start_addr(start_address),
 245     _end_addr(end_address),
 246     _page_size(page_size) {
 247   }
 248 
 249   virtual void work(uint worker_id) {
 250     size_t const actual_chunk_size = MAX2(chunk_size(), _page_size);
 251     while (true) {
 252       char* touch_addr = (char*)Atomic::add_ptr((intptr_t)actual_chunk_size, (volatile void*) &_cur_addr) - actual_chunk_size;
 253       if (touch_addr < _start_addr || touch_addr >= _end_addr) {
 254         break;
 255       }
 256       char* end_addr = touch_addr + MIN2(actual_chunk_size, pointer_delta(_end_addr, touch_addr, sizeof(char)));
 257       os::pretouch_memory(touch_addr, end_addr, _page_size);
 258     }
 259   }
 260 
 261   static size_t chunk_size() { return PreTouchParallelChunkSize; }
 262 };
 263 
 264 void G1PageBasedVirtualSpace::pretouch(size_t start_page, size_t size_in_pages, WorkGang* pretouch_gang) {
 265   guarantee(pretouch_gang != NULL, "No pretouch gang specified.");
 266 

 267   size_t num_chunks = MAX2((size_t)1, size_in_pages * _page_size / MAX2(G1PretouchTask::chunk_size(), _page_size));
 268 
 269   uint num_workers = MIN2((uint)num_chunks, pretouch_gang->active_workers());
 270   G1PretouchTask cl(page_start(start_page), bounded_end_addr(start_page + size_in_pages), _page_size);
 271   log_debug(gc, heap)("Running %s with %u workers for " SIZE_FORMAT " work units pre-touching " SIZE_FORMAT "B.",
 272                       cl.name(), num_workers, num_chunks, size_in_pages * _page_size);
 273   pretouch_gang->run_task(&cl, num_workers);





 274 }
 275 
 276 bool G1PageBasedVirtualSpace::contains(const void* p) const {
 277   return _low_boundary <= (const char*) p && (const char*) p < _high_boundary;
 278 }
 279 
 280 #ifndef PRODUCT
 281 void G1PageBasedVirtualSpace::print_on(outputStream* out) {
 282   out->print   ("Virtual space:");
 283   if (_special) out->print(" (pinned in memory)");
 284   out->cr();
 285   out->print_cr(" - committed: " SIZE_FORMAT, committed_size());
 286   out->print_cr(" - reserved:  " SIZE_FORMAT, reserved_size());
 287   out->print_cr(" - preferred page size: " SIZE_FORMAT, _page_size);
 288   out->print_cr(" - [low_b, high_b]: [" PTR_FORMAT ", " PTR_FORMAT "]",  p2i(_low_boundary), p2i(_high_boundary));
 289 }
 290 
 291 void G1PageBasedVirtualSpace::print() {
 292   print_on(tty);
 293 }


 218   if (_special) {
 219     // Mark that memory is dirty. If committed again the memory might
 220     // need to be cleared explicitly.
 221     _dirty.set_range(start_page, end_page);
 222   } else {
 223     uncommit_internal(start_page, end_page);
 224   }
 225 
 226   _committed.clear_range(start_page, end_page);
 227 }
 228 
 229 class G1PretouchTask : public AbstractGangTask {
 230 private:
 231   char* volatile _cur_addr;
 232   char* const _start_addr;
 233   char* const _end_addr;
 234   size_t const _page_size;
 235 public:
 236   G1PretouchTask(char* start_address, char* end_address, size_t page_size) :
 237     AbstractGangTask("G1 PreTouch",
 238                      Universe::is_fully_initialized() && 
 239                      Thread::current()->is_Named_thread() ? GCId::current_raw() :
 240                                                             // During VM initialization there is
 241                                                             // no GC cycle that this task can be
 242                                                             // associated with.
 243                                                             GCId::undefined()),
 244     _cur_addr(start_address),
 245     _start_addr(start_address),
 246     _end_addr(end_address),
 247     _page_size(page_size) {
 248   }
 249 
 250   virtual void work(uint worker_id) {
 251     size_t const actual_chunk_size = MAX2(chunk_size(), _page_size);
 252     while (true) {
 253       char* touch_addr = (char*)Atomic::add_ptr((intptr_t)actual_chunk_size, (volatile void*) &_cur_addr) - actual_chunk_size;
 254       if (touch_addr < _start_addr || touch_addr >= _end_addr) {
 255         break;
 256       }
 257       char* end_addr = touch_addr + MIN2(actual_chunk_size, pointer_delta(_end_addr, touch_addr, sizeof(char)));
 258       os::pretouch_memory(touch_addr, end_addr, _page_size);
 259     }
 260   }
 261 
 262   static size_t chunk_size() { return PreTouchParallelChunkSize; }
 263 };
 264 
 265 void G1PageBasedVirtualSpace::pretouch(size_t start_page, size_t size_in_pages, WorkGang* pretouch_gang) {
 266   G1PretouchTask cl(page_start(start_page), bounded_end_addr(start_page + size_in_pages), _page_size);
 267 
 268   if (pretouch_gang != NULL) {
 269     size_t num_chunks = MAX2((size_t)1, size_in_pages * _page_size / MAX2(G1PretouchTask::chunk_size(), _page_size));
 270 
 271     uint num_workers = MIN2((uint)num_chunks, pretouch_gang->active_workers());

 272     log_debug(gc, heap)("Running %s with %u workers for " SIZE_FORMAT " work units pre-touching " SIZE_FORMAT "B.",
 273                         cl.name(), num_workers, num_chunks, size_in_pages * _page_size);
 274     pretouch_gang->run_task(&cl, num_workers);
 275   } else {
 276     log_debug(gc, heap)("Running %s pre-touching " SIZE_FORMAT "B.",
 277                         cl.name(), size_in_pages * _page_size);
 278     cl.work(0);
 279   }
 280 }
 281 
 282 bool G1PageBasedVirtualSpace::contains(const void* p) const {
 283   return _low_boundary <= (const char*) p && (const char*) p < _high_boundary;
 284 }
 285 
 286 #ifndef PRODUCT
 287 void G1PageBasedVirtualSpace::print_on(outputStream* out) {
 288   out->print   ("Virtual space:");
 289   if (_special) out->print(" (pinned in memory)");
 290   out->cr();
 291   out->print_cr(" - committed: " SIZE_FORMAT, committed_size());
 292   out->print_cr(" - reserved:  " SIZE_FORMAT, reserved_size());
 293   out->print_cr(" - preferred page size: " SIZE_FORMAT, _page_size);
 294   out->print_cr(" - [low_b, high_b]: [" PTR_FORMAT ", " PTR_FORMAT "]",  p2i(_low_boundary), p2i(_high_boundary));
 295 }
 296 
 297 void G1PageBasedVirtualSpace::print() {
 298   print_on(tty);
 299 }
< prev index next >