13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24 #ifndef SHARE_GC_SHARED_OOPSTORAGEPARSTATE_HPP
25 #define SHARE_GC_SHARED_OOPSTORAGEPARSTATE_HPP
26
27 #include "gc/shared/oopStorage.hpp"
28 #include "utilities/macros.hpp"
29
30 //////////////////////////////////////////////////////////////////////////////
31 // Support for parallel and optionally concurrent state iteration.
32 //
33 // Parallel iteration is for the exclusive use of the GC. Other iteration
34 // clients must use serial iteration.
35 //
36 // Concurrent Iteration
37 //
38 // Iteration involves the _active_array (an ActiveArray), which contains all
39 // of the blocks owned by a storage object.
40 //
41 // At most one concurrent ParState can exist at a time for a given storage
42 // object.
43 //
44 // A concurrent ParState sets the associated storage's
45 // _concurrent_iteration_active flag true when the state is constructed, and
46 // sets it false when the state is destroyed. These assignments are made with
47 // _active_mutex locked. Meanwhile, empty block deletion is not done while
48 // _concurrent_iteration_active is true. The flag check and the dependent
49 // removal of a block from the _active_array is performed with _active_mutex
50 // locked. This prevents concurrent iteration and empty block deletion from
51 // interfering with with each other.
52 //
53 // Both allocate() and delete_empty_blocks_concurrent() lock the
54 // _allocation_mutex while performing their respective list and array
55 // manipulations, preventing them from interfering with each other.
56 //
57 // When allocate() creates a new block, it is added to the end of the
58 // _active_array. Then _active_array's _block_count is incremented to account
59 // for the new block. When concurrent iteration is started (by a parallel
60 // worker thread calling the state's iterate() function), the current
61 // _active_array and its _block_count are captured for use by the iteration,
62 // with iteration processing all blocks in that array up to that block count.
63 //
64 // As a result, the sequence over which concurrent iteration operates is
65 // stable. However, once the iteration is started, later allocations may add
66 // blocks to the end of the array that won't be examined by the iteration.
67 // An allocation may even require expansion of the array, so the iteration is
68 // no longer processing the current array, but rather the previous one.
69 // And while the sequence is stable, concurrent allocate() and release()
70 // operations may change the set of allocated entries in a block at any time
71 // during the iteration.
72 //
73 // As a result, a concurrent iteration handler must accept that some
74 // allocations and releases that occur after the iteration started will not be
75 // seen by the iteration. Further, some may overlap examination by the
76 // iteration. To help with this, allocate() and release() have an invariant
77 // that an entry's value must be NULL when it is not in use.
78 //
79 // An in-progress delete_empty_blocks_concurrent() operation can contend with
80 // the start of a concurrent iteration over the _active_mutex. Since both are
81 // under GC control, that potential contention can be eliminated by never
82 // scheduling both operations to run at the same time.
83 //
84 // ParState<concurrent, is_const>
85 // concurrent must be true if iteration is concurrent with the
86 // mutator, false if iteration is at a safepoint.
87 //
88 // is_const must be true if the iteration is over a constant storage
89 // object, false if the iteration may modify the storage object.
90 //
91 // ParState([const] OopStorage* storage)
92 // Construct an object for managing an iteration over storage. For a
93 // concurrent ParState, empty block deletion for the associated storage
94 // is inhibited for the life of the ParState. There can be no more
95 // than one live concurrent ParState at a time for a given storage object.
96 //
97 // template<typename F> void iterate(F f)
98 // Repeatedly claims a block from the associated storage that has
99 // not been processed by this iteration (possibly by other threads),
100 // and applies f to each entry in the claimed block. Assume p is of
101 // type const oop* or oop*, according to is_const. Then f(p) must be
102 // a valid expression whose value is ignored. Concurrent uses must
103 // be prepared for an entry's value to change at any time, due to
104 // mutator activity.
105 //
106 // template<typename Closure> void oops_do(Closure* cl)
107 // Wrapper around iterate, providing an adaptation layer allowing
108 // the use of OopClosures and similar objects for iteration. Assume
109 // p is of type const oop* or oop*, according to is_const. Then
110 // cl->do_oop(p) must be a valid expression whose value is ignored.
111 // Concurrent uses must be prepared for the entry's value to change
112 // at any time, due to mutator activity.
113 //
114 // Optional operations, provided only if !concurrent && !is_const.
|
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24 #ifndef SHARE_GC_SHARED_OOPSTORAGEPARSTATE_HPP
25 #define SHARE_GC_SHARED_OOPSTORAGEPARSTATE_HPP
26
27 #include "gc/shared/oopStorage.hpp"
28 #include "utilities/macros.hpp"
29
30 //////////////////////////////////////////////////////////////////////////////
31 // Support for parallel and optionally concurrent state iteration.
32 //
33 // Concurrent Iteration
34 //
35 // Iteration involves the _active_array (an ActiveArray), which contains all
36 // of the blocks owned by a storage object.
37 //
38 // A concurrent ParState increments the associated storage's
39 // _concurrent_iteration_count count when the state is constructed, and
40 // decrements it when the state is destroyed. These assignments are made with
41 // _active_mutex locked. Meanwhile, empty block deletion is not done while
42 // _concurrent_iteration_count is non-zero. The counter check and the dependent
43 // removal of a block from the _active_array is performed with _active_mutex
44 // locked. This prevents concurrent iteration and empty block deletion from
45 // interfering with with each other.
46 //
47 // Both allocate() and delete_empty_blocks_concurrent() lock the
48 // _allocation_mutex while performing their respective list and array
49 // manipulations, preventing them from interfering with each other.
50 //
51 // When allocate() creates a new block, it is added to the end of the
52 // _active_array. Then _active_array's _block_count is incremented to account
53 // for the new block. When concurrent iteration is started (by a parallel
54 // worker thread calling the state's iterate() function), the current
55 // _active_array and its _block_count are captured for use by the iteration,
56 // with iteration processing all blocks in that array up to that block count.
57 //
58 // As a result, the sequence over which concurrent iteration operates is
59 // stable. However, once the iteration is started, later allocations may add
60 // blocks to the end of the array that won't be examined by the iteration.
61 // An allocation may even require expansion of the array, so the iteration is
62 // no longer processing the current array, but rather the previous one.
63 // And while the sequence is stable, concurrent allocate() and release()
64 // operations may change the set of allocated entries in a block at any time
65 // during the iteration.
66 //
67 // As a result, a concurrent iteration handler must accept that some
68 // allocations and releases that occur after the iteration started will not be
69 // seen by the iteration. Further, some may overlap examination by the
70 // iteration. To help with this, allocate() and release() have an invariant
71 // that an entry's value must be NULL when it is not in use.
72 //
73 // An in-progress delete_empty_blocks_concurrent() operation can contend with
74 // the start of a concurrent iteration over the _active_mutex. Since both are
75 // under GC control, that potential contention can be eliminated by never
76 // scheduling both operations to run at the same time.
77 //
78 // ParState<concurrent, is_const>
79 // concurrent must be true if iteration may be concurrent with the
80 // mutators.
81 //
82 // is_const must be true if the iteration is over a constant storage
83 // object, false if the iteration may modify the storage object.
84 //
85 // ParState([const] OopStorage* storage)
86 // Construct an object for managing an iteration over storage. For a
87 // concurrent ParState, empty block deletion for the associated storage
88 // is inhibited for the life of the ParState.
89 //
90 // template<typename F> void iterate(F f)
91 // Repeatedly claims a block from the associated storage that has
92 // not been processed by this iteration (possibly by other threads),
93 // and applies f to each entry in the claimed block. Assume p is of
94 // type const oop* or oop*, according to is_const. Then f(p) must be
95 // a valid expression whose value is ignored. Concurrent uses must
96 // be prepared for an entry's value to change at any time, due to
97 // mutator activity.
98 //
99 // template<typename Closure> void oops_do(Closure* cl)
100 // Wrapper around iterate, providing an adaptation layer allowing
101 // the use of OopClosures and similar objects for iteration. Assume
102 // p is of type const oop* or oop*, according to is_const. Then
103 // cl->do_oop(p) must be a valid expression whose value is ignored.
104 // Concurrent uses must be prepared for the entry's value to change
105 // at any time, due to mutator activity.
106 //
107 // Optional operations, provided only if !concurrent && !is_const.
|
134 // is convertible to bool.
135 //
136 // If *p == NULL then neither is_alive nor cl will be invoked for p.
137 // If is_alive->do_object_b(*p) is false, then cl will not be
138 // invoked on p.
139
140 class OopStorage::BasicParState {
141 const OopStorage* _storage;
142 ActiveArray* _active_array;
143 size_t _block_count;
144 volatile size_t _next_block;
145 uint _estimated_thread_count;
146 bool _concurrent;
147
148 // Noncopyable.
149 BasicParState(const BasicParState&);
150 BasicParState& operator=(const BasicParState&);
151
152 struct IterationData;
153
154 void update_iteration_state(bool value);
155 bool claim_next_segment(IterationData* data);
156 bool finish_iteration(const IterationData* data) const;
157
158 // Wrapper for iteration handler; ignore handler result and return true.
159 template<typename F> class AlwaysTrueFn;
160
161 public:
162 BasicParState(const OopStorage* storage,
163 uint estimated_thread_count,
164 bool concurrent);
165 ~BasicParState();
166
167 template<bool is_const, typename F> void iterate(F f);
168
169 static uint default_estimated_thread_count(bool concurrent);
170 };
171
172 template<bool concurrent, bool is_const>
173 class OopStorage::ParState {
|
127 // is convertible to bool.
128 //
129 // If *p == NULL then neither is_alive nor cl will be invoked for p.
130 // If is_alive->do_object_b(*p) is false, then cl will not be
131 // invoked on p.
132
133 class OopStorage::BasicParState {
134 const OopStorage* _storage;
135 ActiveArray* _active_array;
136 size_t _block_count;
137 volatile size_t _next_block;
138 uint _estimated_thread_count;
139 bool _concurrent;
140
141 // Noncopyable.
142 BasicParState(const BasicParState&);
143 BasicParState& operator=(const BasicParState&);
144
145 struct IterationData;
146
147 void update_concurrent_iteration_count(int value);
148 bool claim_next_segment(IterationData* data);
149 bool finish_iteration(const IterationData* data) const;
150
151 // Wrapper for iteration handler; ignore handler result and return true.
152 template<typename F> class AlwaysTrueFn;
153
154 public:
155 BasicParState(const OopStorage* storage,
156 uint estimated_thread_count,
157 bool concurrent);
158 ~BasicParState();
159
160 template<bool is_const, typename F> void iterate(F f);
161
162 static uint default_estimated_thread_count(bool concurrent);
163 };
164
165 template<bool concurrent, bool is_const>
166 class OopStorage::ParState {
|