Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/gc/shenandoah/shenandoahEvacOOMHandler.hpp
40961 views
1
/*
2
* Copyright (c) 2018, 2020, Red Hat, Inc. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHEVACOOMHANDLER_HPP
26
#define SHARE_GC_SHENANDOAH_SHENANDOAHEVACOOMHANDLER_HPP
27
28
#include "gc/shenandoah/shenandoahPadding.hpp"
29
#include "memory/allocation.hpp"
30
#include "runtime/thread.hpp"
31
#include "utilities/globalDefinitions.hpp"
32
33
/**
34
* Provides safe handling of out-of-memory situations during evacuation.
35
*
36
* When a Java thread encounters out-of-memory while evacuating an object in a
37
* load-reference-barrier (i.e. it cannot copy the object to to-space), it does not
38
* necessarily follow we can return immediately from the LRB (and store to from-space).
39
*
40
* In very basic case, on such failure we may wait until the the evacuation is over,
41
* and then resolve the forwarded copy, and to the store there. This is possible
42
* because other threads might still have space in their GCLABs, and successfully
43
* evacuate the object.
44
*
45
* But, there is a race due to non-atomic evac_in_progress transition. Consider
46
* thread A is stuck waiting for the evacuation to be over -- it cannot leave with
47
* from-space copy yet. Control thread drops evacuation_in_progress preparing for
48
* next STW phase that has to recover from OOME. Thread B misses that update, and
49
* successfully evacuates the object, does the write to to-copy. But, before
50
* Thread B is able to install the fwdptr, thread A discovers evac_in_progress is
51
* down, exits from here, reads the fwdptr, discovers old from-copy, and stores there.
52
* Thread B then wakes up and installs to-copy. This breaks to-space invariant, and
53
* silently corrupts the heap: we accepted two writes to separate copies of the object.
54
*
55
* The way it is solved here is to maintain a counter of threads inside the
56
* 'evacuation path'. The 'evacuation path' is the part of evacuation that does the actual
57
* allocation, copying and CASing of the copy object, and is protected by this
58
* OOM-during-evac-handler. The handler allows multiple threads to enter and exit
59
* evacuation path, but on OOME it requires all threads that experienced OOME to wait
60
* for current threads to leave, and blocks other threads from entering.
61
*
62
* Detailed state change:
63
*
64
* Upon entry of the evac-path, entering thread will attempt to increase the counter,
65
* using a CAS. Depending on the result of the CAS:
66
* - success: carry on with evac
67
* - failure:
68
* - if offending value is a valid counter, then try again
69
* - if offending value is OOM-during-evac special value: loop until
70
* counter drops to 0, then exit with resolving the ptr
71
*
72
* Upon exit, exiting thread will decrease the counter using atomic dec.
73
*
74
* Upon OOM-during-evac, any thread will attempt to CAS OOM-during-evac
75
* special value into the counter. Depending on result:
76
* - success: busy-loop until counter drops to zero, then exit with resolve
77
* - failure:
78
* - offender is valid counter update: try again
79
* - offender is OOM-during-evac: busy loop until counter drops to
80
* zero, then exit with resolve
81
*/
82
class ShenandoahEvacOOMHandler {
83
private:
84
static const jint OOM_MARKER_MASK;
85
86
shenandoah_padding(0);
87
volatile jint _threads_in_evac;
88
shenandoah_padding(1);
89
90
void wait_for_no_evac_threads();
91
92
public:
93
ShenandoahEvacOOMHandler();
94
95
/**
96
* Attempt to enter the protected evacuation path.
97
*
98
* When this returns true, it is safe to continue with normal evacuation.
99
* When this method returns false, evacuation must not be entered, and caller
100
* may safely continue with a simple resolve (if Java thread).
101
*/
102
inline void enter_evacuation(Thread* t);
103
104
/**
105
* Leave evacuation path.
106
*/
107
inline void leave_evacuation(Thread* t);
108
109
/**
110
* Signal out-of-memory during evacuation. It will prevent any other threads
111
* from entering the evacuation path, then wait until all threads have left the
112
* evacuation path, and then return. It is then safe to continue with a simple resolve.
113
*/
114
void handle_out_of_memory_during_evacuation();
115
116
void clear();
117
118
private:
119
// Register/Unregister thread to evacuation OOM protocol
120
void register_thread(Thread* t);
121
void unregister_thread(Thread* t);
122
};
123
124
class ShenandoahEvacOOMScope : public StackObj {
125
private:
126
Thread* const _thread;
127
128
public:
129
inline ShenandoahEvacOOMScope();
130
inline ShenandoahEvacOOMScope(Thread* t);
131
inline ~ShenandoahEvacOOMScope();
132
};
133
134
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHEVACOOMHANDLER_HPP
135
136