Move tcpip.Clock impl to Timekeeper

...and pass it explicitly.

This reverts commit b63e61828d.

PiperOrigin-RevId: 380039167
This commit is contained in:
Tamir Duberstein
2021-06-17 14:02:05 -07:00
committed by gVisor bot
parent 0f5c1f5eaf
commit 3cf1644a3b
7 changed files with 68 additions and 67 deletions
+2 -5
View File
@@ -80,12 +80,8 @@ func Boot() (*kernel.Kernel, error) {
}
// Create timekeeper.
tk, err := kernel.NewTimekeeper(k, vdso.ParamPage.FileRange())
if err != nil {
return nil, fmt.Errorf("creating timekeeper: %v", err)
}
tk := kernel.NewTimekeeper(k, vdso.ParamPage.FileRange())
tk.SetClocks(time.NewCalibratedClocks())
k.SetTimekeeper(tk)
creds := auth.NewRootCredentials(auth.NewRootUserNamespace())
@@ -94,6 +90,7 @@ func Boot() (*kernel.Kernel, error) {
if err = k.Init(kernel.InitKernelArgs{
ApplicationCores: uint(runtime.GOMAXPROCS(-1)),
FeatureSet: cpuid.HostFeatureSet(),
Timekeeper: tk,
RootUserNamespace: creds.UserNamespace,
Vdso: vdso,
RootUTSNamespace: kernel.NewUTSNamespace("hostname", "domain", creds.UserNamespace),
+20 -49
View File
@@ -143,12 +143,6 @@ type Kernel struct {
// to CreateProcess, and is protected by extMu.
globalInit *ThreadGroup
// realtimeClock is a ktime.Clock based on timekeeper's Realtime.
realtimeClock *timekeeperClock
// monotonicClock is a ktime.Clock based on timekeeper's Monotonic.
monotonicClock *timekeeperClock
// syslog is the kernel log.
syslog syslog
@@ -306,6 +300,9 @@ type InitKernelArgs struct {
// FeatureSet is the emulated CPU feature set.
FeatureSet *cpuid.FeatureSet
// Timekeeper manages time for all tasks in the system.
Timekeeper *Timekeeper
// RootUserNamespace is the root user namespace.
RootUserNamespace *auth.UserNamespace
@@ -345,24 +342,18 @@ type InitKernelArgs struct {
PIDNamespace *PIDNamespace
}
// SetTimekeeper sets Kernel.timekeeper. SetTimekeeper must be called before
// Init.
func (k *Kernel) SetTimekeeper(tk *Timekeeper) {
k.timekeeper = tk
}
// Init initialize the Kernel with no tasks.
//
// Callers must manually set Kernel.Platform and call Kernel.SetMemoryFile
// and Kernel.SetTimekeeper before calling Init.
// before calling Init.
func (k *Kernel) Init(args InitKernelArgs) error {
if args.FeatureSet == nil {
return fmt.Errorf("args.FeatureSet is nil")
}
if k.timekeeper == nil {
return fmt.Errorf("timekeeper is nil")
if args.Timekeeper == nil {
return fmt.Errorf("args.Timekeeper is nil")
}
if k.timekeeper.clocks == nil {
if args.Timekeeper.clocks == nil {
return fmt.Errorf("must call Timekeeper.SetClocks() before Kernel.Init()")
}
if args.RootUserNamespace == nil {
@@ -373,6 +364,7 @@ func (k *Kernel) Init(args InitKernelArgs) error {
}
k.featureSet = args.FeatureSet
k.timekeeper = args.Timekeeper
k.tasks = newTaskSet(args.PIDNamespace)
k.rootUserNamespace = args.RootUserNamespace
k.rootUTSNamespace = args.RootUTSNamespace
@@ -397,8 +389,6 @@ func (k *Kernel) Init(args InitKernelArgs) error {
}
k.extraAuxv = args.ExtraAuxv
k.vdso = args.Vdso
k.realtimeClock = &timekeeperClock{tk: k.timekeeper, c: sentrytime.Realtime}
k.monotonicClock = &timekeeperClock{tk: k.timekeeper, c: sentrytime.Monotonic}
k.futexes = futex.NewManager()
k.netlinkPorts = port.New()
k.ptraceExceptions = make(map[*Task]*Task)
@@ -531,6 +521,8 @@ func (k *Kernel) SaveTo(ctx context.Context, w wire.Writer) error {
}
log.Infof("CPUID save took [%s].", time.Since(cpuidStart))
// Save the timekeeper's state.
// Save the kernel state.
kernelStart := time.Now()
stats, err := state.Save(ctx, w, k)
@@ -675,7 +667,7 @@ func (k *Kernel) invalidateUnsavableMappings(ctx context.Context) error {
}
// LoadFrom returns a new Kernel loaded from args.
func (k *Kernel) LoadFrom(ctx context.Context, r wire.Reader, net inet.Stack, clocks sentrytime.Clocks, vfsOpts *vfs.CompleteRestoreOptions) error {
func (k *Kernel) LoadFrom(ctx context.Context, r wire.Reader, timeReady chan struct{}, net inet.Stack, clocks sentrytime.Clocks, vfsOpts *vfs.CompleteRestoreOptions) error {
loadStart := time.Now()
initAppCores := k.applicationCores
@@ -722,6 +714,11 @@ func (k *Kernel) LoadFrom(ctx context.Context, r wire.Reader, net inet.Stack, cl
log.Infof("Overall load took [%s]", time.Since(loadStart))
k.Timekeeper().SetClocks(clocks)
if timeReady != nil {
close(timeReady)
}
if net != nil {
net.Resume()
}
@@ -1103,7 +1100,7 @@ func (k *Kernel) Start() error {
}
k.started = true
k.cpuClockTicker = ktime.NewTimer(k.monotonicClock, newKernelCPUClockTicker(k))
k.cpuClockTicker = ktime.NewTimer(k.timekeeper.monotonicClock, newKernelCPUClockTicker(k))
k.cpuClockTicker.Swap(ktime.Setting{
Enabled: true,
Period: linux.ClockTick,
@@ -1258,7 +1255,7 @@ func (k *Kernel) incRunningTasks() {
// These cause very different value of cpuClock. But again, since
// nothing was running while the ticker was disabled, those differences
// don't matter.
setting, exp := k.cpuClockTickerSetting.At(k.monotonicClock.Now())
setting, exp := k.cpuClockTickerSetting.At(k.timekeeper.monotonicClock.Now())
if exp > 0 {
atomic.AddUint64(&k.cpuClock, exp)
}
@@ -1468,12 +1465,12 @@ func (k *Kernel) ApplicationCores() uint {
// RealtimeClock returns the application CLOCK_REALTIME clock.
func (k *Kernel) RealtimeClock() ktime.Clock {
return k.realtimeClock
return k.timekeeper.realtimeClock
}
// MonotonicClock returns the application CLOCK_MONOTONIC clock.
func (k *Kernel) MonotonicClock() ktime.Clock {
return k.monotonicClock
return k.timekeeper.monotonicClock
}
// CPUClockNow returns the current value of k.cpuClock.
@@ -1553,32 +1550,6 @@ func (k *Kernel) SetSaveError(err error) {
}
}
var _ tcpip.Clock = (*Kernel)(nil)
// Now implements tcpip.Clock.NowNanoseconds.
func (k *Kernel) Now() time.Time {
nsec, err := k.timekeeper.GetTime(sentrytime.Realtime)
if err != nil {
panic("timekeeper.GetTime(sentrytime.Realtime): " + err.Error())
}
return time.Unix(0, nsec)
}
// NowMonotonic implements tcpip.Clock.NowMonotonic.
func (k *Kernel) NowMonotonic() tcpip.MonotonicTime {
nsec, err := k.timekeeper.GetTime(sentrytime.Monotonic)
if err != nil {
panic("timekeeper.GetTime(sentrytime.Monotonic): " + err.Error())
}
var mt tcpip.MonotonicTime
return mt.Add(time.Duration(nsec) * time.Nanosecond)
}
// AfterFunc implements tcpip.Clock.AfterFunc.
func (k *Kernel) AfterFunc(d time.Duration, f func()) tcpip.Timer {
return ktime.TcpipAfterFunc(k.realtimeClock, d, f)
}
// SetMemoryFile sets Kernel.mf. SetMemoryFile must be called before Init or
// LoadFrom.
func (k *Kernel) SetMemoryFile(mf *pgalloc.MemoryFile) {
+1 -1
View File
@@ -278,7 +278,7 @@ func (k *Kernel) NewThreadGroup(mntns *fs.MountNamespace, pidns *PIDNamespace, s
limits: limits,
mounts: mntns,
}
tg.itimerRealTimer = ktime.NewTimer(k.monotonicClock, &itimerRealListener{tg: tg})
tg.itimerRealTimer = ktime.NewTimer(k.timekeeper.monotonicClock, &itimerRealListener{tg: tg})
tg.timers = make(map[linux.TimerID]*IntervalTimer)
tg.oldRSeqCritical.Store(&OldRSeqCriticalRegion{})
return tg
+39 -3
View File
@@ -25,6 +25,7 @@ import (
"gvisor.dev/gvisor/pkg/sentry/pgalloc"
sentrytime "gvisor.dev/gvisor/pkg/sentry/time"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/tcpip"
)
// Timekeeper manages all of the kernel clocks.
@@ -39,6 +40,12 @@ type Timekeeper struct {
// It is set only once, by SetClocks.
clocks sentrytime.Clocks `state:"nosave"`
// realtimeClock is a ktime.Clock based on timekeeper's Realtime.
realtimeClock *timekeeperClock
// monotonicClock is a ktime.Clock based on timekeeper's Monotonic.
monotonicClock *timekeeperClock
// bootTime is the realtime when the system "booted". i.e., when
// SetClocks was called in the initial (not restored) run.
bootTime ktime.Time
@@ -90,10 +97,13 @@ type Timekeeper struct {
// NewTimekeeper does not take ownership of paramPage.
//
// SetClocks must be called on the returned Timekeeper before it is usable.
func NewTimekeeper(mfp pgalloc.MemoryFileProvider, paramPage memmap.FileRange) (*Timekeeper, error) {
return &Timekeeper{
func NewTimekeeper(mfp pgalloc.MemoryFileProvider, paramPage memmap.FileRange) *Timekeeper {
t := Timekeeper{
params: NewVDSOParamPage(mfp, paramPage),
}, nil
}
t.realtimeClock = &timekeeperClock{tk: &t, c: sentrytime.Realtime}
t.monotonicClock = &timekeeperClock{tk: &t, c: sentrytime.Monotonic}
return &t
}
// SetClocks the backing clock source.
@@ -167,6 +177,32 @@ func (t *Timekeeper) SetClocks(c sentrytime.Clocks) {
}
}
var _ tcpip.Clock = (*Timekeeper)(nil)
// Now implements tcpip.Clock.
func (t *Timekeeper) Now() time.Time {
nsec, err := t.GetTime(sentrytime.Realtime)
if err != nil {
panic("timekeeper.GetTime(sentrytime.Realtime): " + err.Error())
}
return time.Unix(0, nsec)
}
// NowMonotonic implements tcpip.Clock.
func (t *Timekeeper) NowMonotonic() tcpip.MonotonicTime {
nsec, err := t.GetTime(sentrytime.Monotonic)
if err != nil {
panic("timekeeper.GetTime(sentrytime.Monotonic): " + err.Error())
}
var mt tcpip.MonotonicTime
return mt.Add(time.Duration(nsec) * time.Nanosecond)
}
// AfterFunc implements tcpip.Clock.
func (t *Timekeeper) AfterFunc(d time.Duration, f func()) tcpip.Timer {
return ktime.TcpipAfterFunc(t.realtimeClock, d, f)
}
// startUpdater starts an update goroutine that keeps the clocks updated.
//
// mu must be held.
+2 -2
View File
@@ -110,7 +110,7 @@ type LoadOpts struct {
}
// Load loads the given kernel, setting the provided platform and stack.
func (opts LoadOpts) Load(ctx context.Context, k *kernel.Kernel, n inet.Stack, clocks time.Clocks, vfsOpts *vfs.CompleteRestoreOptions) error {
func (opts LoadOpts) Load(ctx context.Context, k *kernel.Kernel, timeReady chan struct{}, n inet.Stack, clocks time.Clocks, vfsOpts *vfs.CompleteRestoreOptions) error {
// Open the file.
r, m, err := statefile.NewReader(opts.Source, opts.Key)
if err != nil {
@@ -120,5 +120,5 @@ func (opts LoadOpts) Load(ctx context.Context, k *kernel.Kernel, n inet.Stack, c
previousMetadata = m
// Restore the Kernel object graph.
return k.LoadFrom(ctx, r, n, clocks, vfsOpts)
return k.LoadFrom(ctx, r, timeReady, n, clocks, vfsOpts)
}
+1 -1
View File
@@ -439,7 +439,7 @@ func (cm *containerManager) Restore(o *RestoreOpts, _ *struct{}) error {
// Load the state.
loadOpts := state.LoadOpts{Source: specFile}
if err := loadOpts.Load(ctx, k, networkStack, time.NewCalibratedClocks(), &vfs.CompleteRestoreOptions{}); err != nil {
if err := loadOpts.Load(ctx, k, nil, networkStack, time.NewCalibratedClocks(), &vfs.CompleteRestoreOptions{}); err != nil {
return err
}
+3 -6
View File
@@ -278,19 +278,15 @@ func New(args Args) (*Loader, error) {
}
// Create timekeeper.
tk, err := kernel.NewTimekeeper(k, vdso.ParamPage.FileRange())
if err != nil {
return nil, fmt.Errorf("creating timekeeper: %w", err)
}
tk := kernel.NewTimekeeper(k, vdso.ParamPage.FileRange())
tk.SetClocks(time.NewCalibratedClocks())
k.SetTimekeeper(tk)
if err := enableStrace(args.Conf); err != nil {
return nil, fmt.Errorf("enabling strace: %w", err)
}
// Create root network namespace/stack.
netns, err := newRootNetworkNamespace(args.Conf, k, k)
netns, err := newRootNetworkNamespace(args.Conf, tk, k)
if err != nil {
return nil, fmt.Errorf("creating network: %w", err)
}
@@ -332,6 +328,7 @@ func New(args Args) (*Loader, error) {
// to createVFS in order to mount (among other things) procfs.
if err = k.Init(kernel.InitKernelArgs{
FeatureSet: cpuid.HostFeatureSet(),
Timekeeper: tk,
RootUserNamespace: creds.UserNamespace,
RootNetworkNamespace: netns,
ApplicationCores: uint(args.NumCPU),