fix sleep queue corruption bug

Этот коммит содержится в:
Jaden Weiss 2019-09-03 14:43:56 -04:00 коммит произвёл Ayke
родитель 8a5fa51f60
коммит a718b10502

Просмотреть файл

@ -133,42 +133,28 @@ func addSleepTask(t *task) {
now := ticks()
if sleepQueue == nil {
scheduleLog(" -> sleep new queue")
// Create new linked list for the sleep queue.
sleepQueue = t
// set new base time
sleepQueueBaseTime = now
return
}
// Make sure state.data is relative to the queue time base.
state := t.state()
// Insert at front of sleep queue.
if state.data < sleepQueue.state().data {
scheduleLog(" -> sleep at start")
sleepQueue.state().data -= state.data
state.next = sleepQueue
sleepQueue = t
return
}
// Add to sleep queue (in the middle or at the end).
queueIndex := sleepQueue
for {
state.data -= queueIndex.state().data
if queueIndex.state().next == nil || queueIndex.state().data > state.data {
if queueIndex.state().next == nil {
scheduleLog(" -> sleep at end")
state.next = nil
} else {
scheduleLog(" -> sleep in middle")
state.next = queueIndex.state().next
state.next.state().data -= state.data
}
queueIndex.state().next = t
// Add to sleep queue.
q := &sleepQueue
for ; *q != nil; q = &((*q).state()).next {
if t.state().data < (*q).state().data {
// this will finish earlier than the next - insert here
break
} else {
// this will finish later - adjust delay
t.state().data -= (*q).state().data
}
queueIndex = queueIndex.state().next
}
if *q != nil {
// cut delay time between this sleep task and the next
(*q).state().data -= t.state().data
}
t.state().next = *q
*q = t
}
// Run the scheduler until all tasks have finished.
@ -204,8 +190,11 @@ func scheduler() {
timeLeft := timeUnit(sleepQueue.state().data) - (now - sleepQueueBaseTime)
if schedulerDebug {
println(" sleeping...", sleepQueue, uint(timeLeft))
for t := sleepQueue; t != nil; t = t.state().next {
println(" task sleeping:", t, timeUnit(t.state().data))
}
}
sleepTicks(timeUnit(timeLeft))
sleepTicks(timeLeft)
if asyncScheduler {
// The sleepTicks function above only sets a timeout at which
// point the scheduler will be called again. It does not really