--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp Fri Jan 21 11:30:22 2011 -0500
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp Tue Jan 25 17:58:19 2011 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -212,8 +212,11 @@
// mutex.
class SparsePRTIter;
+class SparsePRTCleanupTask;
class SparsePRT VALUE_OBJ_CLASS_SPEC {
+ friend class SparsePRTCleanupTask;
+
// Iterations are done on the _cur hash table, since they only need to
// see entries visible at the start of a collection pause.
// All other operations are done using the _next hash table.
@@ -238,6 +241,8 @@
SparsePRT* next_expanded() { return _next_expanded; }
void set_next_expanded(SparsePRT* nxt) { _next_expanded = nxt; }
+ bool should_be_on_expanded_list();
+
static SparsePRT* _head_expanded_list;
public:
@@ -284,12 +289,36 @@
static void add_to_expanded_list(SparsePRT* sprt);
static SparsePRT* get_from_expanded_list();
+ // The purpose of these three methods is to help the GC workers
+ // during the cleanup pause to recreate the expanded list, purging
+ // any tables from it that belong to regions that are freed during
+ // cleanup (if we don't purge those tables, there is a race that
+ // causes various crashes; see CR 7014261).
+ //
+ // We chose to recreate the expanded list, instead of purging
+ // entries from it by iterating over it, to avoid this serial phase
+ // at the end of the cleanup pause.
+ //
+ // The three methods below work as follows:
+ // * reset_for_cleanup_tasks() : Nulls the expanded list head at the
+ // start of the cleanup pause.
+ // * do_cleanup_work() : Called by the cleanup workers for every
+ // region that is not free / is being freed by the cleanup
+ // pause. It creates a list of expanded tables whose head / tail
+ // are on the thread-local SparsePRTCleanupTask object.
+ // * finish_cleanup_task() : Called by the cleanup workers after
+ // they complete their cleanup task. It adds the local list into
+ // the global expanded list. It assumes that the
+ // ParGCRareEvent_lock is being held to ensure MT-safety.
+ static void reset_for_cleanup_tasks();
+ void do_cleanup_work(SparsePRTCleanupTask* sprt_cleanup_task);
+ static void finish_cleanup_task(SparsePRTCleanupTask* sprt_cleanup_task);
+
bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const {
return _next->contains_card(region_id, card_index);
}
};
-
class SparsePRTIter: public RSHashTableIter {
public:
void init(const SparsePRT* sprt) {
@@ -300,4 +329,22 @@
}
};
+// This allows each worker during a cleanup pause to create a
+// thread-local list of sparse tables that have been expanded and need
+// to be processed at the beginning of the next GC pause. This lists
+// are concatenated into the single expanded list at the end of the
+// cleanup pause.
+class SparsePRTCleanupTask VALUE_OBJ_CLASS_SPEC {
+private:
+ SparsePRT* _head;
+ SparsePRT* _tail;
+
+public:
+ SparsePRTCleanupTask() : _head(NULL), _tail(NULL) { }
+
+ void add(SparsePRT* sprt);
+ SparsePRT* head() { return _head; }
+ SparsePRT* tail() { return _tail; }
+};
+
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_SPARSEPRT_HPP