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 15package mmap 16 17import ( 18 "errors" 19 "os" 20 "reflect" 21 "unsafe" 22) 23 24const ( 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 38const ( 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. 44type MMap []byte 45 46// Map maps an entire file into memory. 47// If ANON is set in flags, f is ignored. 48func Map(f *os.File, prot, flags int) (MMap, error) { 49 return MapRegion(f, -1, prot, flags, 0) 50} 51 52// MapRegion maps part of a file into memory. 53// The offset parameter must be a multiple of the system's page size. 54// If length < 0, the entire file will be mapped. 55// If ANON is set in flags, f is ignored. 56func MapRegion(f *os.File, length int, prot, flags int, offset int64) (MMap, error) { 57 var fd uintptr 58 if flags&ANON == 0 { 59 fd = uintptr(f.Fd()) 60 if length < 0 { 61 fi, err := f.Stat() 62 if err != nil { 63 return nil, err 64 } 65 length = int(fi.Size()) 66 } 67 } else { 68 if length <= 0 { 69 return nil, errors.New("anonymous mapping requires non-zero length") 70 } 71 fd = ^uintptr(0) 72 } 73 return mmap(length, uintptr(prot), uintptr(flags), fd, offset) 74} 75 76func (m *MMap) header() *reflect.SliceHeader { 77 return (*reflect.SliceHeader)(unsafe.Pointer(m)) 78} 79 80// Lock keeps the mapped region in physical memory, ensuring that it will not be 81// swapped out. 82func (m MMap) Lock() error { 83 dh := m.header() 84 return lock(dh.Data, uintptr(dh.Len)) 85} 86 87// Unlock reverses the effect of Lock, allowing the mapped region to potentially 88// be swapped out. 89// If m is already unlocked, aan error will result. 90func (m MMap) Unlock() error { 91 dh := m.header() 92 return unlock(dh.Data, uintptr(dh.Len)) 93} 94 95// Flush synchronizes the mapping's contents to the file's contents on disk. 96func (m MMap) Flush() error { 97 dh := m.header() 98 return flush(dh.Data, uintptr(dh.Len)) 99} 100 101// Unmap deletes the memory mapped region, flushes any remaining changes, and sets 102// m to nil. 103// Trying to read or write any remaining references to m after Unmap is called will 104// result in undefined behavior. 105// Unmap should only be called on the slice value that was originally returned from 106// a call to Map. Calling Unmap on a derived slice may cause errors. 107func (m *MMap) Unmap() error { 108 dh := m.header() 109 err := unmap(dh.Data, uintptr(dh.Len)) 110 *m = nil 111 return err 112} 113