1/*
2 * Copyright (c) 2013, 2018, Red Hat, Inc. All rights reserved.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This code is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
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_SHENANDOAH_SHENANDOAHCONTROLTHREAD_HPP
25#define SHARE_GC_SHENANDOAH_SHENANDOAHCONTROLTHREAD_HPP
26
27#include "gc/shared/gcCause.hpp"
28#include "gc/shared/concurrentGCThread.hpp"
29#include "gc/shenandoah/shenandoahHeap.hpp"
30#include "gc/shenandoah/shenandoahSharedVariables.hpp"
31#include "runtime/task.hpp"
32#include "utilities/ostream.hpp"
33
34// Periodic task is useful for doing asynchronous things that do not require (heap) locks,
35// or synchronization with other parts of collector. These could run even when ShenandoahConcurrentThread
36// is busy driving the GC cycle.
37class ShenandoahPeriodicTask : public PeriodicTask {
38private:
39 ShenandoahControlThread* _thread;
40public:
41 ShenandoahPeriodicTask(ShenandoahControlThread* thread) :
42 PeriodicTask(100), _thread(thread) {}
43 virtual void task();
44};
45
46// Periodic task to flush SATB buffers periodically.
47class ShenandoahPeriodicSATBFlushTask : public PeriodicTask {
48public:
49 ShenandoahPeriodicSATBFlushTask() : PeriodicTask(ShenandoahSATBBufferFlushInterval) {}
50 virtual void task();
51};
52
53class ShenandoahControlThread: public ConcurrentGCThread {
54 friend class VMStructs;
55
56private:
57 typedef enum {
58 none,
59 concurrent_traversal,
60 concurrent_normal,
61 stw_degenerated,
62 stw_full
63 } GCMode;
64
65 // While we could have a single lock for these, it may risk unblocking
66 // GC waiters when alloc failure GC cycle finishes. We want instead
67 // to make complete explicit cycle for for demanding customers.
68 Monitor _alloc_failure_waiters_lock;
69 Monitor _gc_waiters_lock;
70 ShenandoahPeriodicTask _periodic_task;
71 ShenandoahPeriodicSATBFlushTask _periodic_satb_flush_task;
72
73public:
74 void run_service();
75 void stop_service();
76
77private:
78 ShenandoahSharedFlag _gc_requested;
79 ShenandoahSharedFlag _alloc_failure_gc;
80 ShenandoahSharedFlag _graceful_shutdown;
81 ShenandoahSharedFlag _heap_changed;
82 ShenandoahSharedFlag _do_counters_update;
83 ShenandoahSharedFlag _force_counters_update;
84 GCCause::Cause _requested_gc_cause;
85 ShenandoahHeap::ShenandoahDegenPoint _degen_point;
86
87 DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile size_t));
88 volatile size_t _allocs_seen;
89 DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0);
90
91 bool check_cancellation_or_degen(ShenandoahHeap::ShenandoahDegenPoint point);
92 void service_concurrent_normal_cycle(GCCause::Cause cause);
93 void service_stw_full_cycle(GCCause::Cause cause);
94 void service_stw_degenerated_cycle(GCCause::Cause cause, ShenandoahHeap::ShenandoahDegenPoint point);
95 void service_concurrent_traversal_cycle(GCCause::Cause cause);
96 void service_uncommit(double shrink_before);
97
98 bool try_set_alloc_failure_gc();
99 void notify_alloc_failure_waiters();
100 bool is_alloc_failure_gc();
101
102 void notify_gc_waiters();
103
104 // Handle GC request.
105 // Blocks until GC is over.
106 void handle_requested_gc(GCCause::Cause cause);
107
108 bool is_explicit_gc(GCCause::Cause cause) const;
109public:
110 // Constructor
111 ShenandoahControlThread();
112 ~ShenandoahControlThread();
113
114 // Handle allocation failure from normal allocation.
115 // Blocks until memory is available.
116 void handle_alloc_failure(size_t words);
117
118 // Handle allocation failure from evacuation path.
119 // Optionally blocks while collector is handling the failure.
120 void handle_alloc_failure_evac(size_t words);
121
122 void request_gc(GCCause::Cause cause);
123
124 void handle_counters_update();
125 void handle_force_counters_update();
126 void set_forced_counters_update(bool value);
127
128 void notify_heap_changed();
129
130 void pacing_notify_alloc(size_t words);
131
132 void start();
133 void prepare_for_graceful_shutdown();
134 bool in_graceful_shutdown();
135
136 char* name() const { return (char*)"ShenandoahControlThread";}
137
138 // Printing
139 void print_on(outputStream* st) const;
140 void print() const;
141};
142
143#endif // SHARE_GC_SHENANDOAH_SHENANDOAHCONTROLTHREAD_HPP
144