forked from cdfmlr/sham
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscheduler.go
99 lines (85 loc) · 2.71 KB
/
scheduler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package sham
import (
log "github.com/sirupsen/logrus"
"time"
)
// Scheduler 是模拟的调度器
type Scheduler interface {
// schedule 完成调度:传入CPU 实例、进程表,
// 原址完成进程队列调整,并在需要的时候做 CPU.Switch(也可以不做)
schedule(os *OS)
}
// NoScheduler 是一个不调度的调度器,
// 它只运行表中第一个东西,然后结束退出。
type NoScheduler struct{}
func (n NoScheduler) schedule(os *OS) {
// 起手式:运行一个线程
if len(os.ReadyProcs) > 0 {
os.ReadyToRunning(os.ReadyProcs[0].Id)
}
// 调度过程
for len(os.ReadyProcs) > 0 || os.RunningProc.Status != StatusDone {
select {
case pid := <-os.CPU.Done:
os.RunningToDone()
log.WithField("done_process", pid).Info("first thread done, do no more schedule. Shutdown NoScheduler")
return
}
}
}
// FCFSScheduler do first-come first-served schedule.
// 先来先服务,一次跑到够(退出|阻塞),后来排队尾。
type FCFSScheduler struct{}
func (F FCFSScheduler) schedule(os *OS) {
field := "[FCFSScheduler] "
log.Info(field, "FCFSScheduler on")
if len(os.ReadyProcs) > 0 {
log.WithField("first_process", os.ReadyProcs[0].Id).Info(field, "Boot the first process")
os.ReadyToRunning(os.ReadyProcs[0].Id)
}
for {
select {
case status := <-os.CPU.Done:
logger := log.WithFields(log.Fields{
"process": os.RunningProc.Id,
"status": status,
"contextual_PC": os.RunningProc.Thread.contextual.PC,
})
logger.Info(field, "process stop running. Do schedule")
switch status {
case StatusDone:
os.RunningToDone()
case StatusBlocked:
os.RunningToBlocked()
default:
os.RunningToReady()
}
os.HandleInterrupts()
if len(os.ReadyProcs) > 0 {
F._schedule(os)
}
case <-time.After(3 * time.Second):
if os.RunningProc.Status != StatusRunning {
// 避免 "all goroutines are asleep - deadlock":别闲着,去跑 Noop
log.Warn("no process ready. Waiting with noop...")
os.ProcsMutex.Lock()
os.ReadyProcs = append(os.ReadyProcs, &Noop)
os.ProcsMutex.Unlock()
F._schedule(os)
}
}
os.ProcsMutex.RLock()
hasJobsToDo := len(os.ReadyProcs) > 0 || os.RunningProc.Status != StatusDone || len(os.BlockedProcs) > 0
os.ProcsMutex.RUnlock()
if !hasJobsToDo {
break
}
}
log.Info(field, "All process done. no process to schedule. Shutdown FCFSScheduler")
}
// _schedule 完成真正的调度工作:决定并运行谁
// 该函数假设 process 不为空,且 cpu 空闲(Thread == nil)
func (F FCFSScheduler) _schedule(os *OS) {
log.WithField("process_to_run", os.ReadyProcs[0].Id).Info("[FCFSScheduler] ", "run the head process")
os.ReadyToRunning(os.ReadyProcs[0].Id)
}