Skip to content

Commit

Permalink
Updated to Go 1 and polished a bit.
Browse files Browse the repository at this point in the history
  • Loading branch information
niemeyer committed Apr 18, 2012
1 parent 54d1108 commit f168d56
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 229 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
gommap - Memory mapping support for Go.

Copyright (c) 2010, Gustavo Niemeyer <[email protected]>
Copyright (c) 2010-2012, Gustavo Niemeyer <[email protected]>

All rights reserved.

Expand Down
30 changes: 0 additions & 30 deletions Makefile

This file was deleted.

45 changes: 0 additions & 45 deletions consts.c

This file was deleted.

59 changes: 34 additions & 25 deletions consts.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,47 @@
// ** This file is automatically generated from consts.c. **
// ** This file is automatically generated from consts.c.txt **

package gommap

type ProtFlags uint

const (
PROT_NONE = 0x0
PROT_READ = 0x1
PROT_WRITE = 0x2
PROT_EXEC = 0x4
PROT_NONE ProtFlags = 0x0
PROT_READ ProtFlags = 0x1
PROT_WRITE ProtFlags = 0x2
PROT_EXEC ProtFlags = 0x4
)

type MapFlags uint

const (
MAP_SHARED = 0x1
MAP_PRIVATE = 0x2
MAP_FIXED = 0x10
MAP_ANONYMOUS = 0x20
MAP_GROWSDOWN = 0x100
MAP_LOCKED = 0x2000
MAP_NONBLOCK = 0x10000
MAP_NORESERVE = 0x4000
MAP_POPULATE = 0x8000
MAP_SHARED MapFlags = 0x1
MAP_PRIVATE MapFlags = 0x2
MAP_FIXED MapFlags = 0x10
MAP_ANONYMOUS MapFlags = 0x20
MAP_GROWSDOWN MapFlags = 0x100
MAP_LOCKED MapFlags = 0x2000
MAP_NONBLOCK MapFlags = 0x10000
MAP_NORESERVE MapFlags = 0x4000
MAP_POPULATE MapFlags = 0x8000
)

type SyncFlags uint

const (
MS_SYNC = 0x4
MS_ASYNC = 0x1
MS_INVALIDATE = 0x2
MS_SYNC SyncFlags = 0x4
MS_ASYNC SyncFlags = 0x1
MS_INVALIDATE SyncFlags = 0x2
)

type AdviseFlags uint

const (
MADV_NORMAL = 0x0
MADV_RANDOM = 0x1
MADV_SEQUENTIAL = 0x2
MADV_WILLNEED = 0x3
MADV_DONTNEED = 0x4
MADV_REMOVE = 0x9
MADV_DONTFORK = 0xa
MADV_DOFORK = 0xb
MADV_NORMAL AdviseFlags = 0x0
MADV_RANDOM AdviseFlags = 0x1
MADV_SEQUENTIAL AdviseFlags = 0x2
MADV_WILLNEED AdviseFlags = 0x3
MADV_DONTNEED AdviseFlags = 0x4
MADV_REMOVE AdviseFlags = 0x9
MADV_DONTFORK AdviseFlags = 0xa
MADV_DOFORK AdviseFlags = 0xb
)
162 changes: 80 additions & 82 deletions gommap.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Type representing memory mapped file or device. The returned MMap value,
// which is itself an alias to a []byte slice, gives direct access to the
// memory mapped content.
// This package offers the MMap type that manipulates a memory mapped file or
// device.
//
// IMPORTANT NOTE (1): The MMap type is backed by an unsafe memory region,
// which is not covered by the normal rules of Go's memory management. If a
Expand All @@ -11,54 +10,54 @@
package gommap

import (
"syscall"
"os"
"reflect"
"syscall"
"unsafe"
"os"
)


// Type representing memory mapped file or device. The slice gives direct
// access to the memory mapped content.
// The MMap type represents a memory mapped file or device. The slice offers
// direct access to the memory mapped content.
//
// IMPORTANT: Please see note (1) in the package documentation regarding the way
// IMPORTANT: Please see note in the package documentation regarding the way
// in which this type behaves.
type MMap []uint8
type MMap []byte

