From 29a7271f5da9fdb7b4a9a6c9ea61421ce6844a73 Mon Sep 17 00:00:00 2001 From: Ian Gudger Date: Thu, 13 Sep 2018 19:11:12 -0700 Subject: Plumb monotonic time to netstack Netstack needs to be portable, so this seems to be preferable to using raw system calls. PiperOrigin-RevId: 212917409 Change-Id: I7b2073e7db4b4bf75300717ca23aea4c15be944c --- pkg/sentry/kernel/kernel.go | 11 +++++++++++ pkg/tcpip/BUILD | 5 ++++- pkg/tcpip/tcpip.go | 11 +++-------- pkg/tcpip/time_unsafe.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 pkg/tcpip/time_unsafe.go diff --git a/pkg/sentry/kernel/kernel.go b/pkg/sentry/kernel/kernel.go index bc41c3963..316612b37 100644 --- a/pkg/sentry/kernel/kernel.go +++ b/pkg/sentry/kernel/kernel.go @@ -943,6 +943,8 @@ func (k *Kernel) SetExitError(err error) { } } +var _ tcpip.Clock = (*Kernel)(nil) + // NowNanoseconds implements tcpip.Clock.NowNanoseconds. func (k *Kernel) NowNanoseconds() int64 { now, err := k.timekeeper.GetTime(sentrytime.Realtime) @@ -952,6 +954,15 @@ func (k *Kernel) NowNanoseconds() int64 { return now } +// NowMonotonic implements tcpip.Clock.NowMonotonic. +func (k *Kernel) NowMonotonic() int64 { + now, err := k.timekeeper.GetTime(sentrytime.Monotonic) + if err != nil { + panic("Kernel.NowMonotonic: " + err.Error()) + } + return now +} + // SupervisorContext returns a Context with maximum privileges in k. It should // only be used by goroutines outside the control of the emulated kernel // defined by e. diff --git a/pkg/tcpip/BUILD b/pkg/tcpip/BUILD index 5153bd3b4..daff9a0a0 100644 --- a/pkg/tcpip/BUILD +++ b/pkg/tcpip/BUILD @@ -4,7 +4,10 @@ load("//tools/go_stateify:defs.bzl", "go_library", "go_test") go_library( name = "tcpip", - srcs = ["tcpip.go"], + srcs = [ + "tcpip.go", + "time_unsafe.go", + ], importpath = "gvisor.googlesource.com/gvisor/pkg/tcpip", visibility = ["//visibility:public"], deps = [ diff --git a/pkg/tcpip/tcpip.go b/pkg/tcpip/tcpip.go index 51360b11f..b1bd5117f 100644 --- a/pkg/tcpip/tcpip.go +++ b/pkg/tcpip/tcpip.go @@ -123,16 +123,11 @@ func (e ErrSaveRejection) Error() string { // time, but never for netstack internal timekeeping. type Clock interface { // NowNanoseconds returns the current real time as a number of - // nanoseconds since some epoch. + // nanoseconds since the Unix epoch. NowNanoseconds() int64 -} - -// StdClock implements Clock with the time package. -type StdClock struct{} -// NowNanoseconds implements Clock.NowNanoseconds. -func (*StdClock) NowNanoseconds() int64 { - return time.Now().UnixNano() + // NowMonotonic returns a monotonic time value. + NowMonotonic() int64 } // Address is a byte slice cast as a string that represents the address of a diff --git a/pkg/tcpip/time_unsafe.go b/pkg/tcpip/time_unsafe.go new file mode 100644 index 000000000..2102e9633 --- /dev/null +++ b/pkg/tcpip/time_unsafe.go @@ -0,0 +1,43 @@ +// Copyright 2018 Google Inc. +// +// 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. + +// +build go1.9 +// +build !go1.12 + +package tcpip + +import ( + _ "time" // Used with go:linkname. + _ "unsafe" // Required for go:linkname. +) + +// StdClock implements Clock with the time package. +type StdClock struct{} + +var _ Clock = (*StdClock)(nil) + +//go:linkname now time.now +func now() (sec int64, nsec int32, mono int64) + +// NowNanoseconds implements Clock.NowNanoseconds. +func (*StdClock) NowNanoseconds() int64 { + sec, nsec, _ := now() + return sec*1e9 + int64(nsec) +} + +// NowMonotonic implements Clock.NowMonotonic. +func (*StdClock) NowMonotonic() int64 { + _, _, mono := now() + return mono +} -- cgit v1.2.3