103 lines
2.5 KiB
Go
103 lines
2.5 KiB
Go
|
package sim
|
||
|
|
||
|
import (
|
||
|
"log"
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
"git.elyanpoujol.fr/elyan/central-arch/pkg/breakcfg"
|
||
|
"git.elyanpoujol.fr/elyan/central-arch/pkg/events"
|
||
|
"git.elyanpoujol.fr/elyan/central-arch/pkg/simstep"
|
||
|
)
|
||
|
|
||
|
type SchedulerConfig struct {
|
||
|
BreakableEventConfig *breakcfg.BreakableEventConfig
|
||
|
}
|
||
|
|
||
|
type Scheduler struct {
|
||
|
config SchedulerConfig
|
||
|
cpuBreakpoints map[CpuBreakpoint]bool
|
||
|
cpuWatchpoints map[CpuWatchpoint]bool
|
||
|
cpuModeTransitionBreakType CpuModeTransitionBreakType
|
||
|
stepRequest chan events.SimEvent
|
||
|
stepResponse chan bool
|
||
|
commandRequest chan Command
|
||
|
commandReponse chan bool
|
||
|
breakEvent chan *Sim
|
||
|
quitEvent <-chan bool
|
||
|
}
|
||
|
|
||
|
func NewScheduler(config SchedulerConfig, quitEvent <-chan bool) *Scheduler {
|
||
|
return &Scheduler{
|
||
|
config: config,
|
||
|
cpuBreakpoints: make(map[CpuBreakpoint]bool),
|
||
|
cpuWatchpoints: make(map[CpuWatchpoint]bool),
|
||
|
// When the scheduler stopped running, we don't want the client to block
|
||
|
// when sending to this channel
|
||
|
stepRequest: make(chan events.SimEvent, 1),
|
||
|
stepResponse: make(chan bool),
|
||
|
// When the scheduler stopped running, we don't want the client to block
|
||
|
// when sending to this channel
|
||
|
commandRequest: make(chan Command, 1),
|
||
|
commandReponse: make(chan bool),
|
||
|
breakEvent: make(chan *Sim),
|
||
|
quitEvent: quitEvent,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *Scheduler) Run(wg *sync.WaitGroup) {
|
||
|
wg.Add(1)
|
||
|
defer wg.Done()
|
||
|
|
||
|
for {
|
||
|
select {
|
||
|
case <-s.quitEvent:
|
||
|
s.closeSendingChannels()
|
||
|
return
|
||
|
|
||
|
case req := <-s.stepRequest:
|
||
|
s.handleStepRequest(req)
|
||
|
|
||
|
case cmd := <-s.commandRequest:
|
||
|
s.handleSchedulingCommand(cmd)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *Scheduler) closeSendingChannels() {
|
||
|
close(s.stepResponse)
|
||
|
close(s.commandReponse)
|
||
|
close(s.breakEvent)
|
||
|
}
|
||
|
|
||
|
func (s *Scheduler) Cleanup() {
|
||
|
close(s.stepRequest)
|
||
|
close(s.commandRequest)
|
||
|
}
|
||
|
|
||
|
func (s *Scheduler) handleStepRequest(req simstep.SimStepRequest) {
|
||
|
// TODO Handle request
|
||
|
// TODO Check breakpoints
|
||
|
log.Println("step !")
|
||
|
time.Sleep(time.Second)
|
||
|
s.stepResponse <- true
|
||
|
}
|
||
|
|
||
|
func (s *Scheduler) handleSchedulingCommand(cmd Command) {
|
||
|
// TODO Handle scheduling command
|
||
|
}
|
||
|
|
||
|
func (s *Scheduler) RequestStep(req simstep.SimStepRequest) error {
|
||
|
s.stepRequest <- req
|
||
|
|
||
|
// The scheduler always sends true, to receive false means that the channel is closed
|
||
|
// and thus, that we must quit
|
||
|
doContinue := <-s.stepResponse
|
||
|
|
||
|
if !doContinue {
|
||
|
return simstep.SimQuitRequest
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|