Commit 430cccea authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

splice: empty splice.Pair by splicing into /dev/null

parent cfefa3d5
...@@ -35,3 +35,14 @@ func (p *Pair) WriteTo(fd uintptr, n int) (int, error) { ...@@ -35,3 +35,14 @@ func (p *Pair) WriteTo(fd uintptr, n int) (int, error) {
} }
return int(m), err return int(m), err
} }
const _SPLICE_F_NONBLOCK = 0x2
func (p *Pair) discard() {
_, err := syscall.Splice(p.r, nil, int(devNullFD), nil, int(p.size), _SPLICE_F_NONBLOCK)
if err == syscall.EAGAIN {
// all good.
} else if err != nil {
panic(err)
}
}
...@@ -6,7 +6,6 @@ package splice ...@@ -6,7 +6,6 @@ package splice
import ( import (
"sync" "sync"
"syscall"
) )
var splicePool *pairPool var splicePool *pairPool
...@@ -33,7 +32,7 @@ func Used() int { ...@@ -33,7 +32,7 @@ func Used() int {
return splicePool.used() return splicePool.used()
} }
// Return pipe pair to pool // Done returns the pipe pair to pool.
func Done(p *Pair) { func Done(p *Pair) {
splicePool.done(p) splicePool.done(p)
} }
...@@ -93,25 +92,8 @@ func (pp *pairPool) get() (p *Pair, err error) { ...@@ -93,25 +92,8 @@ func (pp *pairPool) get() (p *Pair, err error) {
return newSplicePair() return newSplicePair()
} }
var discardBuffer [32 * 1024]byte
func discardAll(fd int) {
buf := discardBuffer[:]
r := 0
for {
n, _ := syscall.Read(fd, buf)
if n > 0 {
r += n
}
if n < len(buf) {
break
}
}
}
func (pp *pairPool) done(p *Pair) { func (pp *pairPool) done(p *Pair) {
discardAll(p.r) p.discard()
pp.Lock() pp.Lock()
pp.usedCount-- pp.usedCount--
......
...@@ -30,6 +30,9 @@ func MaxPipeSize() int { ...@@ -30,6 +30,9 @@ func MaxPipeSize() int {
// Since Linux 2.6.11, the pipe capacity is 65536 bytes. // Since Linux 2.6.11, the pipe capacity is 65536 bytes.
const DefaultPipeSize = 16 * 4096 const DefaultPipeSize = 16 * 4096
// We empty pipes by splicing to /dev/null.
var devNullFD uintptr
func init() { func init() {
content, err := ioutil.ReadFile("/proc/sys/fs/pipe-max-size") content, err := ioutil.ReadFile("/proc/sys/fs/pipe-max-size")
if err != nil { if err != nil {
...@@ -48,6 +51,13 @@ func init() { ...@@ -48,6 +51,13 @@ func init() {
resizable = resizable && (errNo == 0) resizable = resizable && (errNo == 0)
r.Close() r.Close()
w.Close() w.Close()
fd, err := syscall.Open("/dev/null", os.O_WRONLY, 0)
if err != nil {
log.Panicf("splice: %v", err)
}
devNullFD = uintptr(fd)
} }
// copy & paste from syscall. // copy & paste from syscall.
......
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
func TestPairSize(t *testing.T) { func TestPairSize(t *testing.T) {
p, _ := Get() p, _ := Get()
defer Done(p) defer Done(p)
p.MaxGrow() p.MaxGrow()
b := make([]byte, p.Cap()+100) b := make([]byte, p.Cap()+100)
for i := range b { for i := range b {
...@@ -30,3 +31,20 @@ func TestPairSize(t *testing.T) { ...@@ -30,3 +31,20 @@ func TestPairSize(t *testing.T) {
} }
} }
func TestDiscard(t *testing.T) {
p, _ := Get()
defer Done(p)
if _, err := p.Write([]byte("hello")); err != nil {
t.Fatalf("Write: %v", err)
}
p.discard()
var b [1]byte
n, err := p.Read(b[:])
if n != -1 {
t.Fatalf("Read: got (%d, %v) want (-1, EAGAIN)", n, err)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment