Source file src/runtime/time.go

Documentation: runtime

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Time-related runtime and pieces of package time.
     6  
     7  package runtime
     8  
     9  import (
    10  	"internal/cpu"
    11  	"unsafe"
    12  )
    13  
    14  // Package time knows the layout of this structure.
    15  // If this struct changes, adjust ../time/sleep.go:/runtimeTimer.
    16  // For GOOS=nacl, package syscall knows the layout of this structure.
    17  // If this struct changes, adjust ../syscall/net_nacl.go:/runtimeTimer.
    18  type timer struct {
    19  	tb *timersBucket // the bucket the timer lives in
    20  	i  int           // heap index
    21  
    22  	// Timer wakes up at when, and then at when+period, ... (period > 0 only)
    23  	// each time calling f(arg, now) in the timer goroutine, so f must be
    24  	// a well-behaved function and not block.
    25  	when   int64
    26  	period int64
    27  	f      func(interface{}, uintptr)
    28  	arg    interface{}
    29  	seq    uintptr
    30  }
    31  
    32  // timersLen is the length of timers array.
    33  //
    34  // Ideally, this would be set to GOMAXPROCS, but that would require
    35  // dynamic reallocation
    36  //
    37  // The current value is a compromise between memory usage and performance
    38  // that should cover the majority of GOMAXPROCS values used in the wild.
    39  const timersLen = 64
    40  
    41  // timers contains "per-P" timer heaps.
    42  //
    43  // Timers are queued into timersBucket associated with the current P,
    44  // so each P may work with its own timers independently of other P instances.
    45  //
    46  // Each timersBucket may be associated with multiple P
    47  // if GOMAXPROCS > timersLen.
    48  var timers [timersLen]struct {
    49  	timersBucket
    50  
    51  	// The padding should eliminate false sharing
    52  	// between timersBucket values.
    53  	pad [cpu.CacheLinePadSize - unsafe.Sizeof(timersBucket{})%cpu.CacheLinePadSize]byte
    54  }
    55  
    56  func (t *timer) assignBucket() *timersBucket {
    57  	id := uint8(getg().m.p.ptr().id) % timersLen
    58  	t.tb = &timers[id].timersBucket
    59  	return t.tb
    60  }
    61  
    62  //go:notinheap
    63  type timersBucket struct {
    64  	lock         mutex
    65  	gp           *g
    66  	created      bool
    67  	sleeping     bool
    68  	rescheduling bool
    69  	sleepUntil   int64
    70  	waitnote     note
    71  	t            []*timer
    72  }
    73  
    74  // nacl fake time support - time in nanoseconds since 1970
    75  var faketime int64
    76  
    77  // Package time APIs.
    78  // Godoc uses the comments in package time, not these.
    79  
    80  // time.now is implemented in assembly.
    81  
    82  // timeSleep puts the current goroutine to sleep for at least ns nanoseconds.
    83  //go:linkname timeSleep time.Sleep
    84  func timeSleep(ns int64) {
    85  	if ns <= 0 {
    86  		return
    87  	}
    88  
    89  	gp := getg()
    90  	t := gp.timer
    91  	if t == nil {
    92  		t = new(timer)
    93  		gp.timer = t
    94  	}
    95  	*t = timer{}
    96  	t.when = nanotime() + ns
    97  	t.f = goroutineReady
    98  	t.arg = gp
    99  	tb := t.assignBucket()
   100  	lock(&tb.lock)
   101  	if !tb.addtimerLocked(t) {
   102  		unlock(&tb.lock)
   103  		badTimer()
   104  	}
   105  	goparkunlock(&tb.lock, waitReasonSleep, traceEvGoSleep, 2)
   106  }
   107  
   108  // startTimer adds t to the timer heap.
   109  //go:linkname startTimer time.startTimer
   110  func startTimer(t *timer) {
   111  	if raceenabled {
   112  		racerelease(unsafe.Pointer(t))
   113  	}
   114  	addtimer(t)
   115  }
   116  
   117  // stopTimer removes t from the timer heap if it is there.
   118  // It returns true if t was removed, false if t wasn't even there.
   119  //go:linkname stopTimer time.stopTimer
   120  func stopTimer(t *timer) bool {
   121  	return deltimer(t)
   122  }
   123  
   124  // Go runtime.
   125  
   126  // Ready the goroutine arg.
   127  func goroutineReady(arg interface{}, seq uintptr) {
   128  	goready(arg.(*g), 0)
   129  }
   130  
   131  func addtimer(t *timer) {
   132  	tb := t.assignBucket()
   133  	lock(&tb.lock)
   134  	ok := tb.addtimerLocked(t)
   135  	unlock(&tb.lock)
   136  	if !ok {
   137  		badTimer()
   138  	}
   139  }
   140  
   141  // Add a timer to the heap and start or kick timerproc if the new timer is
   142  // earlier than any of the others.
   143  // Timers are locked.
   144  // Returns whether all is well: false if the data structure is corrupt
   145  // due to user-level races.
   146  func (tb *timersBucket) addtimerLocked(t *timer) bool {
   147  	// when must never be negative; otherwise timerproc will overflow
   148  	// during its delta calculation and never expire other runtime timers.
   149  	if t.when < 0 {
   150  		t.when = 1<<63 - 1
   151  	}
   152  	t.i = len(tb.t)
   153  	tb.t = append(tb.t, t)
   154  	if !siftupTimer(tb.t, t.i) {
   155  		return false
   156  	}
   157  	if t.i == 0 {
   158  		// siftup moved to top: new earliest deadline.
   159  		if tb.sleeping && tb.sleepUntil > t.when {
   160  			tb.sleeping = false
   161  			notewakeup(&tb.waitnote)
   162  		}
   163  		if tb.rescheduling {
   164  			tb.rescheduling = false
   165  			goready(tb.gp, 0)
   166  		}
   167  		if !tb.created {
   168  			tb.created = true
   169  			go timerproc(tb)
   170  		}
   171  	}
   172  	return true
   173  }
   174  
   175  // Delete timer t from the heap.
   176  // Do not need to update the timerproc: if it wakes up early, no big deal.
   177  func deltimer(t *timer) bool {
   178  	if t.tb == nil {
   179  		// t.tb can be nil if the user created a timer
   180  		// directly, without invoking startTimer e.g
   181  		//    time.Ticker{C: c}
   182  		// In this case, return early without any deletion.
   183  		// See Issue 21874.
   184  		return false
   185  	}
   186  
   187  	tb := t.tb
   188  
   189  	lock(&tb.lock)
   190  	removed, ok := tb.deltimerLocked(t)
   191  	unlock(&tb.lock)
   192  	if !ok {
   193  		badTimer()
   194  	}
   195  	return removed
   196  }
   197  
   198  func (tb *timersBucket) deltimerLocked(t *timer) (removed, ok bool) {
   199  	// t may not be registered anymore and may have
   200  	// a bogus i (typically 0, if generated by Go).
   201  	// Verify it before proceeding.
   202  	i := t.i
   203  	last := len(tb.t) - 1
   204  	if i < 0 || i > last || tb.t[i] != t {
   205  		return false, true
   206  	}
   207  	if i != last {
   208  		tb.t[i] = tb.t[last]
   209  		tb.t[i].i = i
   210  	}
   211  	tb.t[last] = nil
   212  	tb.t = tb.t[:last]
   213  	ok = true
   214  	if i != last {
   215  		if !siftupTimer(tb.t, i) {
   216  			ok = false
   217  		}
   218  		if !siftdownTimer(tb.t, i) {
   219  			ok = false
   220  		}
   221  	}
   222  	return true, ok
   223  }
   224  
   225  func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) {
   226  	tb := t.tb
   227  
   228  	lock(&tb.lock)
   229  	_, ok := tb.deltimerLocked(t)
   230  	if ok {
   231  		t.when = when
   232  		t.period = period
   233  		t.f = f
   234  		t.arg = arg
   235  		t.seq = seq
   236  		ok = tb.addtimerLocked(t)
   237  	}
   238  	unlock(&tb.lock)
   239  	if !ok {
   240  		badTimer()
   241  	}
   242  }
   243  
   244  // Timerproc runs the time-driven events.
   245  // It sleeps until the next event in the tb heap.
   246  // If addtimer inserts a new earlier event, it wakes timerproc early.
   247  func timerproc(tb *timersBucket) {
   248  	tb.gp = getg()
   249  	for {
   250  		lock(&tb.lock)
   251  		tb.sleeping = false
   252  		now := nanotime()
   253  		delta := int64(-1)
   254  		for {
   255  			if len(tb.t) == 0 {
   256  				delta = -1
   257  				break
   258  			}
   259  			t := tb.t[0]
   260  			delta = t.when - now
   261  			if delta > 0 {
   262  				break
   263  			}
   264  			ok := true
   265  			if t.period > 0 {
   266  				// leave in heap but adjust next time to fire
   267  				t.when += t.period * (1 + -delta/t.period)
   268  				if !siftdownTimer(tb.t, 0) {
   269  					ok = false
   270  				}
   271  			} else {
   272  				// remove from heap
   273  				last := len(tb.t) - 1
   274  				if last > 0 {
   275  					tb.t[0] = tb.t[last]
   276  					tb.t[0].i = 0
   277  				}
   278  				tb.t[last] = nil
   279  				tb.t = tb.t[:last]
   280  				if last > 0 {
   281  					if !siftdownTimer(tb.t, 0) {
   282  						ok = false
   283  					}
   284  				}
   285  				t.i = -1 // mark as removed
   286  			}
   287  			f := t.f
   288  			arg := t.arg
   289  			seq := t.seq
   290  			unlock(&tb.lock)
   291  			if !ok {
   292  				badTimer()
   293  			}
   294  			if raceenabled {
   295  				raceacquire(unsafe.Pointer(t))
   296  			}
   297  			f(arg, seq)
   298  			lock(&tb.lock)
   299  		}
   300  		if delta < 0 || faketime > 0 {
   301  			// No timers left - put goroutine to sleep.
   302  			tb.rescheduling = true
   303  			goparkunlock(&tb.lock, waitReasonTimerGoroutineIdle, traceEvGoBlock, 1)
   304  			continue
   305  		}
   306  		// At least one timer pending. Sleep until then.
   307  		tb.sleeping = true
   308  		tb.sleepUntil = now + delta
   309  		noteclear(&tb.waitnote)
   310  		unlock(&tb.lock)
   311  		notetsleepg(&tb.waitnote, delta)
   312  	}
   313  }
   314  
   315  func timejump() *g {
   316  	if faketime == 0 {
   317  		return nil
   318  	}
   319  
   320  	for i := range timers {
   321  		lock(&timers[i].lock)
   322  	}
   323  	gp := timejumpLocked()
   324  	for i := range timers {
   325  		unlock(&timers[i].lock)
   326  	}
   327  
   328  	return gp
   329  }
   330  
   331  func timejumpLocked() *g {
   332  	// Determine a timer bucket with minimum when.
   333  	var minT *timer
   334  	for i := range timers {
   335  		tb := &timers[i]
   336  		if !tb.created || len(tb.t) == 0 {
   337  			continue
   338  		}
   339  		t := tb.t[0]
   340  		if minT == nil || t.when < minT.when {
   341  			minT = t
   342  		}
   343  	}
   344  	if minT == nil || minT.when <= faketime {
   345  		return nil
   346  	}
   347  
   348  	faketime = minT.when
   349  	tb := minT.tb
   350  	if !tb.rescheduling {
   351  		return nil
   352  	}
   353  	tb.rescheduling = false
   354  	return tb.gp
   355  }
   356  
   357  func timeSleepUntil() int64 {
   358  	next := int64(1<<63 - 1)
   359  
   360  	// Determine minimum sleepUntil across all the timer buckets.
   361  	//
   362  	// The function can not return a precise answer,
   363  	// as another timer may pop in as soon as timers have been unlocked.
   364  	// So lock the timers one by one instead of all at once.
   365  	for i := range timers {
   366  		tb := &timers[i]
   367  
   368  		lock(&tb.lock)
   369  		if tb.sleeping && tb.sleepUntil < next {
   370  			next = tb.sleepUntil
   371  		}
   372  		unlock(&tb.lock)
   373  	}
   374  
   375  	return next
   376  }
   377  
   378  // Heap maintenance algorithms.
   379  // These algorithms check for slice index errors manually.
   380  // Slice index error can happen if the program is using racy
   381  // access to timers. We don't want to panic here, because
   382  // it will cause the program to crash with a mysterious
   383  // "panic holding locks" message. Instead, we panic while not
   384  // holding a lock.
   385  // The races can occur despite the bucket locks because assignBucket
   386  // itself is called without locks, so racy calls can cause a timer to
   387  // change buckets while executing these functions.
   388  
   389  func siftupTimer(t []*timer, i int) bool {
   390  	if i >= len(t) {
   391  		return false
   392  	}
   393  	when := t[i].when
   394  	tmp := t[i]
   395  	for i > 0 {
   396  		p := (i - 1) / 4 // parent
   397  		if when >= t[p].when {
   398  			break
   399  		}
   400  		t[i] = t[p]
   401  		t[i].i = i
   402  		i = p
   403  	}
   404  	if tmp != t[i] {
   405  		t[i] = tmp
   406  		t[i].i = i
   407  	}
   408  	return true
   409  }
   410  
   411  func siftdownTimer(t []*timer, i int) bool {
   412  	n := len(t)
   413  	if i >= n {
   414  		return false
   415  	}
   416  	when := t[i].when
   417  	tmp := t[i]
   418  	for {
   419  		c := i*4 + 1 // left child
   420  		c3 := c + 2  // mid child
   421  		if c >= n {
   422  			break
   423  		}
   424  		w := t[c].when
   425  		if c+1 < n && t[c+1].when < w {
   426  			w = t[c+1].when
   427  			c++
   428  		}
   429  		if c3 < n {
   430  			w3 := t[c3].when
   431  			if c3+1 < n && t[c3+1].when < w3 {
   432  				w3 = t[c3+1].when
   433  				c3++
   434  			}
   435  			if w3 < w {
   436  				w = w3
   437  				c = c3
   438  			}
   439  		}
   440  		if w >= when {
   441  			break
   442  		}
   443  		t[i] = t[c]
   444  		t[i].i = i
   445  		i = c
   446  	}
   447  	if tmp != t[i] {
   448  		t[i] = tmp
   449  		t[i].i = i
   450  	}
   451  	return true
   452  }
   453  
   454  // badTimer is called if the timer data structures have been corrupted,
   455  // presumably due to racy use by the program. We panic here rather than
   456  // panicing due to invalid slice access while holding locks.
   457  // See issue #25686.
   458  func badTimer() {
   459  	panic(errorString("racy use of timers"))
   460  }
   461  

View as plain text