From 3bd1f29975c0eaa6af8c99776b099faafbbfc250 Mon Sep 17 00:00:00 2001 From: zhangmeng <775834166@qq.com> Date: 星期一, 26 八月 2019 10:36:48 +0800 Subject: [PATCH] init copy from github --- net/listener.go | 53 +++ net/dialer.go | 53 +++ shared.go | 64 ++++ readwriter.go | 321 ++++++++++++++++++++ create.go | 162 ++++++++++ net/conn.go | 46 ++ shared_linux_386.go | 37 ++ shared_linux_amd64.go | 37 ++ unlink.go | 21 + open.go | 107 ++++++ shared_linux.go | 11 errors.go | 14 net/addr.go | 16 + 13 files changed, 942 insertions(+), 0 deletions(-) diff --git a/create.go b/create.go new file mode 100644 index 0000000..8fa3080 --- /dev/null +++ b/create.go @@ -0,0 +1,162 @@ +// 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 ( + "golang.org/x/sys/unix" + "os" + "sync/atomic" + "unsafe" + + "github.com/tmthrgd/go-sem" + "github.com/tmthrgd/go-shm" +) + +func CreateSimplex(name string, perm os.FileMode, blockCount, blockSize int) (*ReadWriteCloser, error) { + if blockSize&0x3f != 0 { + return nil, ErrNotMultipleOf64 + } + + file, err := shm.Open(name, unix.O_CREAT|unix.O_EXCL|unix.O_TRUNC|unix.O_RDWR, perm) + if err != nil { + return nil, err + } + + defer file.Close() + + fullBlockSize := blockHeaderSize + uint64(blockSize) + size := sharedHeaderSize + fullBlockSize*uint64(blockCount) + + if err = file.Truncate(int64(size)); err != nil { + return nil, err + } + + data, err := unix.Mmap(int(file.Fd()), 0, int(size), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED) + if err != nil { + return nil, err + } + + shared := (*sharedMem)(unsafe.Pointer(&data[0])) + + /* + * memset already set: + * shared.ReadStart, shared.ReadEnd = 0, 0 + * shared.WriteStart, shared.WriteEnd = 0, 0 + * shared.block[i].Size = 0 + * shared.block[i].DoneRead, shared.block[i].DoneWrite = 0, 0 + */ + *(*uint32)(&shared.BlockCount), *(*uint64)(&shared.BlockSize) = uint32(blockCount), uint64(blockSize) + + if err = ((*sem.Semaphore)(&shared.SemSignal)).Init(0); err != nil { + return nil, err + } + + if err = ((*sem.Semaphore)(&shared.SemAvail)).Init(0); err != nil { + return nil, err + } + + for i := uint32(0); i < uint32(blockCount); i++ { + block := (*sharedBlock)(unsafe.Pointer(&data[sharedHeaderSize+uint64(i)*fullBlockSize])) + + switch i { + case 0: + block.Next, *(*uint32)(&block.Prev) = 1, uint32(blockCount-1) + case uint32(blockCount - 1): + block.Next, *(*uint32)(&block.Prev) = 0, uint32(blockCount-2) + default: + *(*uint32)(&block.Next), *(*uint32)(&block.Prev) = i+1, i-1 + } + } + + atomic.StoreUint32((*uint32)(&shared.Version), version) + + return &ReadWriteCloser{ + name: name, + + data: data, + readShared: shared, + writeShared: shared, + size: size, + fullBlockSize: fullBlockSize, + + Flags: (*[len(shared.Flags)]uint32)(unsafe.Pointer(&shared.Flags[0])), + }, nil +} + +func CreateDuplex(name string, perm os.FileMode, blockCount, blockSize int) (*ReadWriteCloser, error) { + if blockSize&0x3f != 0 { + return nil, ErrNotMultipleOf64 + } + + file, err := shm.Open(name, unix.O_CREAT|unix.O_EXCL|unix.O_TRUNC|unix.O_RDWR, perm) + if err != nil { + return nil, err + } + + defer file.Close() + + fullBlockSize := blockHeaderSize + uint64(blockSize) + sharedSize := sharedHeaderSize + fullBlockSize*uint64(blockCount) + size := 2 * sharedSize + + if err = file.Truncate(int64(size)); err != nil { + return nil, err + } + + data, err := unix.Mmap(int(file.Fd()), 0, int(size), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED) + if err != nil { + return nil, err + } + + for i := uint64(0); i < 2; i++ { + shared := (*sharedMem)(unsafe.Pointer(&data[i*sharedSize])) + + /* + * memset already set: + * shared.ReadStart, shared.ReadEnd = 0, 0 + * shared.WriteStart, shared.WriteEnd = 0, 0 + * shared.Blocks[i].Size = 0 + * shared.Blocks[i].DoneRead, shared.Blocks[i].DoneWrite = 0, 0 + */ + *(*uint32)(&shared.BlockCount), *(*uint64)(&shared.BlockSize) = uint32(blockCount), uint64(blockSize) + + if err = ((*sem.Semaphore)(&shared.SemSignal)).Init(0); err != nil { + return nil, err + } + + if err = ((*sem.Semaphore)(&shared.SemAvail)).Init(0); err != nil { + return nil, err + } + + for j := uint32(0); j < uint32(blockCount); j++ { + block := (*sharedBlock)(unsafe.Pointer(&data[i*sharedSize+sharedHeaderSize+uint64(j)*fullBlockSize])) + + switch j { + case 0: + block.Next, *(*uint32)(&block.Prev) = 1, uint32(blockCount-1) + case uint32(blockCount - 1): + block.Next, *(*uint32)(&block.Prev) = 0, uint32(blockCount-2) + default: + *(*uint32)(&block.Next), *(*uint32)(&block.Prev) = j+1, j-1 + } + } + } + + readShared := (*sharedMem)(unsafe.Pointer(&data[0])) + atomic.StoreUint32((*uint32)(&readShared.Version), version) + + return &ReadWriteCloser{ + name: name, + + data: data, + readShared: readShared, + writeShared: (*sharedMem)(unsafe.Pointer(&data[sharedSize])), + size: size, + fullBlockSize: fullBlockSize, + + Flags: (*[len(readShared.Flags)]uint32)(unsafe.Pointer(&readShared.Flags[0])), + }, nil +} diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..9f2baf0 --- /dev/null +++ b/errors.go @@ -0,0 +1,14 @@ +// 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 "errors" + +var ( + ErrInvalidSharedMemory = errors.New("invalid shared memory") + ErrNotMultipleOf64 = errors.New("blockSize is not a multiple of 64") + ErrInvalidBuffer = errors.New("invalid buffer") +) diff --git a/net/addr.go b/net/addr.go new file mode 100644 index 0000000..4924376 --- /dev/null +++ b/net/addr.go @@ -0,0 +1,16 @@ +// 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 new file mode 100644 index 0000000..36a5e23 --- /dev/null +++ b/net/conn.go @@ -0,0 +1,46 @@ +// 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 new file mode 100644 index 0000000..1d3cefb --- /dev/null +++ b/net/dialer.go @@ -0,0 +1,53 @@ +// 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 new file mode 100644 index 0000000..4039490 --- /dev/null +++ b/net/listener.go @@ -0,0 +1,53 @@ +// 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 new file mode 100644 index 0000000..861bb76 --- /dev/null +++ b/open.go @@ -0,0 +1,107 @@ +// 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 ( + "golang.org/x/sys/unix" + "sync/atomic" + "unsafe" + + "github.com/tmthrgd/go-shm" +) + +func OpenSimplex(name string) (*ReadWriteCloser, error) { + file, err := shm.Open(name, unix.O_RDWR, 0) + if err != nil { + return nil, err + } + + defer file.Close() + + data, err := unix.Mmap(int(file.Fd()), 0, sharedHeaderSize, unix.PROT_READ, unix.MAP_SHARED) + if err != nil { + return nil, err + } + + shared := (*sharedMem)(unsafe.Pointer(&data[0])) + + if atomic.LoadUint32((*uint32)(&shared.Version)) != version { + return nil, ErrInvalidSharedMemory + } + + blockCount, blockSize := uint64(shared.BlockCount), uint64(shared.BlockSize) + + if err = unix.Munmap(data); err != nil { + return nil, err + } + + size := sharedHeaderSize + (blockHeaderSize+blockSize)*blockCount + + data, err = unix.Mmap(int(file.Fd()), 0, int(size), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED) + if err != nil { + return nil, err + } + + shared = (*sharedMem)(unsafe.Pointer(&data[0])) + return &ReadWriteCloser{ + name: name, + + data: data, + readShared: shared, + writeShared: shared, + size: size, + fullBlockSize: blockHeaderSize + blockSize, + + Flags: (*[len(shared.Flags)]uint32)(unsafe.Pointer(&shared.Flags[0])), + }, nil +} + +func OpenDuplex(name string) (*ReadWriteCloser, error) { + file, err := shm.Open(name, unix.O_RDWR, 0) + if err != nil { + return nil, err + } + + defer file.Close() + + data, err := unix.Mmap(int(file.Fd()), 0, sharedHeaderSize, unix.PROT_READ, unix.MAP_SHARED) + if err != nil { + return nil, err + } + + shared := (*sharedMem)(unsafe.Pointer(&data[0])) + + if atomic.LoadUint32((*uint32)(&shared.Version)) != version { + return nil, ErrInvalidSharedMemory + } + + blockCount, blockSize := uint64(shared.BlockCount), uint64(shared.BlockSize) + + if err = unix.Munmap(data); err != nil { + return nil, err + } + + sharedSize := sharedHeaderSize + (blockHeaderSize+blockSize)*blockCount + size := 2 * sharedSize + + data, err = unix.Mmap(int(file.Fd()), 0, int(size), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED) + if err != nil { + return nil, err + } + + writeShared := (*sharedMem)(unsafe.Pointer(&data[0])) + return &ReadWriteCloser{ + name: name, + + data: data, + readShared: (*sharedMem)(unsafe.Pointer(&data[sharedSize])), + writeShared: writeShared, + size: size, + fullBlockSize: blockHeaderSize + blockSize, + + Flags: (*[len(writeShared.Flags)]uint32)(unsafe.Pointer(&writeShared.Flags[0])), + }, nil +} diff --git a/readwriter.go b/readwriter.go new file mode 100644 index 0000000..2da3119 --- /dev/null +++ b/readwriter.go @@ -0,0 +1,321 @@ +// 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 ( + "golang.org/x/sys/unix" + "io" + "sync/atomic" + "unsafe" + + "github.com/tmthrgd/go-sem" +) + +const ( + eofFlagIndex = 0 + eofFlagMask = 0x01 +) + +type Buffer struct { + block *sharedBlock + write bool + + Data []byte + Flags *[blockFlagsSize]byte +} + +type ReadWriteCloser struct { + name string + + data []byte + readShared *sharedMem + writeShared *sharedMem + size uint64 + fullBlockSize uint64 + + // Must be accessed using atomic operations + Flags *[sharedFlagsSize]uint32 + + closed uint32 +} + +func (rw *ReadWriteCloser) Close() error { + if !atomic.CompareAndSwapUint32(&rw.closed, 0, 1) { + return nil + } + + // finish all sends before close! + + return unix.Munmap(rw.data) +} + +// 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 + +func (rw *ReadWriteCloser) Read(p []byte) (n int, err error) { + buf, err := rw.GetReadBuffer() + if err != nil { + return 0, err + } + + n = copy(p, buf.Data) + isEOF := buf.Flags[eofFlagIndex]&eofFlagMask != 0 + + if err = rw.SendReadBuffer(buf); err != nil { + return n, err + } + + if isEOF { + return n, io.EOF + } + + return n, nil +} + +func (rw *ReadWriteCloser) WriteTo(w io.Writer) (n int64, err error) { + for { + buf, err := rw.GetReadBuffer() + if err != nil { + return n, err + } + + nn, err := w.Write(buf.Data) + n += int64(nn) + + isEOF := buf.Flags[eofFlagIndex]&eofFlagMask != 0 + + if putErr := rw.SendReadBuffer(buf); putErr != nil { + return n, putErr + } + + if err != nil || isEOF { + return n, err + } + } +} + +func (rw *ReadWriteCloser) GetReadBuffer() (Buffer, error) { + if atomic.LoadUint32(&rw.closed) != 0 { + return Buffer{}, io.ErrClosedPipe + } + + var block *sharedBlock + + blocks := uintptr(unsafe.Pointer(rw.readShared)) + sharedHeaderSize + + for { + blockIndex := atomic.LoadUint32((*uint32)(&rw.readShared.ReadStart)) + if blockIndex > uint32(rw.readShared.BlockCount) { + return Buffer{}, ErrInvalidSharedMemory + } + + 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 { + return Buffer{}, err + } + + continue + } + + if atomic.CompareAndSwapUint32((*uint32)(&rw.readShared.ReadStart), blockIndex, uint32(block.Next)) { + break + } + } + + data := (*[1 << 30]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(block)) + blockHeaderSize)) + flags := (*[len(block.Flags)]byte)(unsafe.Pointer(&block.Flags[0])) + return Buffer{ + block: block, + + Data: data[:block.Size:rw.readShared.BlockSize], + Flags: flags, + }, nil +} + +func (rw *ReadWriteCloser) SendReadBuffer(buf Buffer) error { + if atomic.LoadUint32(&rw.closed) != 0 { + return io.ErrClosedPipe + } + + if buf.write { + return ErrInvalidBuffer + } + + block := buf.block + + atomic.StoreUint32((*uint32)(&block.DoneRead), 1) + + blocks := uintptr(unsafe.Pointer(rw.readShared)) + sharedHeaderSize + + for { + blockIndex := atomic.LoadUint32((*uint32)(&rw.readShared.ReadEnd)) + if blockIndex > uint32(rw.readShared.BlockCount) { + return ErrInvalidSharedMemory + } + + block = (*sharedBlock)(unsafe.Pointer(blocks + uintptr(uint64(blockIndex)*rw.fullBlockSize))) + + if !atomic.CompareAndSwapUint32((*uint32)(&block.DoneRead), 1, 0) { + return nil + } + + 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 { + return err + } + } + } +} + +// Write + +func (rw *ReadWriteCloser) Write(p []byte) (n int, err error) { + buf, err := rw.GetWriteBuffer() + if err != nil { + return 0, err + } + + n = copy(buf.Data[:cap(buf.Data)], p) + buf.Data = buf.Data[:n] + + buf.Flags[eofFlagIndex] |= eofFlagMask + + _, err = rw.SendWriteBuffer(buf) + return n, err +} + +func (rw *ReadWriteCloser) ReadFrom(r io.Reader) (n int64, err error) { + for { + buf, err := rw.GetWriteBuffer() + if err != nil { + return n, err + } + + nn, err := r.Read(buf.Data[:cap(buf.Data)]) + buf.Data = buf.Data[:nn] + n += int64(nn) + + if err == io.EOF { + buf.Flags[eofFlagIndex] |= eofFlagMask + } else { + buf.Flags[eofFlagIndex] &^= eofFlagMask + } + + if _, putErr := rw.SendWriteBuffer(buf); putErr != nil { + return n, err + } + + if err == io.EOF { + return n, nil + } else if err != nil { + return n, err + } + } +} + +func (rw *ReadWriteCloser) GetWriteBuffer() (Buffer, error) { + if atomic.LoadUint32(&rw.closed) != 0 { + return Buffer{}, io.ErrClosedPipe + } + + var block *sharedBlock + + blocks := uintptr(unsafe.Pointer(rw.writeShared)) + sharedHeaderSize + + for { + blockIndex := atomic.LoadUint32((*uint32)(&rw.writeShared.WriteStart)) + if blockIndex > uint32(rw.writeShared.BlockCount) { + return Buffer{}, ErrInvalidSharedMemory + } + + 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 { + return Buffer{}, err + } + + continue + } + + if atomic.CompareAndSwapUint32((*uint32)(&rw.writeShared.WriteStart), blockIndex, uint32(block.Next)) { + break + } + } + + data := (*[1 << 30]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(block)) + blockHeaderSize)) + flags := (*[len(block.Flags)]byte)(unsafe.Pointer(&block.Flags[0])) + return Buffer{ + block: block, + write: true, + + Data: data[:0:rw.writeShared.BlockSize], + Flags: flags, + }, nil +} + +func (rw *ReadWriteCloser) SendWriteBuffer(buf Buffer) (n int, err error) { + if atomic.LoadUint32(&rw.closed) != 0 { + return 0, io.ErrClosedPipe + } + + if !buf.write { + return 0, ErrInvalidBuffer + } + + block := buf.block + + *(*uint64)(&block.Size) = uint64(len(buf.Data)) + + atomic.StoreUint32((*uint32)(&block.DoneWrite), 1) + + blocks := uintptr(unsafe.Pointer(rw.writeShared)) + sharedHeaderSize + + for { + blockIndex := atomic.LoadUint32((*uint32)(&rw.writeShared.WriteEnd)) + if blockIndex > uint32(rw.writeShared.BlockCount) { + return len(buf.Data), ErrInvalidSharedMemory + } + + block = (*sharedBlock)(unsafe.Pointer(blocks + uintptr(uint64(blockIndex)*rw.fullBlockSize))) + + if !atomic.CompareAndSwapUint32((*uint32)(&block.DoneWrite), 1, 0) { + return len(buf.Data), nil + } + + 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 { + return len(buf.Data), err + } + } + } +} diff --git a/shared.go b/shared.go new file mode 100644 index 0000000..ad968ff --- /dev/null +++ b/shared.go @@ -0,0 +1,64 @@ +// 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. + +// +build !linux !386,!amd64 + +package shm + +/* +#include <stdint.h> // For (u)int*_t +#include <semaphore.h> // For sem_* + +typedef struct { + uint32_t Next; + uint32_t Prev; + + uint32_t DoneRead; + uint32_t DoneWrite; + + uint64_t Size; + + uint8_t Flags[(0x40-(2*2*sizeof(uint32_t)+sizeof(uint64_t))&0x3f)&0x3f]; + + uint8_t Data[]; +} shared_block_t; + +typedef struct { + uint32_t Version; + uint32_t __padding0; + + uint32_t BlockCount; + uint32_t __padding1; + + uint64_t BlockSize; + + uint32_t ReadStart; + uint32_t ReadEnd; + + uint32_t WriteStart; + uint32_t WriteEnd; + + sem_t SemSignal; + sem_t SemAvail; + + uint32_t Flags[((0x40-(4*2*sizeof(uint32_t)+sizeof(uint64_t)+2*sizeof(sem_t))&0x3f)&0x3f)/4]; + + shared_block_t Blocks[]; +} shared_mem_t; +*/ +import "C" + +type sharedBlock C.shared_block_t + +type sharedMem C.shared_mem_t + +const ( + sharedHeaderSize = C.sizeof_shared_mem_t + sharedFlagsSize = len(sharedMem{}.Flags) + blockHeaderSize = C.sizeof_shared_block_t + blockFlagsSize = len(sharedBlock{}.Flags) + + version = uint32((^uint(0)>>32)&0x80000000) | 0x00000001 +) diff --git a/shared_linux.go b/shared_linux.go new file mode 100644 index 0000000..85c356b --- /dev/null +++ b/shared_linux.go @@ -0,0 +1,11 @@ +// 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. + +// +build linux + +//go:generate sh -c "GOARCH=386 go tool cgo -godefs shared.go | gofmt > shared_linux_386.go" +//go:generate sh -c "GOARCH=amd64 go tool cgo -godefs shared.go | gofmt > shared_linux_amd64.go" + +package shm diff --git a/shared_linux_386.go b/shared_linux_386.go new file mode 100644 index 0000000..93ca12b --- /dev/null +++ b/shared_linux_386.go @@ -0,0 +1,37 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs shared.go + +package shm + +type sharedBlock struct { + Next uint32 + Prev uint32 + DoneRead uint32 + DoneWrite uint32 + Size uint64 + Flags [40]uint8 +} + +type sharedMem struct { + Version uint32 + X__padding0 uint32 + BlockCount uint32 + X__padding1 uint32 + BlockSize uint64 + ReadStart uint32 + ReadEnd uint32 + WriteStart uint32 + WriteEnd uint32 + SemSignal [16]byte + SemAvail [16]byte + Flags [14]uint32 +} + +const ( + sharedHeaderSize = 0x80 + sharedFlagsSize = len(sharedMem{}.Flags) + blockHeaderSize = 0x40 + blockFlagsSize = len(sharedBlock{}.Flags) + + version = uint32((^uint(0)>>32)&0x80000000) | 0x00000001 +) diff --git a/shared_linux_amd64.go b/shared_linux_amd64.go new file mode 100644 index 0000000..3774171 --- /dev/null +++ b/shared_linux_amd64.go @@ -0,0 +1,37 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs shared.go + +package shm + +type sharedBlock struct { + Next uint32 + Prev uint32 + DoneRead uint32 + DoneWrite uint32 + Size uint64 + Flags [40]uint8 +} + +type sharedMem struct { + Version uint32 + X__padding0 uint32 + BlockCount uint32 + X__padding1 uint32 + BlockSize uint64 + ReadStart uint32 + ReadEnd uint32 + WriteStart uint32 + WriteEnd uint32 + SemSignal [32]byte + SemAvail [32]byte + Flags [6]uint32 +} + +const ( + sharedHeaderSize = 0x80 + sharedFlagsSize = len(sharedMem{}.Flags) + blockHeaderSize = 0x40 + blockFlagsSize = len(sharedBlock{}.Flags) + + version = uint32((^uint(0)>>32)&0x80000000) | 0x00000001 +) diff --git a/unlink.go b/unlink.go new file mode 100644 index 0000000..dbf252e --- /dev/null +++ b/unlink.go @@ -0,0 +1,21 @@ +// 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