From 363f2c392c58d54f7e4d1e38bac1dc3a71283335 Mon Sep 17 00:00:00 2001 From: Jason Hall Date: Tue, 19 Jan 2021 13:50:14 -0500 Subject: [PATCH] Derive cpuinfo as needed, instead of at init-time This changes platforms.Parse to hit /proc to look up CPU info only when it's needed, instead of in init(). This makes the package a bit easier for other packages to consume, especially clients that don't call platforms.Parse or need to lookup CPU info. Signed-off-by: Jason Hall --- platforms/cpuinfo.go | 19 ++++++++++++------- platforms/defaults.go | 2 +- platforms/defaults_test.go | 2 +- platforms/platforms.go | 4 ++-- platforms/platforms_test.go | 4 ++-- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/platforms/cpuinfo.go b/platforms/cpuinfo.go index 89c8706a4..4a7177e31 100644 --- a/platforms/cpuinfo.go +++ b/platforms/cpuinfo.go @@ -21,6 +21,7 @@ import ( "os" "runtime" "strings" + "sync" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/log" @@ -28,14 +29,18 @@ import ( ) // Present the ARM instruction set architecture, eg: v7, v8 -var cpuVariant string +// Don't use this value directly; call cpuVariant() instead. +var cpuVariantValue string -func init() { - if isArmArch(runtime.GOARCH) { - cpuVariant = getCPUVariant() - } else { - cpuVariant = "" - } +var cpuVariantOnce sync.Once + +func cpuVariant() string { + cpuVariantOnce.Do(func() { + if isArmArch(runtime.GOARCH) { + cpuVariantValue = getCPUVariant() + } + }) + return cpuVariantValue } // For Linux, the kernel has already detected the ABI, ISA and Features. diff --git a/platforms/defaults.go b/platforms/defaults.go index a14d80e58..076f29f82 100644 --- a/platforms/defaults.go +++ b/platforms/defaults.go @@ -33,6 +33,6 @@ func DefaultSpec() specs.Platform { OS: runtime.GOOS, Architecture: runtime.GOARCH, // The Variant field will be empty if arch != ARM. - Variant: cpuVariant, + Variant: cpuVariant(), } } diff --git a/platforms/defaults_test.go b/platforms/defaults_test.go index 6feaf56d2..62df5350d 100644 --- a/platforms/defaults_test.go +++ b/platforms/defaults_test.go @@ -28,7 +28,7 @@ func TestDefault(t *testing.T) { expected := specs.Platform{ OS: runtime.GOOS, Architecture: runtime.GOARCH, - Variant: cpuVariant, + Variant: cpuVariant(), } p := DefaultSpec() if !reflect.DeepEqual(p, expected) { diff --git a/platforms/platforms.go b/platforms/platforms.go index 77d3f184e..088bdea05 100644 --- a/platforms/platforms.go +++ b/platforms/platforms.go @@ -189,8 +189,8 @@ func Parse(specifier string) (specs.Platform, error) { if isKnownOS(p.OS) { // picks a default architecture p.Architecture = runtime.GOARCH - if p.Architecture == "arm" && cpuVariant != "v7" { - p.Variant = cpuVariant + if p.Architecture == "arm" && cpuVariant() != "v7" { + p.Variant = cpuVariant() } return p, nil diff --git a/platforms/platforms_test.go b/platforms/platforms_test.go index 4d7a9e8f1..66abc062d 100644 --- a/platforms/platforms_test.go +++ b/platforms/platforms_test.go @@ -31,8 +31,8 @@ func TestParseSelector(t *testing.T) { defaultVariant = "" ) - if defaultArch == "arm" && cpuVariant != "v7" { - defaultVariant = cpuVariant + if defaultArch == "arm" && cpuVariant() != "v7" { + defaultVariant = cpuVariant() } for _, testcase := range []struct {