diff options
Diffstat (limited to 'sysv/sem.go')
-rw-r--r-- | sysv/sem.go | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/sysv/sem.go b/sysv/sem.go new file mode 100644 index 0000000..631a16b --- /dev/null +++ b/sysv/sem.go @@ -0,0 +1,106 @@ +package sysv + +import ( + "unsafe" + + "golang.org/x/sys/unix" +) + +const ( + SYS_GETPID int = 0x0B + iota + SYS_GETVAL + SYS_SETVAL int = 0x010 +) + +const ( + non = iota - one + one = 0x01 + zro = 0x00 +) + +type oprations struct { + num uint16 + opt int16 + flg int16 +} + +type Semaphore struct { + nums int + smid int +} + +func NewSemGet(key, nums, flags int) (*Semaphore, error) { + id, _, errno := unix.Syscall( + unix.SYS_SEMGET, uintptr(key), + uintptr(nums), uintptr(flags), + ) + if errno != 0 { + return nil, error(errno) + } + return &Semaphore{nums: nums, smid: int(id)}, nil +} + +func (sem *Semaphore) GetVal(semnum int) (int, error) { + vl, _, errno := unix.Syscall( + unix.SYS_SEMCTL, uintptr(sem.smid), + uintptr(semnum), uintptr(SYS_GETVAL), + ) + if errno != 0 { + return int(vl), error(errno) + } + return int(vl), nil +} + +func (sem *Semaphore) SetVal(semnum, v int) error { + _, _, errno := unix.Syscall6( + unix.SYS_SEMCTL, uintptr(sem.smid), + uintptr(semnum), uintptr(SYS_SETVAL), uintptr(v), 0, 0, + ) + if errno != 0 { + return error(errno) + } + return nil +} + +func (sem *Semaphore) GetPID(semnum int) (int, error) { + pid, _, errno := unix.Syscall( + unix.SYS_SEMCTL, uintptr(sem.smid), + uintptr(semnum), uintptr(SYS_GETPID), + ) + if errno != 0 { + return int(pid), error(errno) + } + return int(pid), nil +} + +func (sem *Semaphore) setops(n uint16, o, f int16) error { + opt := oprations{num: n, opt: o, flg: f} + _, _, errno := unix.Syscall( + unix.SYS_SEMOP, uintptr(sem.smid), + uintptr(unsafe.Pointer(&opt)), uintptr(sem.nums), + ) + + if errno != 0 { + return error(errno) + } + return nil +} + +func (sem *Semaphore) Lock(semnum int) error { + return sem.setops(uint16(semnum), non, zro) +} + +func (sem *Semaphore) Unlock(semnum int) error { + return sem.setops(uint16(semnum), one, zro) +} + +func (sem *Semaphore) DelSem() error { + _, _, errno := unix.Syscall( + unix.SYS_SEMCTL, uintptr(sem.smid), + uintptr(0), uintptr(unix.IPC_RMID), + ) + if errno != 0 { + return error(errno) + } + return nil +} |