23 */ |
23 */ |
24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "gc/g1/suspendibleThreadSet.hpp" |
26 #include "gc/g1/suspendibleThreadSet.hpp" |
27 #include "runtime/mutexLocker.hpp" |
27 #include "runtime/mutexLocker.hpp" |
|
28 #include "runtime/semaphore.hpp" |
28 #include "runtime/thread.inline.hpp" |
29 #include "runtime/thread.inline.hpp" |
29 |
30 |
30 uint SuspendibleThreadSet::_nthreads = 0; |
31 uint SuspendibleThreadSet::_nthreads = 0; |
31 uint SuspendibleThreadSet::_nthreads_stopped = 0; |
32 uint SuspendibleThreadSet::_nthreads_stopped = 0; |
32 bool SuspendibleThreadSet::_suspend_all = false; |
33 bool SuspendibleThreadSet::_suspend_all = false; |
33 double SuspendibleThreadSet::_suspend_all_start = 0.0; |
34 double SuspendibleThreadSet::_suspend_all_start = 0.0; |
|
35 |
|
36 static Semaphore* _synchronize_wakeup = NULL; |
|
37 |
|
38 void SuspendibleThreadSet_init() { |
|
39 assert(_synchronize_wakeup == NULL, "STS already initialized"); |
|
40 _synchronize_wakeup = new Semaphore(); |
|
41 } |
|
42 |
|
43 bool SuspendibleThreadSet::is_synchronized() { |
|
44 assert_lock_strong(STS_lock); |
|
45 assert(_nthreads_stopped <= _nthreads, "invariant"); |
|
46 return _nthreads_stopped == _nthreads; |
|
47 } |
34 |
48 |
35 void SuspendibleThreadSet::join() { |
49 void SuspendibleThreadSet::join() { |
36 assert(!Thread::current()->is_suspendible_thread(), "Thread already joined"); |
50 assert(!Thread::current()->is_suspendible_thread(), "Thread already joined"); |
37 MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); |
51 MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); |
38 while (_suspend_all) { |
52 while (_suspend_all) { |
46 assert(Thread::current()->is_suspendible_thread(), "Thread not joined"); |
60 assert(Thread::current()->is_suspendible_thread(), "Thread not joined"); |
47 MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); |
61 MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); |
48 assert(_nthreads > 0, "Invalid"); |
62 assert(_nthreads > 0, "Invalid"); |
49 DEBUG_ONLY(Thread::current()->clear_suspendible_thread();) |
63 DEBUG_ONLY(Thread::current()->clear_suspendible_thread();) |
50 _nthreads--; |
64 _nthreads--; |
51 if (_suspend_all) { |
65 if (_suspend_all && is_synchronized()) { |
52 ml.notify_all(); |
66 // This leave completes a request, so inform the requestor. |
|
67 _synchronize_wakeup->signal(); |
53 } |
68 } |
54 } |
69 } |
55 |
70 |
56 void SuspendibleThreadSet::yield() { |
71 void SuspendibleThreadSet::yield() { |
57 assert(Thread::current()->is_suspendible_thread(), "Must have joined"); |
72 assert(Thread::current()->is_suspendible_thread(), "Must have joined"); |
|
73 MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); |
58 if (_suspend_all) { |
74 if (_suspend_all) { |
59 MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); |
75 _nthreads_stopped++; |
60 if (_suspend_all) { |
76 if (is_synchronized()) { |
61 _nthreads_stopped++; |
77 if (ConcGCYieldTimeout > 0) { |
62 if (_nthreads_stopped == _nthreads) { |
78 double now = os::elapsedTime(); |
63 if (ConcGCYieldTimeout > 0) { |
79 guarantee((now - _suspend_all_start) * 1000.0 < (double)ConcGCYieldTimeout, "Long delay"); |
64 double now = os::elapsedTime(); |
|
65 guarantee((now - _suspend_all_start) * 1000.0 < (double)ConcGCYieldTimeout, "Long delay"); |
|
66 } |
|
67 } |
80 } |
68 ml.notify_all(); |
81 // This yield completes the request, so inform the requestor. |
69 while (_suspend_all) { |
82 _synchronize_wakeup->signal(); |
70 ml.wait(Mutex::_no_safepoint_check_flag); |
|
71 } |
|
72 assert(_nthreads_stopped > 0, "Invalid"); |
|
73 _nthreads_stopped--; |
|
74 ml.notify_all(); |
|
75 } |
83 } |
|
84 while (_suspend_all) { |
|
85 ml.wait(Mutex::_no_safepoint_check_flag); |
|
86 } |
|
87 assert(_nthreads_stopped > 0, "Invalid"); |
|
88 _nthreads_stopped--; |
76 } |
89 } |
77 } |
90 } |
78 |
91 |
79 void SuspendibleThreadSet::synchronize() { |
92 void SuspendibleThreadSet::synchronize() { |
80 assert(Thread::current()->is_VM_thread(), "Must be the VM thread"); |
93 assert(Thread::current()->is_VM_thread(), "Must be the VM thread"); |
81 if (ConcGCYieldTimeout > 0) { |
94 if (ConcGCYieldTimeout > 0) { |
82 _suspend_all_start = os::elapsedTime(); |
95 _suspend_all_start = os::elapsedTime(); |
83 } |
96 } |
|
97 { |
|
98 MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); |
|
99 assert(!_suspend_all, "Only one at a time"); |
|
100 _suspend_all = true; |
|
101 if (is_synchronized()) { |
|
102 return; |
|
103 } |
|
104 } // Release lock before semaphore wait. |
|
105 |
|
106 // Semaphore initial count is zero. To reach here, there must be at |
|
107 // least one not yielded thread in the set, e.g. is_synchronized() |
|
108 // was false before the lock was released. A thread in the set will |
|
109 // signal the semaphore iff it is the last to yield or leave while |
|
110 // there is an active suspend request. So there will be exactly one |
|
111 // signal, which will increment the semaphore count to one, which |
|
112 // will then be consumed by this wait, returning it to zero. No |
|
113 // thread can exit yield or enter the set until desynchronize is |
|
114 // called, so there are no further opportunities for the semaphore |
|
115 // being signaled until we get back here again for some later |
|
116 // synchronize call. Hence, there is no need to re-check for |
|
117 // is_synchronized after the wait; it will always be true there. |
|
118 _synchronize_wakeup->wait(); |
|
119 |
|
120 #ifdef ASSERT |
84 MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); |
121 MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); |
85 assert(!_suspend_all, "Only one at a time"); |
122 assert(_suspend_all, "STS not synchronizing"); |
86 _suspend_all = true; |
123 assert(is_synchronized(), "STS not synchronized"); |
87 while (_nthreads_stopped < _nthreads) { |
124 #endif |
88 ml.wait(Mutex::_no_safepoint_check_flag); |
|
89 } |
|
90 } |
125 } |
91 |
126 |
92 void SuspendibleThreadSet::desynchronize() { |
127 void SuspendibleThreadSet::desynchronize() { |
93 assert(Thread::current()->is_VM_thread(), "Must be the VM thread"); |
128 assert(Thread::current()->is_VM_thread(), "Must be the VM thread"); |
94 MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); |
129 MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); |
95 assert(_nthreads_stopped == _nthreads, "Invalid"); |
130 assert(_suspend_all, "STS not synchronizing"); |
|
131 assert(is_synchronized(), "STS not synchronized"); |
96 _suspend_all = false; |
132 _suspend_all = false; |
97 ml.notify_all(); |
133 ml.notify_all(); |
98 } |
134 } |