// Create a new mapping in the virtual address space of the calling process.
// Map creates a new mapping in the virtual address space of the calling process.
// This function will attempt to map the entire file by using the fstat system
// call with the provided file descriptor to discover its length.
func Map(fd int, prot, flags uint) (MMap, os.Error) {
func Map(fd uintptr, prot ProtFlags, flags MapFlags) (MMap, error) {
mmap, err := MapAt(0, fd, 0, -1, prot, flags)
return mmap, err
}

// Create a new mapping in the virtual address space of the calling process,
// using the specified region of the provided file or device. If -1 is provided
// as length, this function will attempt to map until the end of the provided
// file descriptor by using the fstat system call to discover its length.
func MapRegion(fd int, offset, length int64, prot, flags uint) (MMap, os.Error) {
// MapRegion creates a new mapping in the virtual address space of the calling
// process, using the specified region of the provided file or device. If -1 is
// provided as length, this function will attempt to map until the end of the
// provided file descriptor by using the fstat system call to discover its
// length.
func MapRegion(fd uintptr, offset, length int64, prot ProtFlags, flags MapFlags) (MMap, error) {
mmap, err := MapAt(0, fd, offset, length, prot, flags)
return mmap, err
}

// Create a new mapping in the virtual address space of the calling process,
// using the specified region of the provided file or device. The provided addr
// parameter will be used as a hint of the address where the kernel should
// position the memory mapped region. If -1 is provided as length, this
// function will attempt to map until the end of the provided file descriptor
// by using the fstat system call to discover its length.
func MapAt(addr uintptr, fd int, offset, length int64, prot, flags uint) (MMap, os.Error) {
// MapAt creates a new mapping in the virtual address space of the calling
// process, using the specified region of the provided file or device. The
// provided addr parameter will be used as a hint of the address where the
// kernel should position the memory mapped region. If -1 is provided as
// length, this function will attempt to map until the end of the provided
// file descriptor by using the fstat system call to discover its length.
func MapAt(addr uintptr, fd uintptr, offset, length int64, prot ProtFlags, flags MapFlags) (MMap, error) {
if length == -1 {
var stat syscall.Stat_t
if errno := syscall.Fstat(fd, &stat); errno != 0 {
return nil, os.Errno(errno)
if err := syscall.Fstat(int(fd), &stat); err != nil {
return nil, err
}
length = stat.Size
}
addr, errno := mmap_syscall(addr, uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), offset)
if errno != 0 {
return nil, os.Errno(errno)
addr, err := mmap_syscall(addr, uintptr(length), uintptr(prot), uintptr(flags), fd, offset)
if err != syscall.Errno(0) {
return nil, err
}
mmap := MMap{}

Expand All @@ -69,93 +68,92 @@ func MapAt(addr uintptr, fd int, offset, length int64, prot, flags uint) (MMap,
return mmap, nil
}

// Delete the memory mapped region defined by the mmap slice. This will also
// flush any remaining changes, if necessary. Using mmap after this method
// has been called will crash the application.
//
// IMPORTANT: Please see note (1) in the package documentation regarding the way
// in which this type behaves.
func (mmap MMap) UnsafeUnmap() os.Error {
// UnsafeUnmap deletes the memory mapped region defined by the mmap slice. This
// will also flush any remaining changes, if necessary. Using mmap or any
// other slices based on it after this method has been called will crash the
// application.
func (mmap MMap) UnsafeUnmap() error {
rh := *(*reflect.SliceHeader)(unsafe.Pointer(&mmap))
_, _, errno := syscall.Syscall(syscall.SYS_MUNMAP, uintptr(rh.Data), uintptr(rh.Len), 0)
if errno != 0 {
return os.Errno(errno)
_, _, err := syscall.Syscall(syscall.SYS_MUNMAP, uintptr(rh.Data), uintptr(rh.Len), 0)
if err != 0 {
return err
}
return nil
}

// Flush changes made to the region determined by the mmap slice back to
// the device. Without calling this method, there are no guarantees that
// changes will be flushed back before the region is unmapped. The flags
// parameter specifies whether flushing should be done synchronously (before
// the method returns) with MS_SYNC, or asynchronously (flushing is just
// Sync flushes changes made to the region determined by the mmap slice
// back to the device. Without calling this method, there are no guarantees
// that changes will be flushed back before the region is unmapped. The
// flags parameter specifies whether flushing should be done synchronously
// (before the method returns) with MS_SYNC, or asynchronously (flushing is just
// scheduled) with MS_ASYNC.
func (mmap MMap) Sync(flags uint) os.Error {
func (mmap MMap) Sync(flags SyncFlags) error {
rh := *(*reflect.SliceHeader)(unsafe.Pointer(&mmap))
_, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(rh.Data), uintptr(rh.Len), uintptr(flags))
if errno != 0 {
return os.Errno(errno)
_, _, err := syscall.Syscall(syscall.SYS_MSYNC, uintptr(rh.Data), uintptr(rh.Len), uintptr(flags))
if err != 0 {
return err
}
return nil
}

// Advise the kernel about how to handle the mapped memory region in terms
// of input/output paging within the memory region defined by the mmap slice.
func (mmap MMap) Advise(advice uint) os.Error {
// Advise advises the kernel about how to handle the mapped memory
// region in terms of input/output paging within the memory region
// defined by the mmap slice.
func (mmap MMap) Advise(advice AdviseFlags) error {
rh := *(*reflect.SliceHeader)(unsafe.Pointer(&mmap))
_, _, errno := syscall.Syscall(syscall.SYS_MADVISE, uintptr(rh.Data), uintptr(rh.Len), uintptr(advice))
if errno != 0 {
return os.Errno(errno)
_, _, err := syscall.Syscall(syscall.SYS_MADVISE, uintptr(rh.Data), uintptr(rh.Len), uintptr(advice))
if err != 0 {
return err
}
return nil
}

// Change protection flags for the memory mapped region defined by
// the mmap slice.
func (mmap MMap) Protect(prot uint) os.Error {
// Protect changes the protection flags for the memory mapped region
// defined by the mmap slice.
func (mmap MMap) Protect(prot ProtFlags) error {
rh := *(*reflect.SliceHeader)(unsafe.Pointer(&mmap))
_, _, errno := syscall.Syscall(syscall.SYS_MPROTECT, uintptr(rh.Data), uintptr(rh.Len), uintptr(prot))
if errno != 0 {
return os.Errno(errno)
_, _, err := syscall.Syscall(syscall.SYS_MPROTECT, uintptr(rh.Data), uintptr(rh.Len), uintptr(prot))
if err != 0 {
return err
}
return nil
}

// Lock the mapped region defined by the mmap slice, preventing it from
// being swapped out.
func (mmap MMap) Lock() os.Error {
// Lock locks the mapped region defined by the mmap slice,
// preventing it from being swapped out.
func (mmap MMap) Lock() error {
rh := *(*reflect.SliceHeader)(unsafe.Pointer(&mmap))
_, _, errno := syscall.Syscall(syscall.SYS_MLOCK, uintptr(rh.Data), uintptr(rh.Len), 0)
if errno != 0 {
return os.Errno(errno)
_, _, err := syscall.Syscall(syscall.SYS_MLOCK, uintptr(rh.Data), uintptr(rh.Len), 0)
if err != 0 {
return err
}
return nil
}

// Unlock the mapped region defined by the mmap slice, allowing it to
// swap out again.
func (mmap MMap) Unlock() os.Error {
// Unlock unlocks the mapped region defined by the mmap slice,
// allowing it to swap out again.
func (mmap MMap) Unlock() error {
rh := *(*reflect.SliceHeader)(unsafe.Pointer(&mmap))
_, _, errno := syscall.Syscall(syscall.SYS_MUNLOCK, uintptr(rh.Data), uintptr(rh.Len), 0)
if errno != 0 {
return os.Errno(errno)
_, _, err := syscall.Syscall(syscall.SYS_MUNLOCK, uintptr(rh.Data), uintptr(rh.Len), 0)
if err != 0 {
return err
}
return nil
}

// Return an array of uint8 values informing with the lowest bit whether
// the given page in the mapped region defined by the mmap slice was or
// not in memory at the time the call was made. Note that the higher bits
// are reserved for future use, so do not simply run an equality test
// with 1.
func (mmap MMap) InCore() ([]uint8, os.Error) {
// InCore returns a slice of booleans informing whether the respective
// memory page in mmap was or not mapped at the time the call was made.
func (mmap MMap) InCore() ([]bool, error) {
pageSize := os.Getpagesize()
result := make([]uint8, (len(mmap)+pageSize-1)/pageSize)
result := make([]bool, (len(mmap)+pageSize-1)/pageSize)
rh := *(*reflect.SliceHeader)(unsafe.Pointer(&mmap))
resulth := *(*reflect.SliceHeader)(unsafe.Pointer(&result))
_, _, errno := syscall.Syscall(syscall.SYS_MINCORE, uintptr(rh.Data), uintptr(rh.Len), uintptr(resulth.Data))
if errno != 0 {
return nil, os.Errno(errno)
_, _, err := syscall.Syscall(syscall.SYS_MINCORE, uintptr(rh.Data), uintptr(rh.Len), uintptr(resulth.Data))
for i := range result {
*(*uint8)(unsafe.Pointer(&result[i])) &= 1
}
if err != 0 {
return nil, err
}
return result, nil
}
Loading

0 comments on commit f168d56

Please sign in to comment.