mirror of
https://github.com/golang/go
synced 2024-11-18 19:14:40 -07:00
[dev.link] cmd/link: fallocate space, and remove all msync calls
The fallocate calls will lower the chances of SIGBUS in the linker, but it might still happen on other unsupported platforms and filesystems. Darwin cmd/compile stats: Munmap 16.0ms ± 8% 0.8ms ± 3% -95.19% (p=0.000 n=8+10) TotalTime 484ms ± 2% 462ms ± 2% -4.52% (p=0.000 n=10+9) Updates #37310 Change-Id: I41c6e490adec26fa1ebee49a5b268828f5ba05e1 Reviewed-on: https://go-review.googlesource.com/c/go/+/228385 Run-TryBot: Jeremy Faller <jeremy@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
7d4c455a80
commit
8ab37b1baf
@ -13,6 +13,13 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// If fallocate is not supported on this platform, return this error.
|
||||
// Note this is the same error returned by filesystems that don't support
|
||||
// fallocate, and that is intentional. The error is ignored where needed, and
|
||||
// OutBuf writes to heap memory.
|
||||
const fallocateNotSupportedErr = "operation not supported"
|
||||
const outbufMode = 0775
|
||||
|
||||
// OutBuf is a buffered file writer.
|
||||
//
|
||||
// It is simlar to the Writer in cmd/internal/bio with a few small differences.
|
||||
@ -70,7 +77,7 @@ func (out *OutBuf) Open(name string) error {
|
||||
if out.f != nil {
|
||||
return errors.New("cannot open more than one file")
|
||||
}
|
||||
f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775)
|
||||
f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, outbufMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
26
src/cmd/link/internal/ld/outbuf_darwin.go
Normal file
26
src/cmd/link/internal/ld/outbuf_darwin.go
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ld
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func (out *OutBuf) fallocate(size uint64) error {
|
||||
store := &syscall.Fstore_t{
|
||||
Flags: syscall.F_ALLOCATEALL,
|
||||
Posmode: syscall.F_PEOFPOSMODE,
|
||||
Offset: 0,
|
||||
Length: int64(size),
|
||||
}
|
||||
|
||||
_, _, err := syscall.Syscall(syscall.SYS_FCNTL, uintptr(out.f.Fd()), syscall.F_PREALLOCATE, uintptr(unsafe.Pointer(store)))
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
11
src/cmd/link/internal/ld/outbuf_linux.go
Normal file
11
src/cmd/link/internal/ld/outbuf_linux.go
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ld
|
||||
|
||||
import "syscall"
|
||||
|
||||
func (out *OutBuf) fallocate(size uint64) error {
|
||||
return syscall.Fallocate(int(out.f.Fd()), outbufMode, 0, int64(size))
|
||||
}
|
@ -8,11 +8,19 @@ package ld
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func (out *OutBuf) Mmap(filesize uint64) error {
|
||||
err := out.f.Truncate(int64(filesize))
|
||||
err := out.fallocate(filesize)
|
||||
if err != nil {
|
||||
// Some file systems do not support fallocate. We ignore that error as linking
|
||||
// can still take place, but you might SIGBUS when you write to the mmapped
|
||||
// area.
|
||||
if err.Error() != fallocateNotSupportedErr {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = out.f.Truncate(int64(filesize))
|
||||
if err != nil {
|
||||
Exitf("resize output file failed: %v", err)
|
||||
}
|
||||
@ -24,27 +32,10 @@ func (out *OutBuf) munmap() {
|
||||
if out.buf == nil {
|
||||
return
|
||||
}
|
||||
err := out.Msync()
|
||||
if err != nil {
|
||||
Exitf("msync output file failed: %v", err)
|
||||
}
|
||||
syscall.Munmap(out.buf)
|
||||
out.buf = nil
|
||||
_, err = out.f.Seek(out.off, 0)
|
||||
_, err := out.f.Seek(out.off, 0)
|
||||
if err != nil {
|
||||
Exitf("seek output file failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (out *OutBuf) Msync() error {
|
||||
if out.buf == nil {
|
||||
return nil
|
||||
}
|
||||
// TODO: netbsd supports mmap and msync, but the syscall package doesn't define MSYNC.
|
||||
// It is excluded from the build tag for now.
|
||||
_, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(&out.buf[0])), uintptr(len(out.buf)), syscall.MS_SYNC)
|
||||
if errno != 0 {
|
||||
return errno
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
13
src/cmd/link/internal/ld/outbuf_nofallocate.go
Normal file
13
src/cmd/link/internal/ld/outbuf_nofallocate.go
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !darwin,!linux
|
||||
|
||||
package ld
|
||||
|
||||
import "errors"
|
||||
|
||||
func (out *OutBuf) fallocate(size uint64) error {
|
||||
return errors.New(fallocateNotSupportedErr)
|
||||
}
|
@ -13,4 +13,3 @@ func (out *OutBuf) Mmap(filesize uint64) error {
|
||||
}
|
||||
|
||||
func (out *OutBuf) munmap() { panic("unreachable") }
|
||||
func (out *OutBuf) Msync() error { panic("unreachable") }
|
||||
|
@ -33,6 +33,9 @@ func TestMMap(t *testing.T) {
|
||||
if err := ob.Mmap(1 << 20); err != nil {
|
||||
t.Errorf("error mmapping file %v", err)
|
||||
}
|
||||
if !ob.isMmapped() {
|
||||
t.Errorf("should be mmapped")
|
||||
}
|
||||
}
|
||||
|
||||
// TestWriteLoc ensures that the math surrounding writeLoc is correct.
|
||||
|
@ -41,10 +41,3 @@ func (out *OutBuf) munmap() {
|
||||
Exitf("UnmapViewOfFile failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (out *OutBuf) Msync() error {
|
||||
if out.buf == nil {
|
||||
return nil
|
||||
}
|
||||
return syscall.FlushViewOfFile(uintptr(unsafe.Pointer(&out.buf[0])), 0)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user