mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
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:
+13
-1
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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"],
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user