Skip to content

Commit 8c5987e

Browse files
fix(z): Address inconsistent mremap return arguments with arm64 (#309)
This PR adds a specific arm64 implementation for the `mremap` function which ignores the second return argument from the syscall. **All other Linux implementations are unchanged.** This PR reworks [an earlier PR](#281) so that the functionality on non-arm64 platforms remains the same. Tested on Linux amd64 and Linux arm64.
1 parent d2cbc2f commit 8c5987e

File tree

3 files changed

+108
-30
lines changed

3 files changed

+108
-30
lines changed

z/mmap_linux.go

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
package z
1818

1919
import (
20-
"fmt"
2120
"os"
22-
"reflect"
2321
"unsafe"
2422

2523
"golang.org/x/sys/unix"
@@ -35,34 +33,6 @@ func mmap(fd *os.File, writable bool, size int64) ([]byte, error) {
3533
return unix.Mmap(int(fd.Fd()), 0, int(size), mtype, unix.MAP_SHARED)
3634
}
3735

38-
// mremap is a Linux-specific system call to remap pages in memory. This can be used in place of munmap + mmap.
39-
func mremap(data []byte, size int) ([]byte, error) {
40-
// taken from <https://github.com/torvalds/linux/blob/f8394f232b1eab649ce2df5c5f15b0e528c92091/include/uapi/linux/mman.h#L8>
41-
const MREMAP_MAYMOVE = 0x1
42-
43-
header := (*reflect.SliceHeader)(unsafe.Pointer(&data))
44-
mmapAddr, mmapSize, errno := unix.Syscall6(
45-
unix.SYS_MREMAP,
46-
header.Data,
47-
uintptr(header.Len),
48-
uintptr(size),
49-
uintptr(MREMAP_MAYMOVE),
50-
0,
51-
0,
52-
)
53-
if errno != 0 {
54-
return nil, errno
55-
}
56-
if mmapSize != uintptr(size) {
57-
return nil, fmt.Errorf("mremap size mismatch: requested: %d got: %d", size, mmapSize)
58-
}
59-
60-
header.Data = mmapAddr
61-
header.Cap = size
62-
header.Len = size
63-
return data, nil
64-
}
65-
6636
// munmap unmaps a previously mapped slice.
6737
//
6838
// unix.Munmap maintains an internal list of mmapped addresses, and only calls munmap

z/mremap_linux.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// +build !arm64
2+
3+
/*
4+
* Copyright 2020 Dgraph Labs, Inc. and Contributors
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package z
20+
21+
import (
22+
"fmt"
23+
"reflect"
24+
"unsafe"
25+
26+
"golang.org/x/sys/unix"
27+
)
28+
29+
// mremap is a Linux-specific system call to remap pages in memory. This can be used in place of munmap + mmap.
30+
func mremap(data []byte, size int) ([]byte, error) {
31+
//nolint:lll
32+
// taken from <https://github.com/torvalds/linux/blob/f8394f232b1eab649ce2df5c5f15b0e528c92091/include/uapi/linux/mman.h#L8>
33+
const MREMAP_MAYMOVE = 0x1
34+
35+
header := (*reflect.SliceHeader)(unsafe.Pointer(&data))
36+
mmapAddr, mmapSize, errno := unix.Syscall6(
37+
unix.SYS_MREMAP,
38+
header.Data,
39+
uintptr(header.Len),
40+
uintptr(size),
41+
uintptr(MREMAP_MAYMOVE),
42+
0,
43+
0,
44+
)
45+
if errno != 0 {
46+
return nil, errno
47+
}
48+
if mmapSize != uintptr(size) {
49+
return nil, fmt.Errorf("mremap size mismatch: requested: %d got: %d", size, mmapSize)
50+
}
51+
52+
header.Data = mmapAddr
53+
header.Cap = size
54+
header.Len = size
55+
return data, nil
56+
}

z/mremap_linux_arm64.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2020 Dgraph Labs, Inc. and Contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package z
18+
19+
import (
20+
"reflect"
21+
"unsafe"
22+
23+
"golang.org/x/sys/unix"
24+
)
25+
26+
// mremap is a Linux-specific system call to remap pages in memory. This can be used in place of munmap + mmap.
27+
func mremap(data []byte, size int) ([]byte, error) {
28+
//nolint:lll
29+
// taken from <https://github.com/torvalds/linux/blob/f8394f232b1eab649ce2df5c5f15b0e528c92091/include/uapi/linux/mman.h#L8>
30+
const MREMAP_MAYMOVE = 0x1
31+
32+
header := (*reflect.SliceHeader)(unsafe.Pointer(&data))
33+
// For ARM64, the second return argument for SYS_MREMAP is inconsistent (prior allocated size) with
34+
// other architectures, which return the size allocated
35+
mmapAddr, _, errno := unix.Syscall6(
36+
unix.SYS_MREMAP,
37+
header.Data,
38+
uintptr(header.Len),
39+
uintptr(size),
40+
uintptr(MREMAP_MAYMOVE),
41+
0,
42+
0,
43+
)
44+
if errno != 0 {
45+
return nil, errno
46+
}
47+
48+
header.Data = mmapAddr
49+
header.Cap = size
50+
header.Len = size
51+
return data, nil
52+
}

0 commit comments

Comments
 (0)