if !writeBarrier.needed {
return
}
- if src != 0 && src < sys.PhysPageSize {
+ if src != 0 && src < minPhysPageSize {
systemstack(func() {
print("runtime: writebarrierptr *", dst, " = ", hex(src), "\n")
throw("bad pointer in write barrier")
if !writeBarrier.needed {
return
}
- if src != 0 && src < sys.PhysPageSize {
+ if src != 0 && src < minPhysPageSize {
systemstack(func() { throw("bad pointer in write barrier") })
}
writebarrierptr_nostore1(dst, src)
)
const (
- _PAGE_SIZE = sys.PhysPageSize
- _EACCES = 13
+ _EACCES = 13
+ _EINVAL = 22
)
// NOTE: vec must be just 1 byte long here.
var addrspace_vec [1]byte
func addrspace_free(v unsafe.Pointer, n uintptr) bool {
- var chunk uintptr
- for off := uintptr(0); off < n; off += chunk {
- chunk = _PAGE_SIZE * uintptr(len(addrspace_vec))
- if chunk > (n - off) {
- chunk = n - off
+ // Step by the minimum possible physical page size. This is
+ // safe even if we have the wrong physical page size; mincore
+ // will just return EINVAL for unaligned addresses.
+ for off := uintptr(0); off < n; off += minPhysPageSize {
+ // Use a length of 1 byte, which the kernel will round
+ // up to one physical page regardless of the true
+ // physical page size.
+ errval := mincore(unsafe.Pointer(uintptr(v)+off), 1, &addrspace_vec[0])
+ if errval == -_EINVAL {
+ // Address is not a multiple of the physical
+ // page size. That's fine.
+ continue
}
- errval := mincore(unsafe.Pointer(uintptr(v)+off), chunk, &addrspace_vec[0])
// ENOMEM means unmapped, which is what we want.
// Anything else we assume means the pages are mapped.
if errval != -_ENOMEM {
"unsafe"
)
+// minPhysPageSize is a lower-bound on the physical page size. The
+// true physical page size may be larger than this. In contrast,
+// sys.PhysPageSize is an upper-bound on the physical page size.
+const minPhysPageSize = 4096
+
// Main malloc heap.
// The heap itself is the "free[]" and "large" arrays,
// but all the other global data is here too.