Request for review (s): 7173959 : Jvm crashed during coherence exabus (tmb) testing
Coleen Phillimore
coleen.phillimore at oracle.com
Fri Dec 14 07:49:44 PST 2012
On 12/14/2012 10:24 AM, Bengt Rutisson wrote:
>
> Hi Coleen,
>
> Thanks for looking at this!
>
> On 12/14/12 2:21 PM, Coleen Phillimore wrote:
>> On 12/14/2012 3:48 AM, Bengt Rutisson wrote:
>>>
>>> Hi again Runtime team,
>>>
>>> I need one more review for this change. It is a P1 bug with a fairly
>>> small change. Any takers?
>>>
>>> Latest webrev based on comments from David Holmes and Vitaly
>>> Davidovich:
>>> http://cr.openjdk.java.net/~brutisso/7173959/webrev.03/
>>
>> Hi Bengt, This code looks good to me but I asked Zhengyu to check
>> it to make sure it doesn't have any bad NMT interactions.
>
> Thanks! He just replied.
>>
>> Also the writeup is great below, but can you add these comments to
>> the code in os_posix.cpp. I had to go back to the email to figure
>> out why you are doing this.
>
> I'm not really sure where to put such a comment. I think the writeup I
> did mostly makes sense when you compare it to the old code. Also, the
> affected code is in the middle of ReservedSpace::initialize(). I think
> it would look strange with a large comment there. In the
> os_posix/windows files the comment does not make much sense in my
> opinion.
>
> I could add a comment in ReservedSpace::initialize() that refers to
> the Jira issue. But I'm not a big fan of such comments.
I agree we shouldn't point to bugs in the source code. A comment at
the top of the os_posix version of this function that paraphrases below
why you are not re-reserving in a loop like windows would be
sufficient. That trimming memory at either end is allowed on
posix-like os's and is thread-safe, something like:
// Multiple threads can race in this code, and can remap over each other
with MAP_FIXED, so on posix, unmap the section
// at the start and at the end of the chunk that we mapped to get
requested alignment.
os_windows:
// Multiple threads can race in this code but it's not possible to remap
with a section of virtual space to get requested alignment, like
posix-like os's.
// Windows prevents multiple thread from remapping over each other so
this loop is thread-safe.
I just want something to document why they are different.
>
>>
>> I don't understand why there are racing threads. I thought all the
>> heap space was initialized at the start of the vm when it is single
>> threaded?
>
> I would have to look up exactly when we set up the heap to see if we
> are single threaded at that point. The issue we saw was with setting
> up the GC bitmaps. At that point we are multithreaded and we are for
> example mapping memory for the GC worker threads at the same time.
I see.
Coleen
>
>
> Thanks again for looking at this!
> Bengt
>
>>
>> thanks,
>> Coleen
>>
>>>
>>> Thanks,
>>> Bengt
>>>
>>>
>>> On 12/14/12 9:29 AM, Bengt Rutisson wrote:
>>>>
>>>> Hi David,
>>>>
>>>> On 12/14/12 1:38 AM, David Holmes wrote:
>>>>> Hi Bengt,
>>>>>
>>>>> That all sounds good to me.
>>>>>
>>>>> With regard to potential overflow perhaps a simple check that
>>>>> extra_size does not overflow? If that is true and extra_base is
>>>>> not null then I think all the other calculations must be valid.
>>>>
>>>> Yes, that makes sense. I'll add an overflow check for the extra_size.
>>>>
>>>> Thanks,
>>>> Bengt
>>>>
>>>>>
>>>>> Thanks,
>>>>> David
>>>>>
>>>>> On 13/12/2012 10:58 PM, Bengt Rutisson wrote:
>>>>>>
>>>>>> Hi David,
>>>>>>
>>>>>> Updated webrev:
>>>>>> http://cr.openjdk.java.net/~brutisso/7173959/webrev.02/
>>>>>>
>>>>>> I moved the alignment of "size" back into
>>>>>> ReservedSpace::initialize()
>>>>>> since we actually store the size in an instance variable (_size),
>>>>>> so I
>>>>>> think it is a bit risky to just do the align_up in
>>>>>> os::reserve_memory_aligned(). We probably want the instance
>>>>>> variables
>>>>>> _size and _alignment in ReservedSpace to be consistent.
>>>>>>
>>>>>> I added an assert in os::reserve_memory_aligned() to verify that the
>>>>>> size is correctly aligned. I also added the assert you suggested to
>>>>>> check that alignment is page size aligned.
>>>>>>
>>>>>> Bengt
>>>>>>
>>>>>> On 12/13/12 11:50 AM, David Holmes wrote:
>>>>>>> On 13/12/2012 8:37 PM, Bengt Rutisson wrote:
>>>>>>>>
>>>>>>>> Hi again,
>>>>>>>>
>>>>>>>> Updated webrev:
>>>>>>>> http://cr.openjdk.java.net/~brutisso/7173959/webrev.01/
>>>>>>>>
>>>>>>>> I removed the comment and the alignment.
>>>>>>>>
>>>>>>>> But I did not add an assert just yet.
>>>>>>>>
>>>>>>>> At the top of ReservedSpace::initialize() we have this code:
>>>>>>>>
>>>>>>>> const size_t granularity = os::vm_allocation_granularity();
>>>>>>>> assert((size & (granularity - 1)) == 0,
>>>>>>>> "size not aligned to os::vm_allocation_granularity()");
>>>>>>>> assert((alignment & (granularity - 1)) == 0,
>>>>>>>> "alignment not aligned to os::vm_allocation_granularity()");
>>>>>>>>
>>>>>>>>
>>>>>>>> Where os::vm_allocation_granularity() is implemented as page
>>>>>>>> size on all
>>>>>>>> platforms except Windows. There we look it up from the Windows
>>>>>>>> API. I
>>>>>>>> assume that is a page size too, but since the Windows code in
>>>>>>>> our patch
>>>>>>>> does not unmap based on the alignment it should be safe either
>>>>>>>> way.
>>>>>>>>
>>>>>>>> Is this assert enough or would you like me to add an assert
>>>>>>>> closer to
>>>>>>>> the code block were I did the changes?
>>>>>>>
>>>>>>> As this is a separate method now I think an assert in the method
>>>>>>> itself would not go astray.
>>>>>>>
>>>>>>> David
>>>>>>> -----
>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> Bengt
>>>>>>>>
>>>>>>>>
>>>>>>>> On 12/13/12 11:02 AM, Bengt Rutisson wrote:
>>>>>>>>>
>>>>>>>>> Hi David,
>>>>>>>>>
>>>>>>>>> Thanks for looking at this!
>>>>>>>>>
>>>>>>>>> On 12/13/12 8:33 AM, David Holmes wrote:
>>>>>>>>>> Hi Bengt,
>>>>>>>>>>
>>>>>>>>>> This has to be one of the absolute best review requests I've
>>>>>>>>>> ever
>>>>>>>>>> read :) Thank you.
>>>>>>>>>
>>>>>>>>> Wow! Thanks! :)
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Just a couple of queries.
>>>>>>>>>>
>>>>>>>>>> os_posix.cpp:
>>>>>>>>>>
>>>>>>>>>> Love the diagram :)
>>>>>>>>>
>>>>>>>>> It was Mikael's way of making sure we got it right.
>>>>>>>>>
>>>>>>>>>> I'm assuming that "alignment" has to be >= the underlying
>>>>>>>>>> page size,
>>>>>>>>>> and in fact must be a multiple of the underlying page size ?
>>>>>>>>>> (As I
>>>>>>>>>> assume you can only unmap whole numbers of pages). If so does
>>>>>>>>>> that
>>>>>>>>>> need to be checked somewhere?
>>>>>>>>>
>>>>>>>>> Good point. I'll add an assert to check that.
>>>>>>>>>
>>>>>>>>>> In virtualSpace.cpp:
>>>>>>>>>>
>>>>>>>>>> // Reserve size large enough to do manual alignment and
>>>>>>>>>> // increase size to a multiple of the desired alignment
>>>>>>>>>> size = align_size_up(size, alignment);
>>>>>>>>>> ! base = os::reserve_memory_aligned(size, alignment);
>>>>>>>>>>
>>>>>>>>>> The comment doesn't seem necessary now, and the align_size_up
>>>>>>>>>> seems
>>>>>>>>>> redundant.
>>>>>>>>>
>>>>>>>>> You are right. I'll remove the comment and the alignment.
>>>>>>>>>
>>>>>>>>> Thanks,
>>>>>>>>> Bengt
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Thanks,
>>>>>>>>>> David
>>>>>>>>>>
>>>>>>>>>> On 13/12/2012 4:42 PM, Bengt Rutisson wrote:
>>>>>>>>>>>
>>>>>>>>>>> Hi all,
>>>>>>>>>>>
>>>>>>>>>>> Could I have a couple of reviews for this change?
>>>>>>>>>>>
>>>>>>>>>>> http://cr.openjdk.java.net/~brutisso/7173959/webrev.00/
>>>>>>>>>>>
>>>>>>>>>>> This is for a bug originally reported by the Coherence team:
>>>>>>>>>>>
>>>>>>>>>>> 7173959 : Jvm crashed during coherence exabus (tmb) testing
>>>>>>>>>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7173959
>>>>>>>>>>>
>>>>>>>>>>> The original analysis and proposed fix was done by Mikael
>>>>>>>>>>> Gerdin
>>>>>>>>>>> and me
>>>>>>>>>>> together. I'll handle the webrev and push since Mikael is on
>>>>>>>>>>> vacation
>>>>>>>>>>> starting today. But Mikael did a great job tracking down
>>>>>>>>>>> this very
>>>>>>>>>>> difficult bug, so he should have a large part of the credit
>>>>>>>>>>> for this
>>>>>>>>>>> bug
>>>>>>>>>>> fix,
>>>>>>>>>>>
>>>>>>>>>>> Description from the CR:
>>>>>>>>>>>
>>>>>>>>>>> The reason that we crash is due to how we re-map memory when we
>>>>>>>>>>> want to
>>>>>>>>>>> align it for large pages in ReservedSpace::initialize().
>>>>>>>>>>>
>>>>>>>>>>> Here is what happens:
>>>>>>>>>>>
>>>>>>>>>>> The reservation of memory is split up to a few steps. When
>>>>>>>>>>> we want a
>>>>>>>>>>> chunk of memory with large pages we first just reserve some
>>>>>>>>>>> memory
>>>>>>>>>>> large
>>>>>>>>>>> enough for what we need. Then we realize that we want large
>>>>>>>>>>> pages,
>>>>>>>>>>> so we
>>>>>>>>>>> want to re-map the reserved memory to use large pages. But
>>>>>>>>>>> since this
>>>>>>>>>>> requires that we have a large-page-aligned memory chunk we may
>>>>>>>>>>> have to
>>>>>>>>>>> fix the recently reserved memory chunk up a bit.
>>>>>>>>>>>
>>>>>>>>>>> We do this in ReservedSpace::initialize() by first releasing
>>>>>>>>>>> the
>>>>>>>>>>> memory
>>>>>>>>>>> we just reserved. Then requesting more memory than we actually
>>>>>>>>>>> need to
>>>>>>>>>>> make sure that we have enough space to do manual large page
>>>>>>>>>>> alignment.
>>>>>>>>>>> After we have gotten this memory we figure out a nicely
>>>>>>>>>>> aligned start
>>>>>>>>>>> address. We then release the memory again and then reserve just
>>>>>>>>>>> enough
>>>>>>>>>>> memory but using the aligned start address as a fixed
>>>>>>>>>>> address to make
>>>>>>>>>>> sure that we get the memory we wanted in an aligned way.
>>>>>>>>>>>
>>>>>>>>>>> This is done in a loop to make sure that we eventually get some
>>>>>>>>>>> memory.
>>>>>>>>>>> The interesting code looks like this:
>>>>>>>>>>>
>>>>>>>>>>> do {
>>>>>>>>>>> char* extra_base = os::reserve_memory(extra_size, NULL,
>>>>>>>>>>> alignment);
>>>>>>>>>>> if (extra_base == NULL) return;
>>>>>>>>>>> // Do manual alignement
>>>>>>>>>>> base = (char*) align_size_up((uintptr_t) extra_base,
>>>>>>>>>>> alignment);
>>>>>>>>>>> assert(base >= extra_base, "just checking");
>>>>>>>>>>> // Re-reserve the region at the aligned base address.
>>>>>>>>>>> os::release_memory(extra_base, extra_size); // (1)
>>>>>>>>>>> base = os::reserve_memory(size, base); // (2)
>>>>>>>>>>> } while (base == NULL);
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> There is a race here between releasing the memory in (1) and
>>>>>>>>>>> re-reserving it in (2). But the loop is supposed to handle
>>>>>>>>>>> this race.
>>>>>>>>>>>
>>>>>>>>>>> The problem is that on posix platforms you can remap the
>>>>>>>>>>> same memory
>>>>>>>>>>> area several times. The call in (2) will use mmap with
>>>>>>>>>>> MAP_FIXED.
>>>>>>>>>>> This
>>>>>>>>>>> means that the OS will think that you know exactly what you are
>>>>>>>>>>> doing.
>>>>>>>>>>> So, if part of the memory has been mapped already by the
>>>>>>>>>>> process it
>>>>>>>>>>> will
>>>>>>>>>>> just go ahead and reuse that memory.
>>>>>>>>>>>
>>>>>>>>>>> This means that if we are having multiple threads that do
>>>>>>>>>>> mmap. We
>>>>>>>>>>> can
>>>>>>>>>>> end up with a situation where we release our mapping in (1).
>>>>>>>>>>> Then
>>>>>>>>>>> another thread comes in and maps part of the memory that we
>>>>>>>>>>> used to
>>>>>>>>>>> have. Then we remap over that memory again in (2) with
>>>>>>>>>>> MAP_FIXED.
>>>>>>>>>>> Now we
>>>>>>>>>>> have a situation where two threads in our process have
>>>>>>>>>>> mapped the
>>>>>>>>>>> same
>>>>>>>>>>> memory. If both threads try to use it or if one of the
>>>>>>>>>>> threads unmap
>>>>>>>>>>> part or all of the memory we will crash.
>>>>>>>>>>>
>>>>>>>>>>> On posix it is possible to unmap any part of a mapped chunk.
>>>>>>>>>>> So, our
>>>>>>>>>>> proposed solution to the race described above is to not
>>>>>>>>>>> unmap all
>>>>>>>>>>> memory
>>>>>>>>>>> in (1) but rather just unmap the section at the start and at
>>>>>>>>>>> the
>>>>>>>>>>> end of
>>>>>>>>>>> the chunk that we mapped to get alignment. This also removes
>>>>>>>>>>> the need
>>>>>>>>>>> for the loop.
>>>>>>>>>>>
>>>>>>>>>>> However, on Windows you can only unmap _all_ of the memory
>>>>>>>>>>> that you
>>>>>>>>>>> have
>>>>>>>>>>> mapped. On the other hand Windows also will not allow you to
>>>>>>>>>>> map over
>>>>>>>>>>> other mappings, so the original code is actually safe. If we
>>>>>>>>>>> keep
>>>>>>>>>>> the loop.
>>>>>>>>>>>
>>>>>>>>>>> So, our solution is to treat this differently on Windows and
>>>>>>>>>>> posix
>>>>>>>>>>> platforms.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Thanks,
>>>>>>>>>>> Bengt
>>>>>>>>>
>>>>>>>>
>>>>>>
>>>>
>>>
>>
>
More information about the hotspot-runtime-dev
mailing list