From 5ff780891e229dbde00d9a37c2f8b6681e592fdb Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Thu, 6 Feb 2020 10:06:56 -0800 Subject: Move p9.pool to a separate package PiperOrigin-RevId: 293617493 --- pkg/p9/BUILD | 3 +-- pkg/p9/client.go | 9 ++++--- pkg/p9/pool.go | 68 --------------------------------------------------- pkg/p9/pool_test.go | 64 ------------------------------------------------ pkg/pool/BUILD | 25 +++++++++++++++++++ pkg/pool/pool.go | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ pkg/pool/pool_test.go | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 161 insertions(+), 138 deletions(-) delete mode 100644 pkg/p9/pool.go delete mode 100644 pkg/p9/pool_test.go create mode 100644 pkg/pool/BUILD create mode 100644 pkg/pool/pool.go create mode 100644 pkg/pool/pool_test.go diff --git a/pkg/p9/BUILD b/pkg/p9/BUILD index 4ccc1de86..8904afad9 100644 --- a/pkg/p9/BUILD +++ b/pkg/p9/BUILD @@ -16,7 +16,6 @@ go_library( "messages.go", "p9.go", "path_tree.go", - "pool.go", "server.go", "transport.go", "transport_flipcall.go", @@ -27,6 +26,7 @@ go_library( "//pkg/fdchannel", "//pkg/flipcall", "//pkg/log", + "//pkg/pool", "//pkg/sync", "//pkg/unet", "@org_golang_x_sys//unix:go_default_library", @@ -41,7 +41,6 @@ go_test( "client_test.go", "messages_test.go", "p9_test.go", - "pool_test.go", "transport_test.go", "version_test.go", ], diff --git a/pkg/p9/client.go b/pkg/p9/client.go index 4045e41fa..a6f493b82 100644 --- a/pkg/p9/client.go +++ b/pkg/p9/client.go @@ -22,6 +22,7 @@ import ( "golang.org/x/sys/unix" "gvisor.dev/gvisor/pkg/flipcall" "gvisor.dev/gvisor/pkg/log" + "gvisor.dev/gvisor/pkg/pool" "gvisor.dev/gvisor/pkg/sync" "gvisor.dev/gvisor/pkg/unet" ) @@ -74,10 +75,10 @@ type Client struct { socket *unet.Socket // tagPool is the collection of available tags. - tagPool pool + tagPool pool.Pool // fidPool is the collection of available fids. - fidPool pool + fidPool pool.Pool // messageSize is the maximum total size of a message. messageSize uint32 @@ -155,8 +156,8 @@ func NewClient(socket *unet.Socket, messageSize uint32, version string) (*Client } c := &Client{ socket: socket, - tagPool: pool{start: 1, limit: uint64(NoTag)}, - fidPool: pool{start: 1, limit: uint64(NoFID)}, + tagPool: pool.Pool{Start: 1, Limit: uint64(NoTag)}, + fidPool: pool.Pool{Start: 1, Limit: uint64(NoFID)}, pending: make(map[Tag]*response), recvr: make(chan bool, 1), messageSize: messageSize, diff --git a/pkg/p9/pool.go b/pkg/p9/pool.go deleted file mode 100644 index 2b14a5ce3..000000000 --- a/pkg/p9/pool.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package p9 - -import ( - "gvisor.dev/gvisor/pkg/sync" -) - -// pool is a simple allocator. -// -// It is used for both tags and FIDs. -type pool struct { - mu sync.Mutex - - // cache is the set of returned values. - cache []uint64 - - // start is the starting value (if needed). - start uint64 - - // max is the current maximum issued. - max uint64 - - // limit is the upper limit. - limit uint64 -} - -// Get gets a value from the pool. -func (p *pool) Get() (uint64, bool) { - p.mu.Lock() - defer p.mu.Unlock() - - // Anything cached? - if len(p.cache) > 0 { - v := p.cache[len(p.cache)-1] - p.cache = p.cache[:len(p.cache)-1] - return v, true - } - - // Over the limit? - if p.start == p.limit { - return 0, false - } - - // Generate a new value. - v := p.start - p.start++ - return v, true -} - -// Put returns a value to the pool. -func (p *pool) Put(v uint64) { - p.mu.Lock() - p.cache = append(p.cache, v) - p.mu.Unlock() -} diff --git a/pkg/p9/pool_test.go b/pkg/p9/pool_test.go deleted file mode 100644 index e4746b8da..000000000 --- a/pkg/p9/pool_test.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package p9 - -import ( - "testing" -) - -func TestPoolUnique(t *testing.T) { - p := pool{start: 1, limit: 3} - got := make(map[uint64]bool) - - for { - n, ok := p.Get() - if !ok { - break - } - - // Check unique. - if _, ok := got[n]; ok { - t.Errorf("pool spit out %v multiple times", n) - } - - // Record. - got[n] = true - } -} - -func TestExausted(t *testing.T) { - p := pool{start: 1, limit: 500} - for i := 0; i < 499; i++ { - _, ok := p.Get() - if !ok { - t.Fatalf("pool exhausted before 499 items") - } - } - - _, ok := p.Get() - if ok { - t.Errorf("pool not exhausted when it should be") - } -} - -func TestPoolRecycle(t *testing.T) { - p := pool{start: 1, limit: 500} - n1, _ := p.Get() - p.Put(n1) - n2, _ := p.Get() - if n1 != n2 { - t.Errorf("pool not recycling items") - } -} diff --git a/pkg/pool/BUILD b/pkg/pool/BUILD new file mode 100644 index 000000000..7b1c6b75b --- /dev/null +++ b/pkg/pool/BUILD @@ -0,0 +1,25 @@ +load("//tools:defs.bzl", "go_library", "go_test") + +package( + default_visibility = ["//visibility:public"], + licenses = ["notice"], +) + +go_library( + name = "pool", + srcs = [ + "pool.go", + ], + deps = [ + "//pkg/sync", + ], +) + +go_test( + name = "pool_test", + size = "small", + srcs = [ + "pool_test.go", + ], + library = ":pool", +) diff --git a/pkg/pool/pool.go b/pkg/pool/pool.go new file mode 100644 index 000000000..a1b2e0cfe --- /dev/null +++ b/pkg/pool/pool.go @@ -0,0 +1,66 @@ +// Copyright 2018 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pool + +import ( + "gvisor.dev/gvisor/pkg/sync" +) + +// Pool is a simple allocator. +type Pool struct { + mu sync.Mutex + + // cache is the set of returned values. + cache []uint64 + + // Start is the starting value (if needed). + Start uint64 + + // max is the current maximum issued. + max uint64 + + // Limit is the upper limit. + Limit uint64 +} + +// Get gets a value from the pool. +func (p *Pool) Get() (uint64, bool) { + p.mu.Lock() + defer p.mu.Unlock() + + // Anything cached? + if len(p.cache) > 0 { + v := p.cache[len(p.cache)-1] + p.cache = p.cache[:len(p.cache)-1] + return v, true + } + + // Over the limit? + if p.Start == p.Limit { + return 0, false + } + + // Generate a new value. + v := p.Start + p.Start++ + return v, true +} + +// Put returns a value to the pool. +func (p *Pool) Put(v uint64) { + p.mu.Lock() + p.cache = append(p.cache, v) + p.mu.Unlock() +} diff --git a/pkg/pool/pool_test.go b/pkg/pool/pool_test.go new file mode 100644 index 000000000..d928439c1 --- /dev/null +++ b/pkg/pool/pool_test.go @@ -0,0 +1,64 @@ +// Copyright 2018 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pool + +import ( + "testing" +) + +func TestPoolUnique(t *testing.T) { + p := Pool{Start: 1, Limit: 3} + got := make(map[uint64]bool) + + for { + n, ok := p.Get() + if !ok { + break + } + + // Check unique. + if _, ok := got[n]; ok { + t.Errorf("pool spit out %v multiple times", n) + } + + // Record. + got[n] = true + } +} + +func TestExausted(t *testing.T) { + p := Pool{Start: 1, Limit: 500} + for i := 0; i < 499; i++ { + _, ok := p.Get() + if !ok { + t.Fatalf("pool exhausted before 499 items") + } + } + + _, ok := p.Get() + if ok { + t.Errorf("pool not exhausted when it should be") + } +} + +func TestPoolRecycle(t *testing.T) { + p := Pool{Start: 1, Limit: 500} + n1, _ := p.Get() + p.Put(n1) + n2, _ := p.Get() + if n1 != n2 { + t.Errorf("pool not recycling items") + } +} -- cgit v1.2.3