mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Move tcpip.Clock impl to Timekeeper
...and pass it explicitly.
This reverts commit b63e61828d.
PiperOrigin-RevId: 380039167
This commit is contained in:
committed by
gVisor bot
parent
0f5c1f5eaf
commit
3cf1644a3b
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user