Also, here is a new webrev including the updated implementations for
mappingAddress/Offset/Length as described below

JIRA:   https://bugs.openjdk.java.net/browse/JDK-8221696
webrev: http://cr.openjdk.java.net/~adinn/8221696/webrev.02

regards,

Andrew Dinn
-----------

On 23/04/2019 17:15, Andrew Dinn wrote:
> Hi Alan,
> 
> Thanks for looking at this.
> 
> On 22/04/2019 16:52, Alan Bateman wrote:
>> The calculation to compute the page aligned address and then the
>> distance from there to the end of the region is tricky to get right. I
>> think you have it right, I'm just wondering if we could leverage the
>> existing mappingOffset/mappingAddress methods so that we have only one
>> place to audit. For example, suppose mappingOffset is changed to take an
>> index. I think this would reduce the new force method down to:
>>
>> long offset = mappingOffset(index);
>> force0(fd, mappingAddress(offset), offset + length);
> 
> I like this idea but I'd like to make sure I am clear about exactly how
> it ought to work. If you will indulge me I will work through this by
> describing first the status quo (as I perceive it) and then what my
> change attempts before trying to reconcile the two.
> 
> Currently:
> 
> There are 4 key locations of interest in the mapped byte range
> 
> [... map_base ... address ... address+limit ... address+capacity ...]
>      |                     |
>      +----- page size -----+
> 
> where:
>   - addresses to the left are numerically (i.e. as longs) lower than
>     those to the right
>   - map_base is aligned to page size -- it is obtained by rounding down
>     address to a page boundary
>   - consequently (address - map_base) is less than page size
> 
> n.b. the mmapped region may or may not commence at map_base but it will
> always include map_base. Also, it will include bytes at all subsequent
> addresses up to (address + capacity). Whether it includes or extends
> beyond (address + capacity) is not really important.
> 
> mappingOffset() computes (address - map_base):
> 
>   int ps = Bits.pageSize();
>   long offset = address % ps;
>   return (offset >= 0) ? offset : (ps + offset);
> 
> The jiggery-pokery with ? : works round the rather unhelpful behaviour
> of mod wrt negative longs.
> 
> I think it could, equivalently, compute it directly as:
> 
>   int ps = Bits.pageSize();
>   long map_base = (address & ~(ps - 1));
>   return address - map_base;
> 
> mappingAddress(mappingOffset) converts a previously retrieved
> mappingOffset back to the map base:
> 
>    return (address - mappingOffset)
>      == (address - (address - map_base))
>      == map_base
> 
> 
> mappingLength(mappingOffset) computes ((address + capacity) - map_base)
> i.e. the byte count from start of page map_base to the last
> (potentially) /writeable/ buffer byte.
> 
>   return capacity() + mappingOffset
>     == capacity + (address - map_base)
>     == (address + capacity) - map_base
> 
> arguably this method could just compute ((address + length) - map_base)
> i.e. the byte count from map_base to the last /written/ byte -- but that
> makes no real difference when performing a file-based flush.
> 
> The call to force0 is made as
> 
>   force0(fd, mappingAddress(offset), mappingLength(offset))
> 
> which is equivalent to
> 
>   force0(fd, map_base, capacity + (address - map_base))
> 
> 
> My updated code:
> 
> When looking at an indexed location there are now 7 key locations of
> interest in the mapped byte range
> 
> [... m_base ... a ... i_base ... a+i ... a+i+ln ... a+lim, a+cap ...]
>      |             |  |             |
>      +- page size -+  +- page size -+
> 
> 
> where:
>   - for brevity, map_base is abbreviated to m_base, address to a,
>     index_base to i_base, index to i, length to ln, limit to lim
>     and capacity to cap
>   - index is identifies the start of the region to be flushed
>   - length is the length of the region to be flushed
>   - (address + index) is the address of the byte at offset index
>   - index_base is the largest page aligned address below (address + idx)
>     i.e. it is obtained by rounding down the first byte of the flush
>     region to a page boundary
> 
> index_base is computed as follows
> 
>   int ps = Bits.pageSize();
>   long index_base = ((address + index) & ~(ps - 1));
> 
> My code is calling
> 
>   force0(fd, index_base, length + ((address + index) - i_base))
> 
> i.e. it the flushed range starts at the nearest page boundary below or
> equal to (address + index) and includes the original length bytes plus
> the intervening bytes between that page boundary and address.
> 
> When this is considered by analogy with the previous call then three
> things stand out:
> 
>   1) in place of map_base for the first argument we have index_base
>   2) in place of the extra included intervening bytes between map_base
>      and address we have the extra included intervening bytes between
>      index_base and address + index
>   3) in place of capacity (default) demarcated bytes to be flushed we
>      have length user demarcated bytes to be flushed
> 
> So, to retain those parallels detailed in 1, 2 and 3 we need
> mappingOffset and mappingAddress to be overloaded and the originals
> rerouted as follows
> 
> mappingOffset(index)
> {
>   int ps = Bits.pageSize();
>   long index_address = address + index;
>   long index_base = (index_address & ~(ps - 1));
>   return index_address - index_base;
> }
> 
> mappingOffset() => mappingOffset(0)
> 
> mappingAddress(mappingOffset, index)
> {
>   long index_address = address + index;
>   return index_address - mappingOffset
>     == (index_address - (index_address - index_base))
>     == index_base
> }
> 
> mappingAddress(mappingOffset) => mappingAddress(mappingOffset, 0)
> 
> mappingLength(mappingOffset, length)
> {
>   return length + mappingOffset
> }
> 
> mappingLength(mappingOffset) =>
>           mappingLength(mappingOffset, (long)capacity())
> 
> Does that look correct? If so I will prepare a new webrev accordingly.
> 
>> I don't expect any issues on Windows but I will test it to make sure.
> Thank you. That would be very helpful.
> 
> regards,
> 
> 
> Andrew Dinn
> -----------
> Senior Principal Software Engineer
> Red Hat UK Ltd
> Registered in England and Wales under Company Registration No. 03798903
> Directors: Michael Cunningham, Michael ("Mike") O'Neill, Eric Shander
> 

Reply via email to