gvisor: convert ilist to ilist:generic_list

ilist:generic_list works faster (cl/240185278) and
the code looks cleaner without type casting.
PiperOrigin-RevId: 241381175
Change-Id: I8487ab1d73637b3e9733c253c56dce9e79f0d35f
This commit is contained in:
Andrei Vagin
2019-04-01 12:53:27 -07:00
committed by Shentubot
parent 0327931ca4
commit a4b34e2637
8 changed files with 66 additions and 33 deletions
+13 -1
View File
@@ -14,6 +14,7 @@ go_library(
"dirent_cache.go",
"dirent_list.go",
"dirent_state.go",
"event_list.go",
"file.go",
"file_operations.go",
"file_overlay.go",
@@ -46,7 +47,6 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/amutex",
"//pkg/ilist",
"//pkg/log",
"//pkg/metric",
"//pkg/p9",
@@ -83,6 +83,18 @@ go_template_instance(
},
)
go_template_instance(
name = "event_list",
out = "event_list.go",
package = "fs",
prefix = "event",
template = "//pkg/ilist:generic_list",
types = {
"Linker": "*Event",
"Element": "*Event",
},
)
go_test(
name = "fs_x_test",
size = "small",
+5 -9
View File
@@ -19,7 +19,6 @@ import (
"sync/atomic"
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
"gvisor.googlesource.com/gvisor/pkg/ilist"
"gvisor.googlesource.com/gvisor/pkg/sentry/arch"
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
"gvisor.googlesource.com/gvisor/pkg/sentry/memmap"
@@ -51,7 +50,7 @@ type Inotify struct {
evMu sync.Mutex `state:"nosave"`
// A list of pending events for this inotify instance. Protected by evMu.
events ilist.List
events eventList
// A scratch buffer, use to serialize inotify events. Use allocate this
// ahead of time and reuse performance. Protected by evMu.
@@ -143,9 +142,7 @@ func (i *Inotify) Read(ctx context.Context, _ *File, dst usermem.IOSequence, _ i
}
var writeLen int64
for e := i.events.Front(); e != nil; e = e.Next() {
event := e.(*Event)
for event := i.events.Front(); event != nil; event = event.Next() {
// Does the buffer have enough remaining space to hold the event we're
// about to write out?
if dst.NumBytes() < int64(event.sizeOf()) {
@@ -160,7 +157,7 @@ func (i *Inotify) Read(ctx context.Context, _ *File, dst usermem.IOSequence, _ i
// Linux always dequeues an available event as long as there's enough
// buffer space to copy it out, even if the copy below fails. Emulate
// this behaviour.
i.events.Remove(e)
i.events.Remove(event)
// Buffer has enough space, copy event to the read buffer.
n, err := event.CopyTo(ctx, i.scratch, dst)
@@ -197,8 +194,7 @@ func (i *Inotify) Ioctl(ctx context.Context, io usermem.IO, args arch.SyscallArg
defer i.evMu.Unlock()
var n uint32
for e := i.events.Front(); e != nil; e = e.Next() {
event := e.(*Event)
n += uint32(event.sizeOf())
n += uint32(e.sizeOf())
}
var buf [4]byte
usermem.ByteOrder.PutUint32(buf[:], n)
@@ -216,7 +212,7 @@ func (i *Inotify) queueEvent(ev *Event) {
// Check if we should coalesce the event we're about to queue with the last
// one currently in the queue. Events are coalesced if they are identical.
if last := i.events.Back(); last != nil {
if ev.equals(last.(*Event)) {
if ev.equals(last) {
// "Coalesce" the two events by simply not queuing the new one. We
// don't need to raise a waiter.EventIn notification because no new
// data is available for reading.
+1 -2
View File
@@ -18,7 +18,6 @@ import (
"bytes"
"fmt"
"gvisor.googlesource.com/gvisor/pkg/ilist"
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
)
@@ -31,7 +30,7 @@ const inotifyEventBaseSize = 16
//
// +stateify savable
type Event struct {
ilist.Entry
eventEntry
wd int32
mask uint32
+14 -1
View File
@@ -1,10 +1,24 @@
package(licenses = ["notice"])
load("//tools/go_generics:defs.bzl", "go_template_instance")
load("//tools/go_stateify:defs.bzl", "go_library", "go_test")
go_template_instance(
name = "buffer_list",
out = "buffer_list.go",
package = "pipe",
prefix = "buffer",
template = "//pkg/ilist:generic_list",
types = {
"Element": "*Buffer",
"Linker": "*Buffer",
},
)
go_library(
name = "pipe",
srcs = [
"buffer_list.go",
"buffers.go",
"device.go",
"node.go",
@@ -18,7 +32,6 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/amutex",
"//pkg/ilist",
"//pkg/sentry/arch",
"//pkg/sentry/context",
"//pkg/sentry/device",
+1 -5
View File
@@ -14,16 +14,12 @@
package pipe
import (
"gvisor.googlesource.com/gvisor/pkg/ilist"
)
// Buffer encapsulates a queueable byte buffer that can
// easily be truncated. It is designed only for use with pipes.
//
// +stateify savable
type Buffer struct {
ilist.Entry
bufferEntry
data []byte
}
+3 -5
View File
@@ -25,7 +25,6 @@ import (
"sync/atomic"
"syscall"
"gvisor.googlesource.com/gvisor/pkg/ilist"
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
"gvisor.googlesource.com/gvisor/pkg/sentry/fs"
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
@@ -51,7 +50,7 @@ type Pipe struct {
Dirent *fs.Dirent
// The buffered byte queue.
data ilist.List
data bufferList
// Max size of the pipe in bytes. When this max has been reached,
// writers will get EWOULDBLOCK.
@@ -170,13 +169,12 @@ func (p *Pipe) read(ctx context.Context, dst usermem.IOSequence) (int64, error)
return 0, syserror.ErrWouldBlock
}
var n int64
for b := p.data.Front(); b != nil; b = p.data.Front() {
buffer := b.(*Buffer)
for buffer := p.data.Front(); buffer != nil; buffer = p.data.Front() {
n0, err := dst.CopyOut(ctx, buffer.bytes())
n += int64(n0)
p.size -= n0
if buffer.truncate(n0) == 0 {
p.data.Remove(b)
p.data.Remove(buffer)
}
dst = dst.DropFirst(n0)
if dst.NumBytes() == 0 || err != nil {
+25 -2
View File
@@ -1,13 +1,28 @@
package(licenses = ["notice"])
load("//tools/go_generics:defs.bzl", "go_template_instance")
load("//tools/go_stateify:defs.bzl", "go_library", "go_test")
go_template_instance(
name = "waiter_list",
out = "waiter_list.go",
package = "waiter",
prefix = "waiter",
template = "//pkg/ilist:generic_list",
types = {
"Element": "*Entry",
"Linker": "*Entry",
},
)
go_library(
name = "waiter",
srcs = ["waiter.go"],
srcs = [
"waiter.go",
"waiter_list.go",
],
importpath = "gvisor.googlesource.com/gvisor/pkg/waiter",
visibility = ["//visibility:public"],
deps = ["//pkg/ilist"],
)
go_test(
@@ -18,3 +33,11 @@ go_test(
],
embed = [":waiter"],
)
filegroup(
name = "autogen",
srcs = [
"waiter_list.go",
],
visibility = ["//:sandbox"],
)
+4 -8
View File
@@ -59,8 +59,6 @@ package waiter
import (
"sync"
"gvisor.googlesource.com/gvisor/pkg/ilist"
)
// EventMask represents io events as used in the poll() syscall.
@@ -127,7 +125,7 @@ type Entry struct {
// The following fields are protected by the queue lock.
mask EventMask
ilist.Entry
waiterEntry
}
type channelCallback struct{}
@@ -162,7 +160,7 @@ func NewChannelEntry(c chan struct{}) (Entry, chan struct{}) {
//
// +stateify savable
type Queue struct {
list ilist.List `state:"zerovalue"`
list waiterList `state:"zerovalue"`
mu sync.RWMutex `state:"nosave"`
}
@@ -186,8 +184,7 @@ func (q *Queue) EventUnregister(e *Entry) {
// in common with the notification mask.
func (q *Queue) Notify(mask EventMask) {
q.mu.RLock()
for it := q.list.Front(); it != nil; it = it.Next() {
e := it.(*Entry)
for e := q.list.Front(); e != nil; e = e.Next() {
if mask&e.mask != 0 {
e.Callback.Callback(e)
}
@@ -201,8 +198,7 @@ func (q *Queue) Events() EventMask {
ret := EventMask(0)
q.mu.RLock()
for it := q.list.Front(); it != nil; it = it.Next() {
e := it.(*Entry)
for e := q.list.Front(); e != nil; e = e.Next() {
ret |= e.mask
}
q.mu.RUnlock()