diff --git a/README.md b/README.md index 90392a6..c246bfa 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,18 @@ var send = flag.Bool("s", true, "send") func main() { flag.Parse() key, _ := ipc.Ftok("/tmp", 0x22) - semid, _ := ipc.Semget(key) + semnum := 0 + semid, err := ipc.Semget(key, 1, 0666) + if err != nil { + semid, err = ipc.Semget(key, 1, ipc.IPC_CREAT|ipc.IPC_EXCL|0666) + if err != nil { + panic(err) + } + _, err := ipc.Semsetvalue(semid, semnum, 1) + if err != nil { + panic(err) + } + } defer ipc.Semrm(semid) shmid, data, _ := ipc.Shmgetat(key, 128, ipc.IPC_CREAT|0600) defer ipc.Shmrm(shmid) @@ -60,11 +71,11 @@ func main() { buf := make([]byte, 10) for { fmt.Scanln(&text) - if _, err := ipc.Semp(semid, ipc.SEM_UNDO); err != nil { + if _, err := ipc.Semp(semid, semnum, ipc.SEM_UNDO); err != nil { return } copy(data, text) - if _, err := ipc.Semv(semid, ipc.SEM_UNDO); err != nil { + if _, err := ipc.Semv(semid, semnum, ipc.SEM_UNDO); err != nil { return } n := binary.PutUvarint(buf, uint64(len(text))) @@ -80,11 +91,11 @@ func main() { return } length, _ := binary.Uvarint(m) - if _, err := ipc.Semp(semid, ipc.SEM_UNDO); err != nil { + if _, err := ipc.Semp(semid, semnum, ipc.SEM_UNDO); err != nil { return } text = string(data[:length]) - if _, err := ipc.Semv(semid, ipc.SEM_UNDO); err != nil { + if _, err := ipc.Semv(semid, semnum, ipc.SEM_UNDO); err != nil { return } fmt.Println(text) diff --git a/ipc.go b/ipc.go index bba1930..c010d48 100644 --- a/ipc.go +++ b/ipc.go @@ -8,14 +8,17 @@ package ipc const ( // IPC_CREAT creates if key is nonexistent - IPC_CREAT = 00001000 + IPC_CREAT = 01000 // IPC_EXCL fails if key exists. - IPC_EXCL = 00002000 + 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 diff --git a/ipc_test.go b/ipc_test.go index 1704b79..ef75262 100644 --- a/ipc_test.go +++ b/ipc_test.go @@ -4,6 +4,7 @@ package ipc import ( + "github.com/hslam/sem" "strings" "testing" "time" @@ -12,21 +13,31 @@ import ( func TestIPC(t *testing.T) { context := strings.Repeat("1", 64) done := make(chan struct{}) + semnum := 0 go func() { key, _ := Ftok("/tmp", 0x22) - semid, _ := Semget(key) + semid, err := Semget(key, 1, 0600) + if err != nil { + semid, err = Semget(key, 1, IPC_CREAT|IPC_EXCL|0600) + if err != nil { + panic(err) + } + _, err := Semsetvalue(semid, semnum, 1) + if err != nil { + panic(err) + } + } defer Semrm(semid) shmid, data, _ := Shmgetat(key, 128, IPC_CREAT|0600) defer Shmrm(shmid) defer Shmdt(data) msgid, _ := Msgget(key, IPC_CREAT|0600) defer Msgrm(msgid) - - if _, err := Semp(semid, SEM_UNDO); err != nil { + if _, err := Semp(semid, semnum, SEM_UNDO); err != nil { return } copy(data, context) - if _, err := Semv(semid, SEM_UNDO); err != nil { + if _, err := Semv(semid, semnum, SEM_UNDO); err != nil { return } if err := Msgsnd(msgid, 1, []byte{byte(len(context))}, 0600); err != nil { @@ -39,12 +50,22 @@ func TestIPC(t *testing.T) { time.Sleep(time.Millisecond * 100) key, _ := Ftok("/tmp", 0x22) - semid, _ := Semget(key) + semid, err := Semget(key, 1, 0600) + if err != nil { + semid, err = Semget(key, 1, IPC_CREAT|IPC_EXCL|0600) + if err != nil { + panic(err) + } + _, err := Semsetvalue(semid, semnum, 1) + if err != nil { + panic(err) + } + } defer Semrm(semid) - shmid, data, _ := Shmgetat(key, 128, IPC_CREAT|0600) + shmid, data, _ := Shmgetat(key, 128, 0600) defer Shmrm(shmid) defer Shmdt(data) - msgid, _ := Msgget(key, IPC_CREAT|0600) + msgid, _ := Msgget(key, 0600) defer Msgrm(msgid) m, err := Msgrcv(msgid, 1, 0600) @@ -52,16 +73,20 @@ func TestIPC(t *testing.T) { return } length := int(m[0]) - if ret, err := Semgetvalue(semid); err != nil { + if ret, err := Semgetvalue(semid, semnum); err != nil { t.Error(err) } else if ret < 1 { t.Error() } - if _, err := Semp(semid, SEM_UNDO); err != nil { + var sops [1]sem.Sembuf + sops[0] = sem.Sembuf{SemNum: uint16(semnum), SemFlg: SEM_UNDO} + sops[0].SemOp = -1 + if _, err := Semop(semid, sops[:]); err != nil { return } text := string(data[:length]) - if _, err := Semv(semid, SEM_UNDO); err != nil { + sops[0].SemOp = 1 + if _, err := Semop(semid, sops[:]); err != nil { return } diff --git a/msg.go b/msg.go index b723e3c..70b929e 100644 --- a/msg.go +++ b/msg.go @@ -8,21 +8,21 @@ import ( ) // Msgget calls the msgget system call. -func Msgget(key int, msgflg int) (uintptr, error) { +func Msgget(key int, msgflg int) (int, error) { return msg.Get(key, msgflg) } // Msgsnd calls the msgsnd system call. -func Msgsnd(msgid uintptr, msgType uint, msgText []byte, flags uint) error { +func Msgsnd(msgid int, msgType uint, msgText []byte, flags int) error { return msg.Snd(msgid, msgType, msgText, flags) } // Msgrcv calls the msgrcv system call. -func Msgrcv(msgid uintptr, msgType uint, flags uint) ([]byte, error) { +func Msgrcv(msgid int, msgType uint, flags int) ([]byte, error) { return msg.Rcv(msgid, msgType, flags) } // Msgrm removes the shm with the given id. -func Msgrm(msgid uintptr) error { +func Msgrm(msgid int) error { return msg.Remove(msgid) } diff --git a/sem.go b/sem.go index afb1998..2cc38df 100644 --- a/sem.go +++ b/sem.go @@ -8,26 +8,66 @@ import ( ) // Semget calls the semget system call. -func Semget(key int) (uintptr, error) { - return sem.Get(key) +// +// The semget() system call returns the System V semaphore set identifier +// associated with the argument key. +// +// A new set of nsems semaphores is created if key has the value +// IPC_PRIVATE or if no existing semaphore set is associated with key +// and IPC_CREAT is specified in semflg. +// +// If semflg specifies both IPC_CREAT and IPC_EXCL and a semaphore set +// already exists for key, then semget() fails with errno set to EEXIST. +// +// The argument nsems can be 0 (a don't care) when a semaphore set is +// not being created. Otherwise, nsems must be greater than 0 and less +// than or equal to the maximum number of semaphores per semaphore set. +// +// If successful, the return value will be the semaphore set identifier, +// otherwise, -1 is returned, with errno indicating the error. +func Semget(key int, nsems int, semflg int) (int, error) { + return sem.Get(key, nsems, semflg) } -// Semp calls the semop P system call. -func Semp(semid uintptr, flg int16) (bool, error) { - return sem.P(semid, flg) -} - -// Semv calls the semop V system call. -func Semv(semid uintptr, flg int16) (bool, error) { - return sem.V(semid, flg) +// Semsetvalue calls the semctl SETVAL system call. +func Semsetvalue(semid int, semnum int, semun int) (bool, error) { + return sem.SetValue(semid, semnum, semun) } // Semgetvalue calls the semctl GETVAL system call. -func Semgetvalue(semid uintptr) (int, error) { - return sem.GetValue(semid) +func Semgetvalue(semid int, semnum int) (int, error) { + return sem.GetValue(semid, semnum) +} + +// Semp calls the semop P system call. +// Flags recognized in semflg are IPC_NOWAIT and SEM_UNDO. +// If an operation specifies SEM_UNDO, it will be automatically undone when the +// process terminates. +func Semp(semid int, semnum int, semflg int) (bool, error) { + return sem.P(semid, semnum, semflg) +} + +// Semv calls the semop V system call. +// Flags recognized in semflg are IPC_NOWAIT and SEM_UNDO. +// If an operation specifies SEM_UNDO, it will be automatically undone when the +// process terminates. +func Semv(semid int, semnum int, semflg int) (bool, error) { + return sem.V(semid, semnum, semflg) +} + +// Semop calls the semop system call. +// Flags recognized in SemFlg are IPC_NOWAIT and SEM_UNDO. +// If an operation specifies SEM_UNDO, it will be automatically undone when the +// process terminates. +// Op calls the semop system call. +// Flags recognized in SemFlg are IPC_NOWAIT and SEM_UNDO. +// If an operation specifies SEM_UNDO, it will be automatically undone when the +// process terminates. +func Semop(semid int, sops []sem.Sembuf) (bool, error) { + return sem.Op(semid, sops) } // Semrm removes the semaphore with the given id. -func Semrm(semid uintptr) error { +func Semrm(semid int) error { return sem.Remove(semid) } diff --git a/shm.go b/shm.go index 6b064e4..d6f07f5 100644 --- a/shm.go +++ b/shm.go @@ -8,7 +8,7 @@ import ( ) // Shmgetat calls the shmget and shmat system call. -func Shmgetat(key int, size int, shmFlg int) (uintptr, []byte, error) { +func Shmgetat(key int, size int, shmFlg int) (int, []byte, error) { return shm.GetAt(key, size, shmFlg) } @@ -18,6 +18,6 @@ func Shmdt(b []byte) error { } // Shmrm removes the shm with the given id. -func Shmrm(shmid uintptr) error { +func Shmrm(shmid int) error { return shm.Remove(shmid) }