121 extern outputStream* tty; // tty output |
121 extern outputStream* tty; // tty output |
122 extern outputStream* gclog_or_tty; // stream for gc log if -Xloggc:<f>, or tty |
122 extern outputStream* gclog_or_tty; // stream for gc log if -Xloggc:<f>, or tty |
123 |
123 |
124 // advisory locking for the shared tty stream: |
124 // advisory locking for the shared tty stream: |
125 class ttyLocker: StackObj { |
125 class ttyLocker: StackObj { |
|
126 friend class ttyUnlocker; |
126 private: |
127 private: |
127 intx _holder; |
128 intx _holder; |
128 |
129 |
129 public: |
130 public: |
130 static intx hold_tty(); // returns a "holder" token |
131 static intx hold_tty(); // returns a "holder" token |
131 static void release_tty(intx holder); // must witness same token |
132 static void release_tty(intx holder); // must witness same token |
|
133 static bool release_tty_if_locked(); // returns true if lock was released |
132 static void break_tty_lock_for_safepoint(intx holder); |
134 static void break_tty_lock_for_safepoint(intx holder); |
133 |
135 |
134 ttyLocker() { _holder = hold_tty(); } |
136 ttyLocker() { _holder = hold_tty(); } |
135 ~ttyLocker() { release_tty(_holder); } |
137 ~ttyLocker() { release_tty(_holder); } |
|
138 }; |
|
139 |
|
140 // Release the tty lock if it's held and reacquire it if it was |
|
141 // locked. Used to avoid lock ordering problems. |
|
142 class ttyUnlocker: StackObj { |
|
143 private: |
|
144 bool _was_locked; |
|
145 public: |
|
146 ttyUnlocker() { |
|
147 _was_locked = ttyLocker::release_tty_if_locked(); |
|
148 } |
|
149 ~ttyUnlocker() { |
|
150 if (_was_locked) { |
|
151 ttyLocker::hold_tty(); |
|
152 } |
|
153 } |
136 }; |
154 }; |
137 |
155 |
138 // for writing to strings; buffer will expand automatically |
156 // for writing to strings; buffer will expand automatically |
139 class stringStream : public outputStream { |
157 class stringStream : public outputStream { |
140 protected: |
158 protected: |