comparison src/share/vm/gc_implementation/g1/concurrentMark.cpp @ 2173:97ba643ea3ed

7014261: G1: RSet-related failures Summary: A race between the concurrent cleanup thread and the VM thread while it is processing the "expanded sparse table list" causes both threads to try to free the same sparse table entry and either causes one of the threads to fail or leaves the entry in an inconsistent state. The solution is purge all entries on the expanded list that correspond go regions that are being cleaned up. Reviewed-by: brutisso, johnc
author tonyp
date Tue, 25 Jan 2011 17:58:19 -0500
parents 0fa27f37d4d4
children 81668b1f4877
comparison
equal deleted inserted replaced
2172:a672e43650cc 2173:97ba643ea3ed
1498 G1CollectedHeap* _g1; 1498 G1CollectedHeap* _g1;
1499 int _worker_num; 1499 int _worker_num;
1500 size_t _max_live_bytes; 1500 size_t _max_live_bytes;
1501 size_t _regions_claimed; 1501 size_t _regions_claimed;
1502 size_t _freed_bytes; 1502 size_t _freed_bytes;
1503 FreeRegionList _local_cleanup_list; 1503 FreeRegionList* _local_cleanup_list;
1504 HumongousRegionSet _humongous_proxy_set; 1504 HumongousRegionSet* _humongous_proxy_set;
1505 HRRSCleanupTask* _hrrs_cleanup_task;
1505 double _claimed_region_time; 1506 double _claimed_region_time;
1506 double _max_region_time; 1507 double _max_region_time;
1507 1508
1508 public: 1509 public:
1509 G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1, 1510 G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1,
1510 int worker_num); 1511 int worker_num,
1512 FreeRegionList* local_cleanup_list,
1513 HumongousRegionSet* humongous_proxy_set,
1514 HRRSCleanupTask* hrrs_cleanup_task);
1511 size_t freed_bytes() { return _freed_bytes; } 1515 size_t freed_bytes() { return _freed_bytes; }
1512 FreeRegionList* local_cleanup_list() {
1513 return &_local_cleanup_list;
1514 }
1515 HumongousRegionSet* humongous_proxy_set() {
1516 return &_humongous_proxy_set;
1517 }
1518 1516
1519 bool doHeapRegion(HeapRegion *r); 1517 bool doHeapRegion(HeapRegion *r);
1520 1518
1521 size_t max_live_bytes() { return _max_live_bytes; } 1519 size_t max_live_bytes() { return _max_live_bytes; }
1522 size_t regions_claimed() { return _regions_claimed; } 1520 size_t regions_claimed() { return _regions_claimed; }
1539 AbstractGangTask("G1 note end"), _g1h(g1h), 1537 AbstractGangTask("G1 note end"), _g1h(g1h),
1540 _max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list) { } 1538 _max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list) { }
1541 1539
1542 void work(int i) { 1540 void work(int i) {
1543 double start = os::elapsedTime(); 1541 double start = os::elapsedTime();
1544 G1NoteEndOfConcMarkClosure g1_note_end(_g1h, i); 1542 FreeRegionList local_cleanup_list("Local Cleanup List");
1543 HumongousRegionSet humongous_proxy_set("Local Cleanup Humongous Proxy Set");
1544 HRRSCleanupTask hrrs_cleanup_task;
1545 G1NoteEndOfConcMarkClosure g1_note_end(_g1h, i, &local_cleanup_list,
1546 &humongous_proxy_set,
1547 &hrrs_cleanup_task);
1545 if (G1CollectedHeap::use_parallel_gc_threads()) { 1548 if (G1CollectedHeap::use_parallel_gc_threads()) {
1546 _g1h->heap_region_par_iterate_chunked(&g1_note_end, i, 1549 _g1h->heap_region_par_iterate_chunked(&g1_note_end, i,
1547 HeapRegion::NoteEndClaimValue); 1550 HeapRegion::NoteEndClaimValue);
1548 } else { 1551 } else {
1549 _g1h->heap_region_iterate(&g1_note_end); 1552 _g1h->heap_region_iterate(&g1_note_end);
1551 assert(g1_note_end.complete(), "Shouldn't have yielded!"); 1554 assert(g1_note_end.complete(), "Shouldn't have yielded!");
1552 1555
1553 // Now update the lists 1556 // Now update the lists
1554 _g1h->update_sets_after_freeing_regions(g1_note_end.freed_bytes(), 1557 _g1h->update_sets_after_freeing_regions(g1_note_end.freed_bytes(),
1555 NULL /* free_list */, 1558 NULL /* free_list */,
1556 g1_note_end.humongous_proxy_set(), 1559 &humongous_proxy_set,
1557 true /* par */); 1560 true /* par */);
1558 { 1561 {
1559 MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); 1562 MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
1560 _max_live_bytes += g1_note_end.max_live_bytes(); 1563 _max_live_bytes += g1_note_end.max_live_bytes();
1561 _freed_bytes += g1_note_end.freed_bytes(); 1564 _freed_bytes += g1_note_end.freed_bytes();
1562 1565
1563 _cleanup_list->add_as_tail(g1_note_end.local_cleanup_list()); 1566 _cleanup_list->add_as_tail(&local_cleanup_list);
1564 assert(g1_note_end.local_cleanup_list()->is_empty(), "post-condition"); 1567 assert(local_cleanup_list.is_empty(), "post-condition");
1568
1569 HeapRegionRemSet::finish_cleanup_task(&hrrs_cleanup_task);
1565 } 1570 }
1566 double end = os::elapsedTime(); 1571 double end = os::elapsedTime();
1567 if (G1PrintParCleanupStats) { 1572 if (G1PrintParCleanupStats) {
1568 gclog_or_tty->print(" Worker thread %d [%8.3f..%8.3f = %8.3f ms] " 1573 gclog_or_tty->print(" Worker thread %d [%8.3f..%8.3f = %8.3f ms] "
1569 "claimed %d regions (tot = %8.3f ms, max = %8.3f ms).\n", 1574 "claimed %d regions (tot = %8.3f ms, max = %8.3f ms).\n",
1600 1605
1601 }; 1606 };
1602 1607
1603 G1NoteEndOfConcMarkClosure:: 1608 G1NoteEndOfConcMarkClosure::
1604 G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1, 1609 G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1,
1605 int worker_num) 1610 int worker_num,
1611 FreeRegionList* local_cleanup_list,
1612 HumongousRegionSet* humongous_proxy_set,
1613 HRRSCleanupTask* hrrs_cleanup_task)
1606 : _g1(g1), _worker_num(worker_num), 1614 : _g1(g1), _worker_num(worker_num),
1607 _max_live_bytes(0), _regions_claimed(0), 1615 _max_live_bytes(0), _regions_claimed(0),
1608 _freed_bytes(0), 1616 _freed_bytes(0),
1609 _claimed_region_time(0.0), _max_region_time(0.0), 1617 _claimed_region_time(0.0), _max_region_time(0.0),
1610 _local_cleanup_list("Local Cleanup List"), 1618 _local_cleanup_list(local_cleanup_list),
1611 _humongous_proxy_set("Local Cleanup Humongous Proxy Set") { } 1619 _humongous_proxy_set(humongous_proxy_set),
1620 _hrrs_cleanup_task(hrrs_cleanup_task) { }
1612 1621
1613 bool G1NoteEndOfConcMarkClosure::doHeapRegion(HeapRegion *hr) { 1622 bool G1NoteEndOfConcMarkClosure::doHeapRegion(HeapRegion *hr) {
1614 // We use a claim value of zero here because all regions 1623 // We use a claim value of zero here because all regions
1615 // were claimed with value 1 in the FinalCount task. 1624 // were claimed with value 1 in the FinalCount task.
1616 hr->reset_gc_time_stamp(); 1625 hr->reset_gc_time_stamp();
1617 if (!hr->continuesHumongous()) { 1626 if (!hr->continuesHumongous()) {
1618 double start = os::elapsedTime(); 1627 double start = os::elapsedTime();
1619 _regions_claimed++; 1628 _regions_claimed++;
1620 hr->note_end_of_marking(); 1629 hr->note_end_of_marking();
1621 _max_live_bytes += hr->max_live_bytes(); 1630 _max_live_bytes += hr->max_live_bytes();
1622 _g1->free_region_if_totally_empty(hr, 1631 _g1->free_region_if_empty(hr,
1623 &_freed_bytes, 1632 &_freed_bytes,
1624 &_local_cleanup_list, 1633 _local_cleanup_list,
1625 &_humongous_proxy_set, 1634 _humongous_proxy_set,
1626 true /* par */); 1635 _hrrs_cleanup_task,
1636 true /* par */);
1627 double region_time = (os::elapsedTime() - start); 1637 double region_time = (os::elapsedTime() - start);
1628 _claimed_region_time += region_time; 1638 _claimed_region_time += region_time;
1629 if (region_time > _max_region_time) _max_region_time = region_time; 1639 if (region_time > _max_region_time) _max_region_time = region_time;
1630 } 1640 }
1631 return false; 1641 return false;
1656 1666
1657 G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy(); 1667 G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy();
1658 g1p->record_concurrent_mark_cleanup_start(); 1668 g1p->record_concurrent_mark_cleanup_start();
1659 1669
1660 double start = os::elapsedTime(); 1670 double start = os::elapsedTime();
1671
1672 HeapRegionRemSet::reset_for_cleanup_tasks();
1661 1673
1662 // Do counting once more with the world stopped for good measure. 1674 // Do counting once more with the world stopped for good measure.
1663 G1ParFinalCountTask g1_par_count_task(g1h, nextMarkBitMap(), 1675 G1ParFinalCountTask g1_par_count_task(g1h, nextMarkBitMap(),
1664 &_region_bm, &_card_bm); 1676 &_region_bm, &_card_bm);
1665 if (G1CollectedHeap::use_parallel_gc_threads()) { 1677 if (G1CollectedHeap::use_parallel_gc_threads()) {