Skip to content
Newer
Older
100644 117 lines (103 sloc) 3.71 KB
b84771a @edsrzf Initial commit
authored
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 file.
4
5 // This file defines the common package interface and contains a little bit of
6 // factored out logic.
7
8 // Package mmap allows mapping files into memory. It tries to provide a simple, reasonably portable interface,
9 // but doesn't go out of its way to abstract away every little platform detail.
10 // This specifically means:
11 // * forked processes may or may not inherit mappings
12 // * a file's timestamp may or may not be updated by writes through mappings
13 // * specifying a size larger than the file's actual size can increase the file's size
14 // * If the mapped file is being modified by another process while your program's running, don't expect consistent results between platforms
15 package mmap
16
17 import (
b9e6220 @edsrzf Convert to Go 1
authored
18 "errors"
b84771a @edsrzf Initial commit
authored
19 "os"
20 "reflect"
21 "unsafe"
22 )
23
24 const (
25 // RDONLY maps the memory read-only.
26 // Attempts to write to the MMap object will result in undefined behavior.
27 RDONLY = 0
28 // RDWR maps the memory as read-write. Writes to the MMap object will update the
29 // underlying file.
30 RDWR = 1 << iota
31 // COPY maps the memory as copy-on-write. Writes to the MMap object will affect
32 // memory, but the underlying file will remain unchanged.
33 COPY
34 // If EXEC is set, the mapped memory is marked as executable.
35 EXEC
36 )
37
38 const (
39 // If the ANON flag is set, the mapped memory will not be backed by a file.
40 ANON = 1 << iota
41 )
42
43 // MMap represents a file mapped into memory.
44 type MMap []byte
45
46 // Map maps an entire file into memory.
56d5ec8 @edsrzf Simplify due to syscall.Mmap
authored
47 // Note that because of runtime limitations, no file larger than about 2GB can
48 // be completely mapped into memory.
b84771a @edsrzf Initial commit
authored
49 // If ANON is set in flags, f is ignored.
b9e6220 @edsrzf Convert to Go 1
authored
50 func Map(f *os.File, prot, flags int) (MMap, error) {
b84771a @edsrzf Initial commit
authored
51 return MapRegion(f, -1, prot, flags, 0)
52 }
53
54 // MapRegion maps part of a file into memory.
55 // The offset parameter must be a multiple of the system's page size.
56 // If length < 0, the entire file will be mapped.
56d5ec8 @edsrzf Simplify due to syscall.Mmap
authored
57 // Note that because of runtime limitations, no file larger than about 2GB can
58 // be completely mapped into memory.
b84771a @edsrzf Initial commit
authored
59 // If ANON is set in flags, f is ignored.
b9e6220 @edsrzf Convert to Go 1
authored
60 func MapRegion(f *os.File, length int, prot, flags int, offset int64) (MMap, error) {
b84771a @edsrzf Initial commit
authored
61 var fd uintptr
62 if flags&ANON == 0 {
63 fd = uintptr(f.Fd())
64 if length < 0 {
65 fi, err := f.Stat()
66 if err != nil {
67 return nil, err
68 }
b9e6220 @edsrzf Convert to Go 1
authored
69 length = int(fi.Size())
b84771a @edsrzf Initial commit
authored
70 }
71 } else {
72 if length <= 0 {
b9e6220 @edsrzf Convert to Go 1
authored
73 return nil, errors.New("anonymous mapping requires non-zero length")
b84771a @edsrzf Initial commit
authored
74 }
75 fd = ^uintptr(0)
76 }
56d5ec8 @edsrzf Simplify due to syscall.Mmap
authored
77 return mmap(length, uintptr(prot), uintptr(flags), fd, offset)
b84771a @edsrzf Initial commit
authored
78 }
79
80 func (m *MMap) header() *reflect.SliceHeader {
81 return (*reflect.SliceHeader)(unsafe.Pointer(m))
82 }
83
84 // Lock keeps the mapped region in physical memory, ensuring that it will not be
85 // swapped out.
b9e6220 @edsrzf Convert to Go 1
authored
86 func (m MMap) Lock() error {
b84771a @edsrzf Initial commit
authored
87 dh := m.header()
88 return lock(dh.Data, uintptr(dh.Len))
89 }
90
91 // Unlock reverses the effect of Lock, allowing the mapped region to potentially
92 // be swapped out.
93 // If m is already unlocked, aan error will result.
b9e6220 @edsrzf Convert to Go 1
authored
94 func (m MMap) Unlock() error {
b84771a @edsrzf Initial commit
authored
95 dh := m.header()
96 return unlock(dh.Data, uintptr(dh.Len))
97 }
98
99 // Flush synchronizes the mapping's contents to the file's contents on disk.
b9e6220 @edsrzf Convert to Go 1
authored
100 func (m MMap) Flush() error {
b84771a @edsrzf Initial commit
authored
101 dh := m.header()
102 return flush(dh.Data, uintptr(dh.Len))
103 }
104
105 // Unmap deletes the memory mapped region, flushes any remaining changes, and sets
106 // m to nil.
107 // Trying to read or write any remaining references to m after Unmap is called will
108 // result in undefined behavior.
109 // Unmap should only be called on the slice value that was originally returned from
110 // a call to Map. Calling Unmap on a derived slice may cause errors.
b9e6220 @edsrzf Convert to Go 1
authored
111 func (m *MMap) Unmap() error {
b84771a @edsrzf Initial commit
authored
112 dh := m.header()
113 err := unmap(dh.Data, uintptr(dh.Len))
114 *m = nil
115 return err
116 }
Something went wrong with that request. Please try again.