mirror of https://github.com/hslam/shm.git
111 lines
2.4 KiB
Go
111 lines
2.4 KiB
Go
// Copyright (c) 2020 Meng Huang (mhboy@outlook.com)
|
|
// This package is licensed under a MIT license that can be found in the LICENSE file.
|
|
|
|
// +build darwin linux dragonfly freebsd netbsd openbsd
|
|
|
|
package shm
|
|
|
|
import (
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
const (
|
|
// IPC_CREAT creates if key is nonexistent
|
|
IPC_CREAT = 01000
|
|
|
|
// IPC_EXCL fails if key exists.
|
|
IPC_EXCL = 02000
|
|
|
|
// IPC_NOWAIT returns error no wait.
|
|
IPC_NOWAIT = 04000
|
|
|
|
// IPC_PRIVATE is private key
|
|
IPC_PRIVATE = 00000
|
|
|
|
// SEM_UNDO sets up adjust on exit entry
|
|
SEM_UNDO = 010000
|
|
|
|
// IPC_RMID removes identifier
|
|
IPC_RMID = 0
|
|
// IPC_SET sets ipc_perm options.
|
|
IPC_SET = 1
|
|
// IPC_STAT gets ipc_perm options.
|
|
IPC_STAT = 2
|
|
)
|
|
|
|
// Get calls the shmget system call.
|
|
func Get(key int, size int, shmFlg int) (int, error) {
|
|
if shmFlg == 0 {
|
|
shmFlg = IPC_CREAT | 0600
|
|
}
|
|
r1, _, errno := syscall.Syscall(SYS_SHMGET, uintptr(key), uintptr(validSize(int64(size))), uintptr(shmFlg))
|
|
shmid := int(r1)
|
|
if shmid < 0 {
|
|
return shmid, syscall.Errno(errno)
|
|
}
|
|
return shmid, nil
|
|
}
|
|
|
|
// At calls the shmat system call.
|
|
func At(shmid int, shmFlg int) (uintptr, error) {
|
|
shmaddr, _, errno := syscall.Syscall(SYS_SHMAT, uintptr(shmid), 0, uintptr(shmFlg))
|
|
if int(shmaddr) < 0 {
|
|
return shmaddr, syscall.Errno(errno)
|
|
}
|
|
return shmaddr, nil
|
|
}
|
|
|
|
// Dt calls the shmdt system call.
|
|
func Dt(addr uintptr) error {
|
|
r1, _, errno := syscall.Syscall(SYS_SHMDT, addr, 0, 0)
|
|
if int(r1) < 0 {
|
|
return syscall.Errno(errno)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetAttach calls the shmget and shmat system call.
|
|
func GetAttach(key int, size int, shmFlg int) (int, []byte, error) {
|
|
shmid, err := Get(key, size, shmFlg)
|
|
if err != nil {
|
|
return shmid, nil, err
|
|
}
|
|
shmaddr, err := At(shmid, shmFlg)
|
|
if err != nil {
|
|
Remove(shmid)
|
|
return shmid, nil, err
|
|
}
|
|
var sl = struct {
|
|
addr uintptr
|
|
len int
|
|
cap int
|
|
}{shmaddr, size, size}
|
|
b := *(*[]byte)(unsafe.Pointer(&sl))
|
|
return shmid, b, nil
|
|
}
|
|
|
|
// Detach calls the shmdt system call with []byte b.
|
|
func Detach(b []byte) error {
|
|
return Dt(uintptr(unsafe.Pointer(&b[0])))
|
|
}
|
|
|
|
// Remove removes the shm with the given id.
|
|
func Remove(shmid int) error {
|
|
r1, _, errno := syscall.Syscall(SYS_SHMCTL, uintptr(shmid), IPC_RMID, 0)
|
|
if int(r1) < 0 {
|
|
return syscall.Errno(errno)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Ftruncate changes the file size of the fd.
|
|
func Ftruncate(fd int, length int64) (err error) {
|
|
return syscall.Ftruncate(fd, length)
|
|
}
|
|
|
|
// Close closes the fd.
|
|
func Close(fd int) (err error) {
|
|
return syscall.Close(fd)
|
|
}
|