From a0123f163eddcea3e6b9f9d36f1f3fb3aa2c835a Mon Sep 17 00:00:00 2001
From: zhangmeng <775834166@qq.com>
Date: 星期一, 26 八月 2019 13:46:34 +0800
Subject: [PATCH] update
---
/dev/null | 21 ----
create.go | 16 +-
sem.go | 114 ++++++++++++++++++++++
shm.go | 83 ++++++++++++++++
open.go | 7
readwriter.go | 27 +----
6 files changed, 212 insertions(+), 56 deletions(-)
diff --git a/create.go b/create.go
index 8fa3080..640429b 100644
--- a/create.go
+++ b/create.go
@@ -6,13 +6,11 @@
package shm
import (
- "golang.org/x/sys/unix"
"os"
"sync/atomic"
"unsafe"
- "github.com/tmthrgd/go-sem"
- "github.com/tmthrgd/go-shm"
+ "golang.org/x/sys/unix"
)
func CreateSimplex(name string, perm os.FileMode, blockCount, blockSize int) (*ReadWriteCloser, error) {
@@ -20,7 +18,7 @@
return nil, ErrNotMultipleOf64
}
- file, err := shm.Open(name, unix.O_CREAT|unix.O_EXCL|unix.O_TRUNC|unix.O_RDWR, perm)
+ file, err := Open(name, unix.O_CREAT|unix.O_EXCL|unix.O_TRUNC|unix.O_RDWR, perm)
if err != nil {
return nil, err
}
@@ -50,11 +48,11 @@
*/
*(*uint32)(&shared.BlockCount), *(*uint64)(&shared.BlockSize) = uint32(blockCount), uint64(blockSize)
- if err = ((*sem.Semaphore)(&shared.SemSignal)).Init(0); err != nil {
+ if err = ((*Semaphore)(&shared.SemSignal)).Init(0); err != nil {
return nil, err
}
- if err = ((*sem.Semaphore)(&shared.SemAvail)).Init(0); err != nil {
+ if err = ((*Semaphore)(&shared.SemAvail)).Init(0); err != nil {
return nil, err
}
@@ -91,7 +89,7 @@
return nil, ErrNotMultipleOf64
}
- file, err := shm.Open(name, unix.O_CREAT|unix.O_EXCL|unix.O_TRUNC|unix.O_RDWR, perm)
+ file, err := Open(name, unix.O_CREAT|unix.O_EXCL|unix.O_TRUNC|unix.O_RDWR, perm)
if err != nil {
return nil, err
}
@@ -123,11 +121,11 @@
*/
*(*uint32)(&shared.BlockCount), *(*uint64)(&shared.BlockSize) = uint32(blockCount), uint64(blockSize)
- if err = ((*sem.Semaphore)(&shared.SemSignal)).Init(0); err != nil {
+ if err = ((*Semaphore)(&shared.SemSignal)).Init(0); err != nil {
return nil, err
}
- if err = ((*sem.Semaphore)(&shared.SemAvail)).Init(0); err != nil {
+ if err = ((*Semaphore)(&shared.SemAvail)).Init(0); err != nil {
return nil, err
}
diff --git a/net/addr.go b/net/addr.go
deleted file mode 100644
index 4924376..0000000
--- a/net/addr.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2016 Tom Thorogood. All rights reserved.
-// Use of this source code is governed by a
-// Modified BSD License license that can be found in
-// the LICENSE file.
-
-package net
-
-type addr string
-
-func (addr) Network() string {
- return "shm"
-}
-
-func (a addr) String() string {
- return string(a)
-}
diff --git a/net/conn.go b/net/conn.go
deleted file mode 100644
index 36a5e23..0000000
--- a/net/conn.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2016 Tom Thorogood. All rights reserved.
-// Use of this source code is governed by a
-// Modified BSD License license that can be found in
-// the LICENSE file.
-
-package net
-
-import (
- "net"
- "sync"
- "time"
-
- "github.com/tmthrgd/shm-go"
-)
-
-type Conn struct {
- *shm.ReadWriteCloser
- name string
-
- mut *sync.Mutex
-}
-
-func (c *Conn) Close() error {
- c.mut.Unlock()
- return nil
-}
-
-func (c *Conn) LocalAddr() net.Addr {
- return addr(c.name)
-}
-
-func (c *Conn) RemoteAddr() net.Addr {
- return addr(c.name)
-}
-
-func (c *Conn) SetDeadline(t time.Time) error {
- return nil
-}
-
-func (c *Conn) SetReadDeadline(t time.Time) error {
- return nil
-}
-
-func (c *Conn) SetWriteDeadline(t time.Time) error {
- return nil
-}
diff --git a/net/dialer.go b/net/dialer.go
deleted file mode 100644
index 1d3cefb..0000000
--- a/net/dialer.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2016 Tom Thorogood. All rights reserved.
-// Use of this source code is governed by a
-// Modified BSD License license that can be found in
-// the LICENSE file.
-
-package net
-
-import (
- "errors"
- "net"
- "sync"
-
- "github.com/tmthrgd/shm-go"
-)
-
-type Dialer struct {
- rw *shm.ReadWriteCloser
- name string
-
- mut sync.Mutex
-}
-
-func Dial(name string) (net.Conn, error) {
- rw, err := shm.OpenDuplex(name)
- if err != nil {
- return nil, err
- }
-
- return (&Dialer{
- rw: rw,
- name: name,
- }).Dial("shm", name)
-}
-
-func NewDialer(rw *shm.ReadWriteCloser, name string) *Dialer {
- return &Dialer{
- rw: rw,
- name: name,
- }
-}
-
-func (d *Dialer) Dial(network, address string) (net.Conn, error) {
- if network != "shm" {
- return nil, errors.New("unrecognised network")
- }
-
- if address != d.name {
- return nil, errors.New("invalid address")
- }
-
- d.mut.Lock()
- return &Conn{d.rw, d.name, &d.mut}, nil
-}
diff --git a/net/listener.go b/net/listener.go
deleted file mode 100644
index 4039490..0000000
--- a/net/listener.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2016 Tom Thorogood. All rights reserved.
-// Use of this source code is governed by a
-// Modified BSD License license that can be found in
-// the LICENSE file.
-
-package net
-
-import (
- "net"
- "os"
- "sync"
-
- "github.com/tmthrgd/shm-go"
-)
-
-type Listener struct {
- rw *shm.ReadWriteCloser
- name string
-
- mut sync.Mutex
-}
-
-func Listen(name string, perm os.FileMode, blockCount, blockSize int) (*Listener, error) {
- rw, err := shm.CreateDuplex(name, perm, blockCount, blockSize)
- if err != nil {
- return nil, err
- }
-
- return &Listener{
- rw: rw,
- name: name,
- }, nil
-}
-
-func NewListener(rw *shm.ReadWriteCloser, name string) *Listener {
- return &Listener{
- rw: rw,
- name: name,
- }
-}
-
-func (l *Listener) Accept() (net.Conn, error) {
- l.mut.Lock()
- return &Conn{l.rw, l.name, &l.mut}, nil
-}
-
-func (l *Listener) Close() error {
- return l.rw.Close()
-}
-
-func (l *Listener) Addr() net.Addr {
- return addr(l.name)
-}
diff --git a/open.go b/open.go
index 861bb76..a63b4b5 100644
--- a/open.go
+++ b/open.go
@@ -6,15 +6,14 @@
package shm
import (
- "golang.org/x/sys/unix"
"sync/atomic"
"unsafe"
- "github.com/tmthrgd/go-shm"
+ "golang.org/x/sys/unix"
)
func OpenSimplex(name string) (*ReadWriteCloser, error) {
- file, err := shm.Open(name, unix.O_RDWR, 0)
+ file, err := Open(name, unix.O_RDWR, 0)
if err != nil {
return nil, err
}
@@ -60,7 +59,7 @@
}
func OpenDuplex(name string) (*ReadWriteCloser, error) {
- file, err := shm.Open(name, unix.O_RDWR, 0)
+ file, err := Open(name, unix.O_RDWR, 0)
if err != nil {
return nil, err
}
diff --git a/readwriter.go b/readwriter.go
index 2da3119..523a605 100644
--- a/readwriter.go
+++ b/readwriter.go
@@ -6,12 +6,11 @@
package shm
import (
- "golang.org/x/sys/unix"
"io"
"sync/atomic"
"unsafe"
- "github.com/tmthrgd/go-sem"
+ "golang.org/x/sys/unix"
)
const (
@@ -55,22 +54,6 @@
// Name returns the name of the shared memory.
func (rw *ReadWriteCloser) Name() string {
return rw.name
-}
-
-// Unlink removes the shared memory.
-//
-// It is the equivalent to calling Unlink(string) with
-// the same name as Create* or Open*.
-//
-// Taken from shm_unlink(3):
-// The operation of shm_unlink() is analogous to unlink(2): it removes a
-// shared memory object name, and, once all processes have unmapped the
-// object, de-allocates and destroys the contents of the associated memory
-// region. After a successful shm_unlink(), attempts to shm_open() an
-// object with the same name will fail (unless O_CREAT was specified, in
-// which case a new, distinct object is created).
-func (rw *ReadWriteCloser) Unlink() error {
- return Unlink(rw.name)
}
// Read
@@ -135,7 +118,7 @@
block = (*sharedBlock)(unsafe.Pointer(blocks + uintptr(uint64(blockIndex)*rw.fullBlockSize)))
if blockIndex == atomic.LoadUint32((*uint32)(&rw.readShared.WriteEnd)) {
- if err := ((*sem.Semaphore)(&rw.readShared.SemSignal)).Wait(); err != nil {
+ if err := ((*Semaphore)(&rw.readShared.SemSignal)).Wait(); err != nil {
return Buffer{}, err
}
@@ -187,7 +170,7 @@
atomic.CompareAndSwapUint32((*uint32)(&rw.readShared.ReadEnd), blockIndex, uint32(block.Next))
if uint32(block.Prev) == atomic.LoadUint32((*uint32)(&rw.readShared.WriteStart)) {
- if err := ((*sem.Semaphore)(&rw.readShared.SemAvail)).Post(); err != nil {
+ if err := ((*Semaphore)(&rw.readShared.SemAvail)).Post(); err != nil {
return err
}
}
@@ -258,7 +241,7 @@
block = (*sharedBlock)(unsafe.Pointer(blocks + uintptr(uint64(blockIndex)*rw.fullBlockSize)))
if uint32(block.Next) == atomic.LoadUint32((*uint32)(&rw.writeShared.ReadEnd)) {
- if err := ((*sem.Semaphore)(&rw.writeShared.SemAvail)).Wait(); err != nil {
+ if err := ((*Semaphore)(&rw.writeShared.SemAvail)).Wait(); err != nil {
return Buffer{}, err
}
@@ -313,7 +296,7 @@
atomic.CompareAndSwapUint32((*uint32)(&rw.writeShared.WriteEnd), blockIndex, uint32(block.Next))
if blockIndex == atomic.LoadUint32((*uint32)(&rw.writeShared.ReadStart)) {
- if err := ((*sem.Semaphore)(&rw.writeShared.SemSignal)).Post(); err != nil {
+ if err := ((*Semaphore)(&rw.writeShared.SemSignal)).Post(); err != nil {
return len(buf.Data), err
}
}
diff --git a/sem.go b/sem.go
new file mode 100644
index 0000000..ecc24a3
--- /dev/null
+++ b/sem.go
@@ -0,0 +1,114 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs sem_linux.go
+
+package shm
+
+import (
+ "sync/atomic"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/sys/unix"
+)
+
+type Semaphore [32]byte
+
+type newSem struct {
+ Value uint32
+ Private int32
+ NWaiters uint64
+}
+
+func New(value uint) (*Semaphore, error) {
+ sem := new(Semaphore)
+
+ if err := sem.Init(value); err != nil {
+ return nil, err
+ }
+
+ return sem, nil
+}
+
+func atomicDecrementIfPositive(mem *uint32) uint32 {
+ for {
+ if old := atomic.LoadUint32(mem); old == 0 || atomic.CompareAndSwapUint32(mem, old, old-1) {
+ return old
+ }
+ }
+}
+
+func (sem *Semaphore) Wait() error {
+ isem := (*newSem)(unsafe.Pointer(sem))
+
+ if atomicDecrementIfPositive(&isem.Value) > 0 {
+ return nil
+ }
+
+ atomic.AddUint64(&isem.NWaiters, 1)
+
+ for {
+ t := syscall.Timeval{3 /*sec*/, 0 /*usec*/}
+ if _, _, err := unix.Syscall6(unix.SYS_FUTEX, uintptr(unsafe.Pointer(&isem.Value)), uintptr(0x0), 0, uintptr(unsafe.Pointer(&t)), 0, 0); err != 0 && err != unix.EWOULDBLOCK {
+ atomic.AddUint64(&isem.NWaiters, ^uint64(0))
+ return err
+ }
+
+ if atomicDecrementIfPositive(&isem.Value) > 0 {
+ atomic.AddUint64(&isem.NWaiters, ^uint64(0))
+ return nil
+ }
+ }
+}
+
+func (sem *Semaphore) TryWait() error {
+ isem := (*newSem)(unsafe.Pointer(sem))
+
+ if atomicDecrementIfPositive(&isem.Value) > 0 {
+ return nil
+ }
+
+ return unix.EAGAIN
+}
+
+func (sem *Semaphore) Post() error {
+ isem := (*newSem)(unsafe.Pointer(sem))
+
+ for {
+ cur := atomic.LoadUint32(&isem.Value)
+
+ if cur == 0x7fffffff {
+ return unix.EOVERFLOW
+ }
+
+ if atomic.CompareAndSwapUint32(&isem.Value, cur, cur+1) {
+ break
+ }
+ }
+
+ if atomic.LoadUint64(&isem.NWaiters) <= 0 {
+ return nil
+ }
+
+ if _, _, err := unix.Syscall6(unix.SYS_FUTEX, uintptr(unsafe.Pointer(&isem.Value)), uintptr(0x1), 1, 0, 0, 0); err != 0 {
+ return err
+ }
+
+ return nil
+}
+
+func (sem *Semaphore) Init(value uint) error {
+ if value > 0x7fffffff {
+ return unix.EINVAL
+ }
+
+ isem := (*newSem)(unsafe.Pointer(sem))
+ isem.Value = uint32(value)
+ isem.Private = 0
+ isem.NWaiters = 0
+
+ return nil
+}
+
+func (sem *Semaphore) Destroy() error {
+ return nil
+}
diff --git a/shm.go b/shm.go
new file mode 100644
index 0000000..c65cea3
--- /dev/null
+++ b/shm.go
@@ -0,0 +1,83 @@
+// Copyright 2016 Tom Thorogood. All rights reserved.
+// Use of this source code is governed by a
+// Modified BSD License license that can be found in
+// the LICENSE file.
+
+// Package shm provides functions to open and unlink shared memory.
+package shm
+
+import (
+ "os"
+
+ "golang.org/x/sys/unix"
+)
+
+const devShm = "/dev/shm/"
+
+// Taken from shm_open(3):
+// shm_open() creates and opens a new, or opens an existing, POSIX shared
+// memory object. A POSIX shared memory object is in effect a handle which
+// can be used by unrelated processes to mmap(2) the same region of shared
+// memory. The shm_unlink() function performs the converse operation,
+// removing an object previously created by shm_open().
+//
+// The operation of shm_open() is analogous to that of open(2). name
+// specifies the shared memory object to be created or opened. For
+// portable use, a shared memory object should be identified by a name of
+// the form /somename; that is, a null-terminated string of up to NAME_MAX
+// (i.e., 255) characters consisting of an initial slash, followed by one
+// or more characters, none of which are slashes.
+func Open(name string, flag int, perm os.FileMode) (*os.File, error) {
+ fileName := name
+
+ for len(name) != 0 && name[0] == '/' {
+ name = name[1:]
+ }
+
+ if len(name) == 0 {
+ return nil, &os.PathError{Op: "open", Path: fileName, Err: unix.EINVAL}
+ }
+
+ o := uint32(perm.Perm())
+ if perm&os.ModeSetuid != 0 {
+ o |= unix.S_ISUID
+ }
+ if perm&os.ModeSetgid != 0 {
+ o |= unix.S_ISGID
+ }
+ if perm&os.ModeSticky != 0 {
+ o |= unix.S_ISVTX
+ }
+
+ fd, err := unix.Open(devShm+name, flag|unix.O_CLOEXEC, o)
+ if err != nil {
+ return nil, &os.PathError{Op: "open", Path: fileName, Err: err}
+ }
+
+ return os.NewFile(uintptr(fd), fileName), nil
+}
+
+// Taken from shm_unlink(3):
+// The operation of shm_unlink() is analogous to unlink(2): it removes a
+// shared memory object name, and, once all processes have unmapped the
+// object, de-allocates and destroys the contents of the associated memory
+// region. After a successful shm_unlink(), attempts to shm_open() an
+// object with the same name will fail (unless O_CREAT was specified, in
+// which case a new, distinct object is created).
+func Unlink(name string) error {
+ fileName := name
+
+ for len(name) != 0 && name[0] == '/' {
+ name = name[1:]
+ }
+
+ if len(name) == 0 {
+ return &os.PathError{Op: "unlink", Path: fileName, Err: unix.EINVAL}
+ }
+
+ if err := unix.Unlink(devShm + name); err != nil {
+ return &os.PathError{Op: "unlink", Path: fileName, Err: err}
+ }
+
+ return nil
+}
diff --git a/unlink.go b/unlink.go
deleted file mode 100644
index dbf252e..0000000
--- a/unlink.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2016 Tom Thorogood. All rights reserved.
-// Use of this source code is governed by a
-// Modified BSD License license that can be found in
-// the LICENSE file.
-
-package shm
-
-import "github.com/tmthrgd/go-shm"
-
-// Unlink removes the previously created blocker.
-//
-// Taken from shm_unlink(3):
-// The operation of shm_unlink() is analogous to unlink(2): it removes a
-// shared memory object name, and, once all processes have unmapped the
-// object, de-allocates and destroys the contents of the associated memory
-// region. After a successful shm_unlink(), attempts to shm_open() an
-// object with the same name will fail (unless O_CREAT was specified, in
-// which case a new, distinct object is created).
-func Unlink(name string) error {
- return shm.Unlink(name)
-}
--
Gitblit v1.8.0