1
0
Fork 0
cpu_ctrl/main.go

170 lines
4.4 KiB
Go
Raw Normal View History

2017-09-05 01:13:03 +09:00
package main
import (
2017-09-06 07:53:17 +09:00
"errors"
2017-09-05 01:13:03 +09:00
"os"
"os/signal"
2017-09-10 16:28:50 +09:00
"runtime"
2017-09-05 01:13:03 +09:00
"syscall"
"time"
2017-09-07 01:26:04 +09:00
2017-09-10 16:28:50 +09:00
"amuz.es/src/infra/cpu_ctrl/daemon"
"amuz.es/src/infra/cpu_ctrl/logger"
"amuz.es/src/infra/cpu_ctrl/processor"
"amuz.es/src/infra/cpu_ctrl/util"
"amuz.es/src/infra/cpu_ctrl/consumer"
2017-09-11 01:49:54 +09:00
"gopkg.in/alecthomas/kingpin.v2"
2017-09-05 01:13:03 +09:00
)
var (
2017-09-11 01:49:54 +09:00
app = kingpin.New("cpu_ctrl", "Interactive CPU fan controller").Author("Sangbum Kim")
verbose = app.Flag("verbose", "Enable verbose mode.").Short('v').Bool()
P = app.Flag("proportional-gain", "Set proportional gain value.").Short('p').Default("1.5").Float64()
2017-09-11 01:58:42 +09:00
I = app.Flag("integral-gain", "Set integral gain value.").Short('i').Default("0.4").Float64()
D = app.Flag("derivative-gain", "Set derivative gain value.").Short('d').Default("2.0").Float64()
2017-09-11 01:49:54 +09:00
SetPoint = app.Flag("set-point", "Set pointe tempeture").Short('t').Default("38.0").Float64()
2017-09-10 16:28:50 +09:00
log = logger.NewLogger("cpu_ctrl")
2017-09-05 01:13:03 +09:00
)
2017-09-10 16:28:50 +09:00
func init() {
2017-09-11 01:49:54 +09:00
app.Version("0.3")
if _, err := app.Parse(os.Args[1:]); err != nil {
panic(err)
}
logger.InitLogger(*verbose, "", &logger.Config{FileName: "Stderr"})
2017-09-10 16:28:50 +09:00
setMaxProcs()
2017-09-05 01:13:03 +09:00
}
2017-09-10 16:28:50 +09:00
func setMaxProcs() {
// TODO(vmarmol): Consider limiting if we have a CPU mask in effect.
// Allow as many threads as we have cores unless the user specified a value.
var numProcs int
// if *maxProcs < 1 {
numProcs = runtime.NumCPU()
// } else {
// numProcs = *maxProcs
// }
runtime.GOMAXPROCS(numProcs)
// Check if the setting was successful.
actualNumProcs := runtime.GOMAXPROCS(0)
if actualNumProcs != numProcs {
log.Printf("Specified max procs of %v but using %v\n", numProcs, actualNumProcs)
2017-09-05 01:13:03 +09:00
}
}
2017-09-11 07:41:59 +09:00
func FanoutSpeed(sender <-chan processor.FanspeedInfo, handler util.Handler, receivers ...chan<- processor.FanspeedInfo) {
defer handler.DecreaseWait()
defer func() {
if err := recover(); err != nil {
handler.NotifyError(err.(error))
}
}()
for {
select {
case tempeture := <-sender:
for _, receiver := range receivers {
select {
case receiver <- tempeture:
default:
2017-09-11 07:46:57 +09:00
log.Warn("Some Fanspeed consumer blocked!")
2017-09-11 07:41:59 +09:00
}
}
case <-handler.Done():
return
}
}
}
func FanoutTempeture(sender <-chan processor.TempetureInfo, handler util.Handler, receivers ...chan<- processor.TempetureInfo) {
defer handler.DecreaseWait()
defer func() {
if err := recover(); err != nil {
handler.NotifyError(err.(error))
}
}()
for {
select {
case tempeture := <-sender:
for _, receiver := range receivers {
select {
case receiver <- tempeture:
default:
log.Warn("Some Tempeture consumer blocked!")
}
}
case <-handler.Done():
return
}
}
}
2017-09-05 01:13:03 +09:00
func main() {
2017-09-05 01:13:03 +09:00
var (
2017-09-10 16:28:50 +09:00
processorCount = processor.GetProcessorCount()
processors []processor.Processor
exitSignal = make(chan os.Signal, 1)
handler = util.NewHandler()
sampleDuration = time.Second
2017-09-05 01:13:03 +09:00
)
2017-09-11 01:49:54 +09:00
log.Infof("Cpu fan controller")
2017-09-05 01:13:03 +09:00
2017-09-06 07:53:17 +09:00
if processorCount == 0 {
2017-09-10 16:28:50 +09:00
handler.NotifyError(errors.New("cpu not found!"))
2017-09-06 07:53:17 +09:00
}
2017-09-11 07:41:59 +09:00
var (
tempetureChannel = make(chan processor.TempetureInfo)
fanspeedChannel = make(chan processor.FanspeedInfo)
)
2017-09-10 16:28:50 +09:00
processors = make([]processor.Processor, 0, processorCount)
2017-09-05 01:13:03 +09:00
for i := 0; i < processorCount; i++ {
2017-09-10 16:28:50 +09:00
if info, err := processor.NewProcessorInfo(handler, i, sampleDuration,
2017-09-11 01:49:54 +09:00
*P, *I, *D, *SetPoint, 0x64, 0x4,
2017-09-11 07:41:59 +09:00
tempetureChannel, fanspeedChannel,
2017-09-10 16:28:50 +09:00
);
err != nil {
handler.NotifyError(err)
2017-09-06 07:53:17 +09:00
} else {
2017-09-10 16:28:50 +09:00
processors = append(processors, info)
handler.IncreaseWait()
2017-09-10 16:28:50 +09:00
go info.StartMonitoring()
2017-09-06 07:53:17 +09:00
}
2017-09-05 01:13:03 +09:00
}
2017-09-10 16:28:50 +09:00
2017-09-11 07:41:59 +09:00
fanController := consumer.NewFanControl(processorCount, sampleDuration, handler)
metricLogger := consumer.NewInfluxMetric("", processorCount, handler)
2017-09-11 07:41:59 +09:00
handler.IncreaseWait()
go FanoutTempeture(tempetureChannel, handler, metricLogger.TempetureConsumer())
defer close(tempetureChannel)
2017-09-11 07:41:59 +09:00
handler.IncreaseWait()
go FanoutSpeed(fanspeedChannel, handler, fanController.Consumer(), metricLogger.FanSpeedConsumer())
defer close(fanspeedChannel)
2017-09-10 16:28:50 +09:00
handler.IncreaseWait()
go fanController.StartControl()
2017-09-11 07:41:59 +09:00
handler.IncreaseWait()
go metricLogger.StartLogging()
2017-09-10 16:28:50 +09:00
2017-09-05 01:13:03 +09:00
signal.Notify(exitSignal, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
2017-09-10 16:28:50 +09:00
daemon.NotifyDaemon(daemon.DaemonStarted)
defer daemon.NotifyDaemon(daemon.DaemonStopping)
defer close(exitSignal)
defer handler.GracefullWait()
2017-09-05 01:13:03 +09:00
select {
2017-09-10 16:28:50 +09:00
case <-handler.Done():
log.Infoln("Service request to close this application")
case err := <-handler.Error():
log.Errorf("%s", err)
2017-09-05 01:13:03 +09:00
case sysSignal := <-exitSignal:
2017-09-10 16:28:50 +09:00
log.Warnf("SYSCALL! %s", sysSignal.String())
2017-09-05 01:13:03 +09:00
}
}