270fa73 by Loïc Rouchon at 2010-01-17 1
/*
2
 * $Id$
3
 *
4
 * Copyright (C) 2003-2009 JNode.org
5
 *
6
 * This library is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU Lesser General Public License as published
8
 * by the Free Software Foundation; either version 2.1 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful, but 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
14
 * License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with this library; If not, write to the Free Software Foundation, Inc., 
18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
 */
ea37d1f by loic at 2010-01-25 20
270fa73 by Loïc Rouchon at 2010-01-17 21
package org.jnode.vm.memmgr.generational;
22
23
import org.jnode.vm.Unsafe;
24
import org.jnode.vm.scheduler.Monitor;
25
26
/**
27
 * @author Ewout Prangsma (epr@users.sourceforge.net)
28
 */
29
final class GenGCThread extends Thread {
30
31
    /**
32
     * The manager
33
     */
ea37d1f by loic at 2010-01-25 34
    private final GenGCManager manager;
270fa73 by Loïc Rouchon at 2010-01-17 35
36
    /**
37
     * Monitor for synchronizing access to my fields
38
     */
12865b3 by Loïc Rouchon at 2010-01-28 39
    private Monitor heapMonitor;
270fa73 by Loïc Rouchon at 2010-01-17 40
41
    /**
42
     * Is a GC run requested?
43
     */
2af7864 by Loïc Rouchon at 2010-02-01 44
    private boolean runMajorNeeded;
45
    private boolean runMinorNeeded;
270fa73 by Loïc Rouchon at 2010-01-17 46
47
    /**
48
     * Is the GC currently active
49
     */
50
    private boolean gcActive;
51
52
    /**
53
     * Initialize this instance.
ea37d1f by loic at 2010-01-25 54
     * 
270fa73 by Loïc Rouchon at 2010-01-17 55
     * @param manager
56
     */
ea37d1f by loic at 2010-01-25 57
    public GenGCThread(GenGCManager manager, Monitor heapMonitor) {
270fa73 by Loïc Rouchon at 2010-01-17 58
        super("gc-thread");
59
        this.manager = manager;
60
        this.heapMonitor = heapMonitor;
61
    }
62
63
    /**
2af7864 by Loïc Rouchon at 2010-02-01 64
     * Trigger a major GC run.
ea37d1f by loic at 2010-01-25 65
     * 
66
     * @param waitToFinish
67
     *            If true, block until the run is ready, if false, return
68
     *            immediately.
270fa73 by Loïc Rouchon at 2010-01-17 69
     */
70
    public final void trigger(boolean waitToFinish) {
2af7864 by Loïc Rouchon at 2010-02-01 71
        triggerMajor(waitToFinish);
72
    }
73
74
    /**
75
     * Trigger a major GC run.
76
     * 
77
     * @param waitToFinish
78
     *            If true, block until the run is ready, if false, return
79
     *            immediately.
80
     */
81
    public final void triggerMajor(boolean waitToFinish) {
82
        if (runMajorNeeded && !waitToFinish) {
270fa73 by Loïc Rouchon at 2010-01-17 83
            return;
84
        }
85
        heapMonitor.enter();
86
        try {
2af7864 by Loïc Rouchon at 2010-02-01 87
            runMajorNeeded = true;
270fa73 by Loïc Rouchon at 2010-01-17 88
            heapMonitor.NotifyAll();
89
            if (waitToFinish) {
2af7864 by Loïc Rouchon at 2010-02-01 90
                waitForMajorCollectionEnd();
91
            }
92
        } finally {
93
            heapMonitor.exit();
94
        }
95
    }
96
97
    /**
98
     * Trigger a minor GC run.
99
     * 
100
     * @param waitToFinish
101
     *            If true, block until the run is ready, if false, return
102
     *            immediately.
103
     */
104
    public final void triggerMinor(boolean waitToFinish) {
105
        if (runMinorNeeded && !waitToFinish) {
106
            return;
107
        }
108
        heapMonitor.enter();
109
        try {
110
            runMinorNeeded = true;
111
            heapMonitor.NotifyAll();
112
            if (waitToFinish) {
113
                waitForMinorCollectionEnd();
270fa73 by Loïc Rouchon at 2010-01-17 114
            }
115
        } finally {
116
            heapMonitor.exit();
117
        }
118
    }
119
120
    /**
121
     * Continue to GC.
ea37d1f by loic at 2010-01-25 122
     * 
270fa73 by Loïc Rouchon at 2010-01-17 123
     * @see java.lang.Runnable#run()
124
     */
ef5b586 by Loïc Rouchon at 2010-01-27 125
    @Override
270fa73 by Loïc Rouchon at 2010-01-17 126
    public final void run() {
127
        while (true) {
128
            try {
2af7864 by Loïc Rouchon at 2010-02-01 129
                waitForGcStart();
ea37d1f by loic at 2010-01-25 130
                callGc();
2af7864 by Loïc Rouchon at 2010-02-01 131
                notifyGcEnd();
270fa73 by Loïc Rouchon at 2010-01-17 132
            } catch (Throwable ex) {
133
                try {
134
                    Unsafe.debug(ex.getMessage());
135
                    Unsafe.debug('\n');
136
                    Unsafe.debugStackTrace(ex);
137
                    Unsafe.die("GCThread failed");
138
                } catch (Throwable ex2) {
ea37d1f by loic at 2010-01-25 139
                    continue;
270fa73 by Loïc Rouchon at 2010-01-17 140
                }
141
            }
142
        }
143
    }
ea37d1f by loic at 2010-01-25 144
2af7864 by Loïc Rouchon at 2010-02-01 145
    private void waitForMajorCollectionEnd() {
146
        while (runMajorNeeded || gcActive) {
ea37d1f by loic at 2010-01-25 147
            try {
148
                heapMonitor.Wait(0L);
149
            } catch (InterruptedException ex) {
150
                continue;
151
            }
152
        }
153
    }
154
2af7864 by Loïc Rouchon at 2010-02-01 155
    private void waitForMinorCollectionEnd() {
156
        while (runMinorNeeded || gcActive) {
157
            try {
158
                heapMonitor.Wait(0L);
159
            } catch (InterruptedException ex) {
160
                continue;
161
            }
162
        }
ea37d1f by loic at 2010-01-25 163
    }
164
165
    private final void waitForGcStart() throws InterruptedException {
166
        heapMonitor.enter();
167
        try {
2af7864 by Loïc Rouchon at 2010-02-01 168
            while (!runMajorNeeded) {
ea37d1f by loic at 2010-01-25 169
                heapMonitor.Wait(0L);
170
            }
171
            gcActive = true;
172
        } finally {
173
            heapMonitor.exit();
174
        }
175
    }
176
2af7864 by Loïc Rouchon at 2010-02-01 177
    private final void callGc() throws InterruptedException {
178
        if (runMajorNeeded) {
179
            Unsafe.debug("GenGCThread.callGc(major)\n");
180
            manager.majorGC();
181
            runMinorNeeded = false;
182
        } else {
1b187f6 by Loïc Rouchon at 2010-02-03 183
            Unsafe.debug("GenGCThread.callGc(minor)\n");
2af7864 by Loïc Rouchon at 2010-02-01 184
            manager.minorGC();
185
            runMinorNeeded = false;
186
        }
187
    }
188
ea37d1f by loic at 2010-01-25 189
    private final void notifyGcEnd() {
190
        gcActive = false;
191
        heapMonitor.enter();
192
        try {
193
            heapMonitor.NotifyAll();
194
        } finally {
195
            heapMonitor.exit();
196
        }
197
    }
270fa73 by Loïc Rouchon at 2010-01-17 198
}