github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/sentry/kernel/time/time.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package time defines the Timer type, which provides a periodic timer that 16 // works by sampling a user-provided clock. 17 package time 18 19 import ( 20 "fmt" 21 "math" 22 "time" 23 24 "github.com/MerlinKodo/gvisor/pkg/abi/linux" 25 "github.com/MerlinKodo/gvisor/pkg/errors/linuxerr" 26 "github.com/MerlinKodo/gvisor/pkg/sync" 27 "github.com/MerlinKodo/gvisor/pkg/waiter" 28 ) 29 30 // Events that may be generated by a Clock. 31 const ( 32 // ClockEventSet occurs when a Clock undergoes a discontinuous change. 33 ClockEventSet waiter.EventMask = 1 << iota 34 35 // ClockEventRateIncrease occurs when the rate at which a Clock advances 36 // increases significantly, such that values returned by previous calls to 37 // Clock.WallTimeUntil may be too large. 38 ClockEventRateIncrease 39 ) 40 41 // Time represents an instant in time with nanosecond precision. 42 // 43 // Time may represent time with respect to any clock and may not have any 44 // meaning in the real world. 45 // 46 // +stateify savable 47 type Time struct { 48 ns int64 49 } 50 51 var ( 52 // MinTime is the zero time instant, the lowest possible time that can 53 // be represented by Time. 54 MinTime = Time{ns: math.MinInt64} 55 56 // MaxTime is the highest possible time that can be represented by 57 // Time. 58 MaxTime = Time{ns: math.MaxInt64} 59 60 // ZeroTime represents the zero time in an unspecified Clock's domain. 61 ZeroTime = Time{ns: 0} 62 ) 63 64 const ( 65 // MinDuration is the minimum duration representable by time.Duration. 66 MinDuration = time.Duration(math.MinInt64) 67 68 // MaxDuration is the maximum duration representable by time.Duration. 69 MaxDuration = time.Duration(math.MaxInt64) 70 ) 71 72 // FromNanoseconds returns a Time representing the point ns nanoseconds after 73 // an unspecified Clock's zero time. 74 func FromNanoseconds(ns int64) Time { 75 return Time{ns} 76 } 77 78 // FromSeconds returns a Time representing the point s seconds after an 79 // unspecified Clock's zero time. 80 func FromSeconds(s int64) Time { 81 if s > math.MaxInt64/time.Second.Nanoseconds() { 82 return MaxTime 83 } 84 return Time{s * 1e9} 85 } 86 87 // FromUnix converts from Unix seconds and nanoseconds to Time, assuming a real 88 // time Unix clock domain. 89 func FromUnix(s int64, ns int64) Time { 90 if s > math.MaxInt64/time.Second.Nanoseconds() { 91 return MaxTime 92 } 93 t := s * 1e9 94 if t > math.MaxInt64-ns { 95 return MaxTime 96 } 97 return Time{t + ns} 98 } 99 100 // FromTimespec converts from Linux Timespec to Time. 101 func FromTimespec(ts linux.Timespec) Time { 102 return Time{ts.ToNsecCapped()} 103 } 104 105 // FromTimeval converts a Linux Timeval to Time. 106 func FromTimeval(tv linux.Timeval) Time { 107 return Time{tv.ToNsecCapped()} 108 } 109 110 // Nanoseconds returns nanoseconds elapsed since the zero time in t's Clock 111 // domain. If t represents walltime, this is nanoseconds since the Unix epoch. 112 func (t Time) Nanoseconds() int64 { 113 return t.ns 114 } 115 116 // Microseconds returns microseconds elapsed since the zero time in t's Clock 117 // domain. If t represents walltime, this is microseconds since the Unix epoch. 118 func (t Time) Microseconds() int64 { 119 return t.ns / 1000 120 } 121 122 // Seconds returns seconds elapsed since the zero time in t's Clock domain. If 123 // t represents walltime, this is seconds since Unix epoch. 124 func (t Time) Seconds() int64 { 125 return t.Nanoseconds() / time.Second.Nanoseconds() 126 } 127 128 // Timespec converts Time to a Linux timespec. 129 func (t Time) Timespec() linux.Timespec { 130 return linux.NsecToTimespec(t.Nanoseconds()) 131 } 132 133 // Unix returns the (seconds, nanoseconds) representation of t such that 134 // seconds*1e9 + nanoseconds = t. 135 func (t Time) Unix() (s int64, ns int64) { 136 s = t.ns / 1e9 137 ns = t.ns % 1e9 138 return 139 } 140 141 // TimeT converts Time to a Linux time_t. 142 func (t Time) TimeT() linux.TimeT { 143 return linux.NsecToTimeT(t.Nanoseconds()) 144 } 145 146 // Timeval converts Time to a Linux timeval. 147 func (t Time) Timeval() linux.Timeval { 148 return linux.NsecToTimeval(t.Nanoseconds()) 149 } 150 151 // StatxTimestamp converts Time to a Linux statx_timestamp. 152 func (t Time) StatxTimestamp() linux.StatxTimestamp { 153 return linux.NsecToStatxTimestamp(t.Nanoseconds()) 154 } 155 156 // Add adds the duration of d to t. 157 func (t Time) Add(d time.Duration) Time { 158 if t.ns > 0 && d.Nanoseconds() > math.MaxInt64-int64(t.ns) { 159 return MaxTime 160 } 161 if t.ns < 0 && d.Nanoseconds() < math.MinInt64-int64(t.ns) { 162 return MinTime 163 } 164 return Time{int64(t.ns) + d.Nanoseconds()} 165 } 166 167 // AddTime adds the duration of u to t. 168 func (t Time) AddTime(u Time) Time { 169 return t.Add(time.Duration(u.ns)) 170 } 171 172 // Equal reports whether the two times represent the same instant in time. 173 func (t Time) Equal(u Time) bool { 174 return t.ns == u.ns 175 } 176 177 // Before reports whether the instant t is before the instant u. 178 func (t Time) Before(u Time) bool { 179 return t.ns < u.ns 180 } 181 182 // After reports whether the instant t is after the instant u. 183 func (t Time) After(u Time) bool { 184 return t.ns > u.ns 185 } 186 187 // Sub returns the duration of t - u. 188 // 189 // N.B. This measure may not make sense for every Time returned by ktime.Clock. 190 // Callers who need wall time duration can use ktime.Clock.WallTimeUntil to 191 // estimate that wall time. 192 func (t Time) Sub(u Time) time.Duration { 193 dur := time.Duration(int64(t.ns)-int64(u.ns)) * time.Nanosecond 194 switch { 195 case u.Add(dur).Equal(t): 196 return dur 197 case t.Before(u): 198 return MinDuration 199 default: 200 return MaxDuration 201 } 202 } 203 204 // IsMin returns whether t represents the lowest possible time instant. 205 func (t Time) IsMin() bool { 206 return t == MinTime 207 } 208 209 // IsZero returns whether t represents the zero time instant in t's Clock domain. 210 func (t Time) IsZero() bool { 211 return t == ZeroTime 212 } 213 214 // String returns the time represented in nanoseconds as a string. 215 func (t Time) String() string { 216 return fmt.Sprintf("%dns", t.Nanoseconds()) 217 } 218 219 // A Clock is an abstract time source. 220 type Clock interface { 221 // Now returns the current time in nanoseconds according to the Clock. 222 Now() Time 223 224 // WallTimeUntil returns the estimated wall time until Now will return a 225 // value greater than or equal to t, given that a recent call to Now 226 // returned now. If t has already passed, WallTimeUntil may return 0 or a 227 // negative value. 228 // 229 // WallTimeUntil must be abstract to support Clocks that do not represent 230 // wall time (e.g. thread group execution timers). Clocks that represent 231 // wall times may embed the WallRateClock type to obtain an appropriate 232 // trivial implementation of WallTimeUntil. 233 // 234 // WallTimeUntil is used to determine when associated Timers should next 235 // check for expirations. Returning too small a value may result in 236 // spurious Timer goroutine wakeups, while returning too large a value may 237 // result in late expirations. Implementations should usually err on the 238 // side of underestimating. 239 WallTimeUntil(t, now Time) time.Duration 240 241 // Waitable methods may be used to subscribe to Clock events. Waiters will 242 // not be preserved by Save and must be re-established during restore. 243 // 244 // Since Clock events are transient, implementations of 245 // waiter.Waitable.Readiness should return 0. 246 waiter.Waitable 247 } 248 249 // WallRateClock implements Clock.WallTimeUntil for Clocks that elapse at the 250 // same rate as wall time. 251 type WallRateClock struct{} 252 253 // WallTimeUntil implements Clock.WallTimeUntil. 254 func (*WallRateClock) WallTimeUntil(t, now Time) time.Duration { 255 return t.Sub(now) 256 } 257 258 // NoClockEvents implements waiter.Waitable for Clocks that do not generate 259 // events. 260 type NoClockEvents struct{} 261 262 // Readiness implements waiter.Waitable.Readiness. 263 func (*NoClockEvents) Readiness(mask waiter.EventMask) waiter.EventMask { 264 return 0 265 } 266 267 // EventRegister implements waiter.Waitable.EventRegister. 268 func (*NoClockEvents) EventRegister(e *waiter.Entry) error { 269 return nil 270 } 271 272 // EventUnregister implements waiter.Waitable.EventUnregister. 273 func (*NoClockEvents) EventUnregister(e *waiter.Entry) { 274 } 275 276 // ClockEventsQueue implements waiter.Waitable by wrapping waiter.Queue and 277 // defining waiter.Waitable.Readiness as required by Clock. 278 type ClockEventsQueue struct { 279 waiter.Queue 280 } 281 282 // EventRegister implements waiter.Waitable. 283 func (c *ClockEventsQueue) EventRegister(e *waiter.Entry) error { 284 c.Queue.EventRegister(e) 285 return nil 286 } 287 288 // Readiness implements waiter.Waitable.Readiness. 289 func (*ClockEventsQueue) Readiness(mask waiter.EventMask) waiter.EventMask { 290 return 0 291 } 292 293 // Listener receives expirations from a Timer. 294 type Listener interface { 295 // NotifyTimer is called when its associated Timer expires. exp is the number 296 // of expirations. setting is the next timer Setting. 297 // 298 // Notify is called with the associated Timer's mutex locked, so Notify 299 // must not take any locks that precede Timer.mu in lock order. 300 // 301 // If Notify returns true, the timer will use the returned setting 302 // rather than the passed one. 303 // 304 // Preconditions: exp > 0. 305 NotifyTimer(exp uint64, setting Setting) (newSetting Setting, update bool) 306 } 307 308 // Setting contains user-controlled mutable Timer properties. 309 // 310 // +stateify savable 311 type Setting struct { 312 // Enabled is true if the timer is running. 313 Enabled bool 314 315 // Next is the time in nanoseconds of the next expiration. 316 Next Time 317 318 // Period is the time in nanoseconds between expirations. If Period is 319 // zero, the timer will not automatically restart after expiring. 320 // 321 // Invariant: Period >= 0. 322 Period time.Duration 323 } 324 325 // SettingFromSpec converts a (value, interval) pair to a Setting based on a 326 // reading from c. value is interpreted as a time relative to c.Now(). 327 func SettingFromSpec(value time.Duration, interval time.Duration, c Clock) (Setting, error) { 328 return SettingFromSpecAt(value, interval, c.Now()) 329 } 330 331 // SettingFromSpecAt converts a (value, interval) pair to a Setting. value is 332 // interpreted as a time relative to now. 333 func SettingFromSpecAt(value time.Duration, interval time.Duration, now Time) (Setting, error) { 334 if value < 0 { 335 return Setting{}, linuxerr.EINVAL 336 } 337 if value == 0 { 338 return Setting{Period: interval}, nil 339 } 340 return Setting{ 341 Enabled: true, 342 Next: now.Add(value), 343 Period: interval, 344 }, nil 345 } 346 347 // SettingFromAbsSpec converts a (value, interval) pair to a Setting. value is 348 // interpreted as an absolute time. 349 func SettingFromAbsSpec(value Time, interval time.Duration) (Setting, error) { 350 if value.Before(ZeroTime) { 351 return Setting{}, linuxerr.EINVAL 352 } 353 if value.IsZero() { 354 return Setting{Period: interval}, nil 355 } 356 return Setting{ 357 Enabled: true, 358 Next: value, 359 Period: interval, 360 }, nil 361 } 362 363 // SettingFromItimerspec converts a linux.Itimerspec to a Setting. If abs is 364 // true, its.Value is interpreted as an absolute time. Otherwise, it is 365 // interpreted as a time relative to c.Now(). 366 func SettingFromItimerspec(its linux.Itimerspec, abs bool, c Clock) (Setting, error) { 367 if abs { 368 return SettingFromAbsSpec(FromTimespec(its.Value), its.Interval.ToDuration()) 369 } 370 return SettingFromSpec(its.Value.ToDuration(), its.Interval.ToDuration(), c) 371 } 372 373 // SpecFromSetting converts a timestamp and a Setting to a (relative value, 374 // interval) pair, as used by most Linux syscalls that return a struct 375 // itimerval or struct itimerspec. 376 func SpecFromSetting(now Time, s Setting) (value, period time.Duration) { 377 if !s.Enabled { 378 return 0, s.Period 379 } 380 return s.Next.Sub(now), s.Period 381 } 382 383 // ItimerspecFromSetting converts a Setting to a linux.Itimerspec. 384 func ItimerspecFromSetting(now Time, s Setting) linux.Itimerspec { 385 val, iv := SpecFromSetting(now, s) 386 return linux.Itimerspec{ 387 Interval: linux.DurationToTimespec(iv), 388 Value: linux.DurationToTimespec(val), 389 } 390 } 391 392 // At returns an updated Setting and a number of expirations after the 393 // associated Clock indicates a time of now. 394 // 395 // Settings may be created by successive calls to At with decreasing 396 // values of now (i.e. time may appear to go backward). Supporting this is 397 // required to support non-monotonic clocks, as well as allowing 398 // Timer.clock.Now() to be called without holding Timer.mu. 399 func (s Setting) At(now Time) (Setting, uint64) { 400 if !s.Enabled { 401 return s, 0 402 } 403 if s.Next.After(now) { 404 return s, 0 405 } 406 if s.Period == 0 { 407 s.Enabled = false 408 return s, 1 409 } 410 exp := 1 + uint64(now.Sub(s.Next).Nanoseconds())/uint64(s.Period) 411 s.Next = s.Next.Add(time.Duration(uint64(s.Period) * exp)) 412 return s, exp 413 } 414 415 // Timer is an optionally-periodic timer driven by sampling a user-specified 416 // Clock. Timer's semantics support the requirements of Linux's interval timers 417 // (setitimer(2), timer_create(2), timerfd_create(2)). 418 // 419 // Timers should be created using NewTimer and must be cleaned up by calling 420 // Timer.Destroy when no longer used. 421 // 422 // +stateify savable 423 type Timer struct { 424 // clock is the time source. clock is immutable. 425 clock Clock 426 427 // listener is notified of expirations. listener is immutable. 428 listener Listener 429 430 // mu protects the following mutable fields. 431 mu sync.Mutex `state:"nosave"` 432 433 // setting is the timer setting. setting is protected by mu. 434 setting Setting 435 436 // paused is true if the Timer is paused. paused is protected by mu. 437 paused bool 438 439 // kicker is used to wake the Timer goroutine. The kicker pointer is 440 // immutable, but its state is protected by mu. 441 kicker *time.Timer `state:"nosave"` 442 443 // entry is registered with clock.EventRegister. entry is immutable. 444 // 445 // Per comment in Clock, entry must be re-registered after restore; per 446 // comment in Timer.Load, this is done in Timer.Resume. 447 entry waiter.Entry `state:"nosave"` 448 449 // events is the channel that will be notified whenever entry receives an 450 // event. It is also closed by Timer.Destroy to instruct the Timer 451 // goroutine to exit. 452 events chan struct{} `state:"nosave"` 453 } 454 455 // timerTickEvents are Clock events that require the Timer goroutine to Tick 456 // prematurely. 457 const timerTickEvents = ClockEventSet | ClockEventRateIncrease 458 459 // NewTimer returns a new Timer that will obtain time from clock and send 460 // expirations to listener. The Timer is initially stopped and has no first 461 // expiration or period configured. 462 func NewTimer(clock Clock, listener Listener) *Timer { 463 t := &Timer{ 464 clock: clock, 465 listener: listener, 466 } 467 t.init() 468 return t 469 } 470 471 // init initializes Timer state that is not preserved across save/restore. If 472 // init has already been called, calling it again is a no-op. 473 // 474 // Preconditions: t.mu must be locked, or the caller must have exclusive access 475 // to t. 476 func (t *Timer) init() { 477 if t.kicker != nil { 478 return 479 } 480 // If t.kicker is nil, the Timer goroutine can't be running, so we can't 481 // race with it. 482 t.kicker = time.NewTimer(0) 483 t.entry, t.events = waiter.NewChannelEntry(timerTickEvents) 484 if err := t.clock.EventRegister(&t.entry); err != nil { 485 panic(err) 486 } 487 go t.runGoroutine() // S/R-SAFE: synchronized by t.mu 488 } 489 490 // Destroy releases resources owned by the Timer. A Destroyed Timer must not be 491 // used again; in particular, a Destroyed Timer should not be Saved. 492 func (t *Timer) Destroy() { 493 // Stop the Timer, ensuring that the Timer goroutine will not call 494 // t.kicker.Reset, before calling t.kicker.Stop. 495 t.mu.Lock() 496 t.setting.Enabled = false 497 t.mu.Unlock() 498 t.kicker.Stop() 499 // Unregister t.entry, ensuring that the Clock will not send to t.events, 500 // before closing t.events to instruct the Timer goroutine to exit. 501 t.clock.EventUnregister(&t.entry) 502 close(t.events) 503 } 504 505 func (t *Timer) runGoroutine() { 506 for { 507 select { 508 case <-t.kicker.C: 509 case _, ok := <-t.events: 510 if !ok { 511 // Channel closed by Destroy. 512 return 513 } 514 } 515 t.Tick() 516 } 517 } 518 519 // Tick requests that the Timer immediately check for expirations and 520 // re-evaluate when it should next check for expirations. 521 func (t *Timer) Tick() { 522 now := t.clock.Now() 523 t.mu.Lock() 524 defer t.mu.Unlock() 525 if t.paused { 526 return 527 } 528 s, exp := t.setting.At(now) 529 t.setting = s 530 if exp > 0 { 531 if newS, ok := t.listener.NotifyTimer(exp, t.setting); ok { 532 t.setting = newS 533 } 534 } 535 t.resetKickerLocked(now) 536 } 537 538 // Pause pauses the Timer, ensuring that it does not generate any further 539 // expirations until Resume is called. If the Timer is already paused, Pause 540 // has no effect. 541 func (t *Timer) Pause() { 542 t.mu.Lock() 543 defer t.mu.Unlock() 544 t.paused = true 545 // t.kicker may be nil if we were restored but never resumed. 546 if t.kicker != nil { 547 t.kicker.Stop() 548 } 549 } 550 551 // Resume ends the effect of Pause. If the Timer is not paused, Resume has no 552 // effect. 553 func (t *Timer) Resume() { 554 t.mu.Lock() 555 defer t.mu.Unlock() 556 if !t.paused { 557 return 558 } 559 t.paused = false 560 561 // Lazily initialize the Timer. We can't call Timer.init until Timer.Resume 562 // because save/restore will restore Timers before 563 // kernel.Timekeeper.SetClocks() has been called, so if t.clock is backed 564 // by a kernel.Timekeeper then the Timer goroutine will panic if it calls 565 // t.clock.Now(). 566 t.init() 567 568 // Kick the Timer goroutine in case it was already initialized, but the 569 // Timer goroutine was sleeping. 570 t.kicker.Reset(0) 571 } 572 573 // Get returns a snapshot of the Timer's current Setting and the time 574 // (according to the Timer's Clock) at which the snapshot was taken. 575 // 576 // Preconditions: The Timer must not be paused (since its Setting cannot 577 // be advanced to the current time while it is paused.) 578 func (t *Timer) Get() (Time, Setting) { 579 now := t.clock.Now() 580 t.mu.Lock() 581 defer t.mu.Unlock() 582 if t.paused { 583 panic(fmt.Sprintf("Timer.Get called on paused Timer %p", t)) 584 } 585 s, exp := t.setting.At(now) 586 t.setting = s 587 if exp > 0 { 588 if newS, ok := t.listener.NotifyTimer(exp, t.setting); ok { 589 t.setting = newS 590 } 591 } 592 t.resetKickerLocked(now) 593 return now, s 594 } 595 596 // Swap atomically changes the Timer's Setting and returns the Timer's previous 597 // Setting and the time (according to the Timer's Clock) at which the snapshot 598 // was taken. Setting s.Enabled to true starts the Timer, while setting 599 // s.Enabled to false stops it. 600 // 601 // Preconditions: The Timer must not be paused. 602 func (t *Timer) Swap(s Setting) (Time, Setting) { 603 return t.SwapAnd(s, nil) 604 } 605 606 // SwapAnd atomically changes the Timer's Setting, calls f if it is not nil, 607 // and returns the Timer's previous Setting and the time (according to the 608 // Timer's Clock) at which the Setting was changed. Setting s.Enabled to true 609 // starts the timer, while setting s.Enabled to false stops it. 610 // 611 // Preconditions: 612 // - The Timer must not be paused. 613 // - f cannot call any Timer methods since it is called with the Timer mutex 614 // locked. 615 func (t *Timer) SwapAnd(s Setting, f func()) (Time, Setting) { 616 now := t.clock.Now() 617 t.mu.Lock() 618 defer t.mu.Unlock() 619 if t.paused { 620 panic(fmt.Sprintf("Timer.SwapAnd called on paused Timer %p", t)) 621 } 622 oldS, oldExp := t.setting.At(now) 623 if oldExp > 0 { 624 t.listener.NotifyTimer(oldExp, oldS) 625 // N.B. The returned Setting doesn't matter because we're about 626 // to overwrite. 627 } 628 if f != nil { 629 f() 630 } 631 newS, newExp := s.At(now) 632 t.setting = newS 633 if newExp > 0 { 634 if newS, ok := t.listener.NotifyTimer(newExp, t.setting); ok { 635 t.setting = newS 636 } 637 } 638 t.resetKickerLocked(now) 639 return now, oldS 640 } 641 642 // Atomically invokes f atomically with respect to expirations of t; that is, t 643 // cannot generate expirations while f is being called. 644 // 645 // Preconditions: f cannot call any Timer methods since it is called with the 646 // Timer mutex locked. 647 func (t *Timer) Atomically(f func()) { 648 t.mu.Lock() 649 defer t.mu.Unlock() 650 f() 651 } 652 653 // Preconditions: t.mu must be locked. 654 func (t *Timer) resetKickerLocked(now Time) { 655 if t.setting.Enabled { 656 // Clock.WallTimeUntil may return a negative value. This is fine; 657 // time.when treats negative Durations as 0. 658 t.kicker.Reset(t.clock.WallTimeUntil(t.setting.Next, now)) 659 } 660 // We don't call t.kicker.Stop if !t.setting.Enabled because in most cases 661 // resetKickerLocked will be called from the Timer goroutine itself, in 662 // which case t.kicker has already fired and t.kicker.Stop will be an 663 // expensive no-op (time.Timer.Stop => time.stopTimer => runtime.stopTimer 664 // => runtime.deltimer). 665 } 666 667 // Clock returns the Clock used by t. 668 func (t *Timer) Clock() Clock { 669 return t.clock 670 } 671 672 // ChannelNotifier is a Listener that sends on a channel. 673 // 674 // ChannelNotifier cannot be saved or loaded. 675 type ChannelNotifier chan struct{} 676 677 // NewChannelNotifier creates a new channel notifier. 678 // 679 // If the notifier is used with a timer, Timer.Destroy will close the channel 680 // returned here. 681 func NewChannelNotifier() (Listener, <-chan struct{}) { 682 tchan := make(chan struct{}, 1) 683 return ChannelNotifier(tchan), tchan 684 } 685 686 // NotifyTimer implements Listener.NotifyTimer. 687 func (c ChannelNotifier) NotifyTimer(uint64, Setting) (Setting, bool) { 688 select { 689 case c <- struct{}{}: 690 default: 691 } 692 693 return Setting{}, false 694 }