github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/runtime/time.go (about) 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 }