all_platform/vendor/github.com/gen2brain/shm/shm_solaris.go
2025-03-16 23:57:25 +08:00

199 lines
4.1 KiB
Go

// +build solaris
package shm
// #include <sys/ipc.h>
// #include <sys/shm.h>
// #include <errno.h>
import "C"
import (
"unsafe"
)
// Perm is used to pass permission information to IPC operations.
type Perm struct {
// Owner's user ID.
Uid uint32
// Owner's group ID.
Gid uint32
// Creator's user ID.
Cuid uint32
// Creator's group ID.
Cgid uint32
// Read/write permission.
Mode uint32
// Sequence number.
Seq uint32
// Key.
Key int32
}
// IdDs describes shared memory segment.
type IdDs struct {
// Operation permission struct.
Perm Perm
// Padding.
PadCgo0 [4]byte
// Size of segment in bytes.
SegSz uint64
// Flags.
Flags uint64
// Internal.
Lkcnt uint16
// Padding.
PadCgo1 [2]byte
// Pid of last shmat/shmdt.
Lpid int32
// Pid of creator.
Cpid int32
// Padding.
PadCgo2 [4]byte
// Number of current attaches.
Nattch uint64
// Internal.
Cnattch uint64
// Last attach time.
Atime int64
// Last detach time.
Dtime int64
// Last change time.
Ctime int64
// Internal.
Amp *byte
// Internal.
Gransize uint64
// Internal.
Allocated uint64
// Padding.
Pad4 [1]int64
}
// Constants.
const (
// Mode bits for `shmget`.
// Create key if key does not exist.
IPC_CREAT = 01000
// Fail if key exists.
IPC_EXCL = 02000
// Return error on wait.
IPC_NOWAIT = 04000
// Special key values.
// Private key.
IPC_PRIVATE = 0
// Flags for `shmat`.
// Attach read-only access.
SHM_RDONLY = 010000
// Round attach address to SHMLBA.
SHM_RND = 020000
// Take-over region on attach.
SHM_REMAP = 040000
// Execution access.
SHM_EXEC = 0100000
// Commands for `shmctl`.
// Lock segment (root only).
SHM_LOCK = 1
// Unlock segment (root only).
SHM_UNLOCK = 12
// Control commands for `shmctl`.
// Remove identifier.
IPC_RMID = 10
// Set `ipc_perm` options.
IPC_SET = 11
// Get `ipc_perm' options.
IPC_STAT = 12
)
// Get allocates a shared memory segment.
//
// Get() returns the identifier of the shared memory segment associated with the value of the argument key.
// A new shared memory segment is created if key has the value IPC_PRIVATE or key isn't IPC_PRIVATE,
// no shared memory segment corresponding to key exists, and IPC_CREAT is specified in shmFlg.
//
// If shmFlg specifies both IPC_CREAT and IPC_EXCL and a shared memory segment already exists for key,
// then Get() fails with errno set to EEXIST.
func Get(key int, size int, shmFlg int) (shmId int, err error) {
id, errno := C.shmget(C.key_t(key), C.size_t(size), C.int(shmFlg))
if int(id) == -1 {
return -1, errno
}
return int(id), nil
}
// At attaches the shared memory segment identified by shmId.
//
// Using At() with shmAddr equal to NULL is the preferred, portable way of attaching a shared memory segment.
func At(shmId int, shmAddr uintptr, shmFlg int) (data []byte, err error) {
addr, errno := C.shmat(C.int(shmId), unsafe.Pointer(shmAddr), C.int(shmFlg))
if int(uintptr(addr)) == -1 {
return nil, errno
}
length, err := Size(shmId)
if err != nil {
return nil, err
}
var b = struct {
addr uintptr
len int
cap int
}{uintptr(addr), int(length), int(length)}
data = *(*[]byte)(unsafe.Pointer(&b))
return data, nil
}
// Dt detaches the shared memory segment.
//
// The to-be-detached segment must be currently attached with shmAddr equal to the value returned by the attaching At() call.
func Dt(data []byte) error {
result, errno := C.shmdt(unsafe.Pointer(&data[0]))
if int(result) == -1 {
return errno
}
return nil
}
// Ctl performs the control operation specified by cmd on the shared memory segment whose identifier is given in shmId.
//
// The buf argument is a pointer to a IdDs structure.
func Ctl(shmId int, cmd int, buf *IdDs) (int, error) {
result, errno := C.shmctl(C.int(shmId), C.int(cmd), (*C.struct_shmid_ds)(unsafe.Pointer(buf)))
if int(result) == -1 {
return -1, errno
}
return int(result), nil
}
// Rm removes the shared memory segment.
func Rm(shmId int) error {
_, err := Ctl(shmId, IPC_RMID, nil)
return err
}
// Size returns size of shared memory segment.
func Size(shmId int) (int64, error) {
var idDs IdDs
_, err := Ctl(shmId, IPC_STAT, &idDs)
if err != nil {
return 0, err
}
return int64(idDs.SegSz), nil
}