1.1 --- a/src/share/vm/gc_implementation/g1/sparsePRT.hpp Fri Jan 21 11:30:22 2011 -0500 1.2 +++ b/src/share/vm/gc_implementation/g1/sparsePRT.hpp Tue Jan 25 17:58:19 2011 -0500 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -212,8 +212,11 @@ 1.11 // mutex. 1.12 1.13 class SparsePRTIter; 1.14 +class SparsePRTCleanupTask; 1.15 1.16 class SparsePRT VALUE_OBJ_CLASS_SPEC { 1.17 + friend class SparsePRTCleanupTask; 1.18 + 1.19 // Iterations are done on the _cur hash table, since they only need to 1.20 // see entries visible at the start of a collection pause. 1.21 // All other operations are done using the _next hash table. 1.22 @@ -238,6 +241,8 @@ 1.23 SparsePRT* next_expanded() { return _next_expanded; } 1.24 void set_next_expanded(SparsePRT* nxt) { _next_expanded = nxt; } 1.25 1.26 + bool should_be_on_expanded_list(); 1.27 + 1.28 static SparsePRT* _head_expanded_list; 1.29 1.30 public: 1.31 @@ -284,12 +289,36 @@ 1.32 static void add_to_expanded_list(SparsePRT* sprt); 1.33 static SparsePRT* get_from_expanded_list(); 1.34 1.35 + // The purpose of these three methods is to help the GC workers 1.36 + // during the cleanup pause to recreate the expanded list, purging 1.37 + // any tables from it that belong to regions that are freed during 1.38 + // cleanup (if we don't purge those tables, there is a race that 1.39 + // causes various crashes; see CR 7014261). 1.40 + // 1.41 + // We chose to recreate the expanded list, instead of purging 1.42 + // entries from it by iterating over it, to avoid this serial phase 1.43 + // at the end of the cleanup pause. 1.44 + // 1.45 + // The three methods below work as follows: 1.46 + // * reset_for_cleanup_tasks() : Nulls the expanded list head at the 1.47 + // start of the cleanup pause. 1.48 + // * do_cleanup_work() : Called by the cleanup workers for every 1.49 + // region that is not free / is being freed by the cleanup 1.50 + // pause. It creates a list of expanded tables whose head / tail 1.51 + // are on the thread-local SparsePRTCleanupTask object. 1.52 + // * finish_cleanup_task() : Called by the cleanup workers after 1.53 + // they complete their cleanup task. It adds the local list into 1.54 + // the global expanded list. It assumes that the 1.55 + // ParGCRareEvent_lock is being held to ensure MT-safety. 1.56 + static void reset_for_cleanup_tasks(); 1.57 + void do_cleanup_work(SparsePRTCleanupTask* sprt_cleanup_task); 1.58 + static void finish_cleanup_task(SparsePRTCleanupTask* sprt_cleanup_task); 1.59 + 1.60 bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const { 1.61 return _next->contains_card(region_id, card_index); 1.62 } 1.63 }; 1.64 1.65 - 1.66 class SparsePRTIter: public RSHashTableIter { 1.67 public: 1.68 void init(const SparsePRT* sprt) { 1.69 @@ -300,4 +329,22 @@ 1.70 } 1.71 }; 1.72 1.73 +// This allows each worker during a cleanup pause to create a 1.74 +// thread-local list of sparse tables that have been expanded and need 1.75 +// to be processed at the beginning of the next GC pause. This lists 1.76 +// are concatenated into the single expanded list at the end of the 1.77 +// cleanup pause. 1.78 +class SparsePRTCleanupTask VALUE_OBJ_CLASS_SPEC { 1.79 +private: 1.80 + SparsePRT* _head; 1.81 + SparsePRT* _tail; 1.82 + 1.83 +public: 1.84 + SparsePRTCleanupTask() : _head(NULL), _tail(NULL) { } 1.85 + 1.86 + void add(SparsePRT* sprt); 1.87 + SparsePRT* head() { return _head; } 1.88 + SparsePRT* tail() { return _tail; } 1.89 +}; 1.90 + 1.91 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_SPARSEPRT_HPP