mmap_unix.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. // Copyright 2011 Evan Shaw. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE-MMAP-GO file.
  4. //go:build darwin || dragonfly || freebsd || linux || openbsd || (solaris && !illumos) || netbsd
  5. // +build darwin dragonfly freebsd linux openbsd solaris,!illumos netbsd
  6. // Modifications (c) 2017 The Memory Authors.
  7. package memory // import "modernc.org/memory"
  8. import (
  9. "os"
  10. "syscall"
  11. )
  12. const pageSizeLog = 20
  13. var (
  14. osPageMask = osPageSize - 1
  15. osPageSize = os.Getpagesize()
  16. )
  17. func unmap(addr uintptr, size int) error {
  18. _, _, errno := syscall.Syscall(syscall.SYS_MUNMAP, addr, uintptr(size), 0)
  19. if errno != 0 {
  20. return errno
  21. }
  22. return nil
  23. }
  24. // pageSize aligned.
  25. func mmap(size int) (uintptr, int, error) {
  26. size = roundup(size, osPageSize)
  27. // The actual mmap syscall varies by architecture. mmapSyscall provides same
  28. // functionality as the unexported funtion syscall.mmap and is declared in
  29. // mmap_*_*.go and mmap_fallback.go. To add support for a new architecture,
  30. // check function mmap in src/syscall/syscall_*_*.go or
  31. // src/syscall/zsyscall_*_*.go in Go's source code.
  32. p, err := mmapSyscall(0, uintptr(size+pageSize), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_PRIVATE|syscall.MAP_ANON, -1, 0)
  33. if err != nil {
  34. return 0, 0, err
  35. }
  36. n := size + pageSize
  37. if p&uintptr(osPageMask) != 0 {
  38. panic("internal error")
  39. }
  40. mod := int(p) & pageMask
  41. if mod != 0 {
  42. m := pageSize - mod
  43. if err := unmap(p, m); err != nil {
  44. return 0, 0, err
  45. }
  46. n -= m
  47. p += uintptr(m)
  48. }
  49. if p&uintptr(pageMask) != 0 {
  50. panic("internal error")
  51. }
  52. if n-size != 0 {
  53. if err := unmap(p+uintptr(size), n-size); err != nil {
  54. return 0, 0, err
  55. }
  56. }
  57. return p, size, nil
  58. }