35 |
35 |
36 // CopyrightVersion 1.2 |
36 // CopyrightVersion 1.2 |
37 |
37 |
38 int ConcurrentGCThread::_CGC_flag = CGC_nil; |
38 int ConcurrentGCThread::_CGC_flag = CGC_nil; |
39 |
39 |
40 SuspendibleThreadSet ConcurrentGCThread::_sts; |
|
41 |
|
42 ConcurrentGCThread::ConcurrentGCThread() : |
40 ConcurrentGCThread::ConcurrentGCThread() : |
43 _should_terminate(false), _has_terminated(false) { |
41 _should_terminate(false), _has_terminated(false) { |
44 _sts.initialize(); |
|
45 }; |
42 }; |
46 |
|
47 void ConcurrentGCThread::safepoint_synchronize() { |
|
48 _sts.suspend_all(); |
|
49 } |
|
50 |
|
51 void ConcurrentGCThread::safepoint_desynchronize() { |
|
52 _sts.resume_all(); |
|
53 } |
|
54 |
43 |
55 void ConcurrentGCThread::create_and_start() { |
44 void ConcurrentGCThread::create_and_start() { |
56 if (os::create_thread(this, os::cgc_thread)) { |
45 if (os::create_thread(this, os::cgc_thread)) { |
57 // XXX: need to set this to low priority |
46 // XXX: need to set this to low priority |
58 // unless "aggressive mode" set; priority |
47 // unless "aggressive mode" set; priority |
88 Terminator_lock->notify(); |
77 Terminator_lock->notify(); |
89 } |
78 } |
90 |
79 |
91 // Thread destructor usually does this.. |
80 // Thread destructor usually does this.. |
92 ThreadLocalStorage::set_thread(NULL); |
81 ThreadLocalStorage::set_thread(NULL); |
93 } |
|
94 |
|
95 |
|
96 void SuspendibleThreadSet::initialize_work() { |
|
97 MutexLocker x(STS_init_lock); |
|
98 if (!_initialized) { |
|
99 _m = new Monitor(Mutex::leaf, |
|
100 "SuspendibleThreadSetLock", true); |
|
101 _async = 0; |
|
102 _async_stop = false; |
|
103 _async_stopped = 0; |
|
104 _initialized = true; |
|
105 } |
|
106 } |
|
107 |
|
108 void SuspendibleThreadSet::join() { |
|
109 initialize(); |
|
110 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); |
|
111 while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag); |
|
112 _async++; |
|
113 assert(_async > 0, "Huh."); |
|
114 } |
|
115 |
|
116 void SuspendibleThreadSet::leave() { |
|
117 assert(_initialized, "Must be initialized."); |
|
118 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); |
|
119 _async--; |
|
120 assert(_async >= 0, "Huh."); |
|
121 if (_async_stop) _m->notify_all(); |
|
122 } |
|
123 |
|
124 void SuspendibleThreadSet::yield(const char* id) { |
|
125 assert(_initialized, "Must be initialized."); |
|
126 if (_async_stop) { |
|
127 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); |
|
128 if (_async_stop) { |
|
129 _async_stopped++; |
|
130 assert(_async_stopped > 0, "Huh."); |
|
131 if (_async_stopped == _async) { |
|
132 if (ConcGCYieldTimeout > 0) { |
|
133 double now = os::elapsedTime(); |
|
134 guarantee((now - _suspend_all_start) * 1000.0 < |
|
135 (double)ConcGCYieldTimeout, |
|
136 "Long delay; whodunit?"); |
|
137 } |
|
138 } |
|
139 _m->notify_all(); |
|
140 while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag); |
|
141 _async_stopped--; |
|
142 assert(_async >= 0, "Huh"); |
|
143 _m->notify_all(); |
|
144 } |
|
145 } |
|
146 } |
|
147 |
|
148 void SuspendibleThreadSet::suspend_all() { |
|
149 initialize(); // If necessary. |
|
150 if (ConcGCYieldTimeout > 0) { |
|
151 _suspend_all_start = os::elapsedTime(); |
|
152 } |
|
153 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); |
|
154 assert(!_async_stop, "Only one at a time."); |
|
155 _async_stop = true; |
|
156 while (_async_stopped < _async) _m->wait(Mutex::_no_safepoint_check_flag); |
|
157 } |
|
158 |
|
159 void SuspendibleThreadSet::resume_all() { |
|
160 assert(_initialized, "Must be initialized."); |
|
161 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); |
|
162 assert(_async_stopped == _async, "Huh."); |
|
163 _async_stop = false; |
|
164 _m->notify_all(); |
|
165 } |
82 } |
166 |
83 |
167 static void _sltLoop(JavaThread* thread, TRAPS) { |
84 static void _sltLoop(JavaThread* thread, TRAPS) { |
168 SurrogateLockerThread* slt = (SurrogateLockerThread*)thread; |
85 SurrogateLockerThread* slt = (SurrogateLockerThread*)thread; |
169 slt->loop(); |
86 slt->loop(); |
281 _monitor.notify(); |
198 _monitor.notify(); |
282 } |
199 } |
283 } |
200 } |
284 assert(!_monitor.owned_by_self(), "Should unlock before exit."); |
201 assert(!_monitor.owned_by_self(), "Should unlock before exit."); |
285 } |
202 } |
286 |
|
287 |
|
288 // ===== STS Access From Outside CGCT ===== |
|
289 |
|
290 void ConcurrentGCThread::stsYield(const char* id) { |
|
291 assert( Thread::current()->is_ConcurrentGC_thread(), |
|
292 "only a conc GC thread can call this" ); |
|
293 _sts.yield(id); |
|
294 } |
|
295 |
|
296 bool ConcurrentGCThread::stsShouldYield() { |
|
297 assert( Thread::current()->is_ConcurrentGC_thread(), |
|
298 "only a conc GC thread can call this" ); |
|
299 return _sts.should_yield(); |
|
300 } |
|
301 |
|
302 void ConcurrentGCThread::stsJoin() { |
|
303 assert( Thread::current()->is_ConcurrentGC_thread(), |
|
304 "only a conc GC thread can call this" ); |
|
305 _sts.join(); |
|
306 } |
|
307 |
|
308 void ConcurrentGCThread::stsLeave() { |
|
309 assert( Thread::current()->is_ConcurrentGC_thread(), |
|
310 "only a conc GC thread can call this" ); |
|
311 _sts.leave(); |
|
312 } |
|