[9] RFR(S): 8075214: SIGSEGV in nmethod sweeping
Tobias Hartmann
tobias.hartmann at oracle.com
Fri Mar 27 09:30:09 UTC 2015
David, thanks again for looking into this.
Best,
Tobias
On 27.03.2015 09:51, David Holmes wrote:
> Correction ...
>
> On 27/03/2015 3:25 PM, David Holmes wrote:
>> Hi Tobias,
>>
>> On 26/03/2015 10:52 PM, Tobias Hartmann wrote:
>>> Hi Vladimir,
>>>
>>> On 25.03.2015 18:10, Vladimir Kozlov wrote:
>>>> This is messy. Tobias, can you investigate if we can have the same
>>>> functionality (sweeping on request) in already running sweeper thread
>>>> without crating new thread for that? It may require additional
>>>> synchronization which should be fine since it is testing - no need to
>>>> worry about performance.
>>>
>>> I agree. I removed creation of a new sweeper thread and added the
>>> method NMethodSweeper::force_sweep() to enforce a sweep by setting
>>> '_force_sweep', notifying the sweeper and waiting for completion.
>>> Synchronization is done by using the CodeCache_lock.
>>>
>>> Here are the new webrevs:
>>> http://cr.openjdk.java.net/~thartmann/8075214/top/webrev.00/
>>> http://cr.openjdk.java.net/~thartmann/8075214/webrev.01/
>>
>> This won't quite work. Suppose the sweeper thread is active in
>> possible_sweep, _should_sweep is true and forced/_force_sweep are false,
>> and sweeping is in progress. Now a force_sweep request comes in: sets
>> _force_sweep to true, performs a notify (which does nothing) and then
>> does a wait(1000). The sweeper thread completes the sweep, sees
>> forced==false and so doesn't do a notify, and itself goes back to
>> waiting until it either times out (after 24 hours!) or is notified again
>> (when codecache fills up enough). The force_sweep caller will keep
>> looping checking _forced_sweep, which is still true, and doing a wait
>> for 1 second until the next actual sweep occurs.
>
> I overlooked the fact that when it wakes up after 1 second it will notify the sweeper thread again. So no problem. Thanks for pointing that out Tobias.
>
> David
>
>> I think you need the sweeper_thread to check _forced_sweep before
>> waiting ie:
>>
>> 251 void NMethodSweeper::sweeper_loop() {
>> 252 bool timeout;
>> 253 while (true) {
>> 254 {
>> 255 ThreadBlockInVM tbivm(JavaThread::current());
>> 256 MutexLockerEx waiter(CodeCache_lock,
>> Mutex::_no_safepoint_check_flag);
>> + if (!_forced_sweep) {
>> 257 const long wait_time = 60*60*24 * 1000;
>> 258 timeout =
>> CodeCache_lock->wait(Mutex::_no_safepoint_check_flag, wait_time);
>> + }
>> 259 }
>> ! 260 if (!timeout || _forced_sweep) {
>> 261 possibly_sweep();
>> 262 }
>> 263 }
>> 264 }
>>
>> That would trigger two back-to-back sweeps. Alternatively, if two
>> back-to-backs sweeps is not ideal then in possibly_sweep you'd need to
>> unconditionally grab the lock and check _forced_sweep and clear it and
>> notify. But you must check _forced_sweep with the lock hold.
>>
>> Also under the current approach concurrent calls to force_sweep wouldn't
>> force a sweep per call, but would simply block until A forced sweep had
>> occurred (or just a sweep depending on what you do above). That's
>> probably what you want but I wanted to flag it just in case.
>>
>> Cheers,
>> David
>>
>>> I executed 1k runs of the failing test.
>>>
>>> Thanks,
>>> Tobias
>>>
>>>> I looked in reviews of original changes for 8064669 and we did not
>>>> ask about that.
>>>>
>>>> Thanks,
>>>> Vladimir
>>>>
>>>> On 3/25/15 6:53 AM, Tobias Hartmann wrote:
>>>>> Hi,
>>>>>
>>>>> please review the following patch.
>>>>>
>>>>> https://bugs.openjdk.java.net/browse/JDK-8075214
>>>>> http://cr.openjdk.java.net/~thartmann/8075214/webrev.00/
>>>>>
>>>>> Problem:
>>>>> The test uses the Whitebox API to enforce sweeping by creating and
>>>>> starting a 'CodeCacheSweeperThread'. During creation of the thread,
>>>>> the interpreter crashes in j.l.ThreadGroup.add(Thread t) [1] while
>>>>> executing a subtype check to validate that 't' is a subtype of
>>>>> j.l.Thread [2]. The problem is that we pass
>>>>> 'JavaThread->threadObj()' to 'ThreadGroup.add' which is invalid due
>>>>> to a GC that moved the object. The GC does not know about the thread
>>>>> because it was not yet added to the threads list and therefore does
>>>>> not update the oop.
>>>>>
>>>>> Solution:
>>>>> Instead of calling 'JavaThread::allocate_threadObj', the
>>>>> initialization is moved to the caller to make sure that setting the
>>>>> thread oop is done together with adding the thread to the threads
>>>>> list. I also fixed the missing oom handling described as one of the
>>>>> problems in JDK-8072377 [3].
>>>>>
>>>>> Testing:
>>>>> - 1k runs of failing testcase
>>>>> - JPRT
>>>>>
>>>>> Thanks,
>>>>> Tobias
>>>>>
>>>>> [1]
>>>>> http://hg.openjdk.java.net/jdk9/hs-comp/jdk/file/tip/src/java.base/share/classes/java/lang/ThreadGroup.java#l896
>>>>>
>>>>> [2] see '__ gen_subtype_check' in 'TemplateTable::aastore'
>>>>> [3] https://bugs.openjdk.java.net/browse/JDK-8072377
>>>>>
More information about the hotspot-compiler-dev
mailing list