Skip to content

Commit e0c3b6e

Browse files
anton-kuklingopherbot
authored andcommitted
unix: add Mremap for linux
For golang/go#60409 Change-Id: I75a9732ee996f0aeb91599d80803f96ada468c27 GitHub-Last-Rev: c348b61 GitHub-Pull-Request: #164 Reviewed-on: https://go-review.googlesource.com/c/sys/+/502715 Auto-Submit: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Bryan Mills <bcmills@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com>
1 parent ca096e4 commit e0c3b6e

File tree

6 files changed

+114
-6
lines changed

6 files changed

+114
-6
lines changed

unix/mkerrors.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ ccflags="$@"
519519
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
520520
$2 ~ /^LO_(KEY|NAME)_SIZE$/ ||
521521
$2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ ||
522-
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ ||
522+
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MREMAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ ||
523523
$2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ ||
524524
$2 ~ /^NFC_.*_(MAX)?SIZE$/ ||
525525
$2 ~ /^RAW_PAYLOAD_/ ||

unix/mremap.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build linux
6+
// +build linux
7+
8+
package unix
9+
10+
import "unsafe"
11+
12+
type mremapMmapper struct {
13+
mmapper
14+
mremap func(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error)
15+
}
16+
17+
func (m *mremapMmapper) Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) {
18+
if newLength <= 0 || len(oldData) == 0 || len(oldData) != cap(oldData) || flags&MREMAP_FIXED != 0 {
19+
return nil, EINVAL
20+
}
21+
22+
pOld := &oldData[cap(oldData)-1]
23+
m.Lock()
24+
defer m.Unlock()
25+
bOld := m.active[pOld]
26+
if bOld == nil || &bOld[0] != &oldData[0] {
27+
return nil, EINVAL
28+
}
29+
newAddr, errno := m.mremap(uintptr(unsafe.Pointer(&bOld[0])), uintptr(len(bOld)), uintptr(newLength), flags, 0)
30+
if errno != nil {
31+
return nil, errno
32+
}
33+
bNew := unsafe.Slice((*byte)(unsafe.Pointer(newAddr)), newLength)
34+
pNew := &bNew[cap(bNew)-1]
35+
if flags&MREMAP_DONTUNMAP == 0 {
36+
delete(m.active, pOld)
37+
}
38+
m.active[pNew] = bNew
39+
return bNew, nil
40+
}

unix/mremap_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build linux
6+
// +build linux
7+
8+
package unix_test
9+
10+
import (
11+
"testing"
12+
13+
"golang.org/x/sys/unix"
14+
)
15+
16+
func TestMremap(t *testing.T) {
17+
b, err := unix.Mmap(-1, 0, unix.Getpagesize(), unix.PROT_NONE, unix.MAP_ANON|unix.MAP_PRIVATE)
18+
if err != nil {
19+
t.Fatalf("Mmap: %v", err)
20+
}
21+
if err := unix.Mprotect(b, unix.PROT_READ|unix.PROT_WRITE); err != nil {
22+
t.Fatalf("Mprotect: %v", err)
23+
}
24+
25+
b[0] = 42
26+
27+
bNew, err := unix.Mremap(b, unix.Getpagesize()*2, unix.MREMAP_MAYMOVE)
28+
if err != nil {
29+
t.Fatalf("Mremap2: %v", err)
30+
}
31+
bNew[unix.Getpagesize()+1] = 84 // checks
32+
33+
if bNew[0] != 42 {
34+
t.Fatal("first element value was changed")
35+
}
36+
if len(bNew) != unix.Getpagesize()*2 {
37+
t.Fatal("new memory len not equal to specified len")
38+
}
39+
if cap(bNew) != unix.Getpagesize()*2 {
40+
t.Fatal("new memory cap not equal to specified len")
41+
}
42+
43+
_, err = unix.Mremap(b, unix.Getpagesize(), unix.MREMAP_FIXED)
44+
if err != unix.EINVAL {
45+
t.Fatalf("unix.MREMAP_FIXED should be forbidden")
46+
}
47+
}

unix/syscall_linux.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,11 +2124,15 @@ func writevRacedetect(iovecs []Iovec, n int) {
21242124

21252125
// mmap varies by architecture; see syscall_linux_*.go.
21262126
//sys munmap(addr uintptr, length uintptr) (err error)
2127+
//sys mremap(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error)
21272128

2128-
var mapper = &mmapper{
2129-
active: make(map[*byte][]byte),
2130-
mmap: mmap,
2131-
munmap: munmap,
2129+
var mapper = &mremapMmapper{
2130+
mmapper: mmapper{
2131+
active: make(map[*byte][]byte),
2132+
mmap: mmap,
2133+
munmap: munmap,
2134+
},
2135+
mremap: mremap,
21322136
}
21332137

21342138
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
@@ -2139,6 +2143,10 @@ func Munmap(b []byte) (err error) {
21392143
return mapper.Munmap(b)
21402144
}
21412145

2146+
func Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) {
2147+
return mapper.Mremap(oldData, newLength, flags)
2148+
}
2149+
21422150
//sys Madvise(b []byte, advice int) (err error)
21432151
//sys Mprotect(b []byte, prot int) (err error)
21442152
//sys Mlock(b []byte) (err error)
@@ -2487,7 +2495,6 @@ func Getresgid() (rgid, egid, sgid int) {
24872495
// MqTimedreceive
24882496
// MqTimedsend
24892497
// MqUnlink
2490-
// Mremap
24912498
// Msgctl
24922499
// Msgget
24932500
// Msgrcv

unix/zerrors_linux.go

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

unix/zsyscall_linux.go

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)