/// <summary> /// Loads this buffer's content into physical memory. /// /// <para> This method makes a best effort to ensure that, when it returns, /// this buffer's content is resident in physical memory. Invoking this /// method may cause some number of page faults and I/O operations to /// occur. </para> /// </summary> /// <returns> This buffer </returns> public MappedByteBuffer Load() { CheckMapped(); if ((Address == 0) || (Capacity() == 0)) { return(this); } long offset = MappingOffset(); long length = MappingLength(offset); load0(MappingAddress(offset), length); // Read a byte from each page to bring it into memory. A checksum // is computed as we go along to prevent the compiler from otherwise // considering the loop as dead code. Unsafe @unsafe = Unsafe.Unsafe; int ps = Bits.PageSize(); int count = Bits.PageCount(length); long a = MappingAddress(offset); sbyte x = 0; for (int i = 0; i < count; i++) { x ^= @unsafe.getByte(a); a += ps; } if (Unused != 0) { Unused = x; } return(this); }
// Primary constructor // internal DirectByteBuffer(int cap) : base(-1, 0, cap, cap) // package-private { bool pa = VM.DirectMemoryPageAligned; int ps = Bits.PageSize(); long size = System.Math.Max(1L, (long)cap + (pa ? ps : 0)); Bits.ReserveMemory(size, cap); long @base = 0; try { @base = @unsafe.allocateMemory(size); } catch (OutOfMemoryError x) { Bits.UnreserveMemory(size, cap); throw x; } @unsafe.setMemory(@base, size, (sbyte)0); if (pa && (@base % ps != 0)) { // Round up to page boundary Address = @base + ps - (@base & (ps - 1)); } else { Address = @base; } Cleaner_Renamed = Cleaner.create(this, new Deallocator(@base, size, cap)); Att = null; }
// Returns the distance (in bytes) of the buffer from the page aligned address // of the mapping. Computed each time to avoid storing in every direct buffer. private long MappingOffset() { int ps = Bits.PageSize(); long offset = Address % ps; return((offset >= 0) ? offset : (ps + offset)); }