Compare commits

..

No commits in common. "96e07ece2d8a8187e2d64af1e3b8ea9d4cf9c4eb" and "f5d80a335fe6b181a56123fc079b081b9681a530" have entirely different histories.

4 changed files with 7 additions and 37 deletions

View file

@ -70,9 +70,6 @@ type apiData struct {
// HighReached is true when the system has reached a high vacuum stage. // HighReached is true when the system has reached a high vacuum stage.
HighReached bool HighReached bool
} }
// LoopLoad is a percentage expressing how busy the processing loop is; 100
// is full utilization; >100 is lag.
LoopLoad int64
// System junk. // System junk.
System struct { System struct {
// Load of the system. // Load of the system.
@ -117,7 +114,6 @@ func (s *webServer) apiData(skipSystem bool) *apiData {
ad.Pumps.DPOn = state.dpOn ad.Pumps.DPOn = state.dpOn
ad.Feedback.RoughReached = rough ad.Feedback.RoughReached = rough
ad.Feedback.HighReached = high ad.Feedback.HighReached = high
ad.LoopLoad = s.d.loopLoad()
ad.System.Load = load ad.System.Load = load
ad.System.Hostname = hostname ad.System.Hostname = hostname
return &ad return &ad

View file

@ -100,29 +100,27 @@ td > span {
<tr> <tr>
<th rowspan="3">Control</th> <th rowspan="3">Control</th>
<th>RP</th> <th>RP</th>
<td colspan="3"> <td>
<button id="rpon">On</button> <button id="rpon">On</button>
<button id="rpoff">Off</button> <button id="rpoff">Off</button>
</td> </td>
</tr> </tr>
<tr> <tr>
<th>DP</th> <th>DP</th>
<td colspan="3"> <td>
<button id="dpon">On</button> <button id="dpon">On</button>
<button id="dpoff">Off</button> <button id="dpoff">Off</button>
</td> </td>
</tr> </tr>
<tr> <tr>
<td colspan="3"> <td colspan="2">
<button id="pd">Pump Down</button> <button id="pd">Pump Down</button>
<button id="vent">Vent</button> <button id="vent">Vent</button>
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Status</th> <th>Status</th>
<td id="status" colspan="1">OK</td> <td id="status" colspan="4">OK</td>
<th>Load</th>
<td id="load" colspan="1">...</td>
</tr> </tr>
</table> </table>
</p> </p>
@ -277,7 +275,6 @@ window.addEventListener("load", (_) => {
let ping = document.querySelector("#ping"); let ping = document.querySelector("#ping");
let trough = document.querySelector("#trough"); let trough = document.querySelector("#trough");
let thigh = document.querySelector("#thigh"); let thigh = document.querySelector("#thigh");
let load = document.querySelector("#load");
// Buttons // Buttons
let pd = document.querySelector("#pd"); let pd = document.querySelector("#pd");
@ -357,7 +354,6 @@ window.addEventListener("load", (_) => {
thigh.innerHTML = "NOK"; thigh.innerHTML = "NOK";
thigh.style = "background-color: #f06060"; thigh.style = "background-color: #f06060";
} }
load.innerHTML = data.LoopLoad.toString() + "%";
historicalPush(data.Pirani.MbarFloat); historicalPush(data.Pirani.MbarFloat);
ping.innerHTML = Date.now(); ping.innerHTML = Date.now();
}); });

View file

@ -5,7 +5,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"sync" "sync"
"sync/atomic"
"time" "time"
"k8s.io/klog" "k8s.io/klog"
@ -24,8 +23,6 @@ type daemon struct {
gpioBelowRough gpio gpioBelowRough gpio
gpioBelowHigh gpio gpioBelowHigh gpio
load atomic.Int64
// mu guards the state below. // mu guards the state below.
mu sync.RWMutex mu sync.RWMutex
daemonState daemonState
@ -65,22 +62,11 @@ func (d *daemonState) vacuumStatus() (rough, high bool) {
// process runs the pain acquisition and control loop of succd. // process runs the pain acquisition and control loop of succd.
func (d *daemon) process(ctx context.Context) { func (d *daemon) process(ctx context.Context) {
var lastRun time.Time ticker := time.NewTicker(time.Millisecond * 100)
hz := 100
period := time.Second / time.Duration(hz)
// Extra grace period for GC pauses and other non-realtime system jitter.
periodGrace := period + time.Millisecond*5
ticker := time.NewTicker(period)
defer ticker.Stop() defer ticker.Stop()
for { for {
select { select {
case <-ticker.C: case <-ticker.C:
now := time.Now()
if elapsed := now.Sub(lastRun); !lastRun.IsZero() && elapsed > periodGrace {
klog.Warningf("Processing loop lag: took %s, want %s", elapsed, period)
}
lastRun = now
if err := d.processOnce(ctx); err != nil { if err := d.processOnce(ctx); err != nil {
if errors.Is(err, ctx.Err()) { if errors.Is(err, ctx.Err()) {
return return
@ -89,9 +75,6 @@ func (d *daemon) process(ctx context.Context) {
time.Sleep(time.Second * 10) time.Sleep(time.Second * 10)
} }
} }
runtime := time.Since(lastRun)
load := int64(100 * runtime / period)
d.load.Store(load)
case <-ctx.Done(): case <-ctx.Done():
return return
} }
@ -121,8 +104,8 @@ func (d *daemon) processOnce(_ context.Context) error {
mbar := d.piraniMbar3.mbar mbar := d.piraniMbar3.mbar
if !d.safety.failsafe && mbar < 4e-6 { if !d.safety.failsafe && mbar < 4e-6 {
// Unrealistic result, Pirani probe probably disconnected. Failsafe mode. // Unrealistic result, Pirani probe probably disconnected. Failsafe mode.
d.safety.failsafe = true d.safety.failsafe = true
klog.Errorf("SAFETY: Pirani probe seems disconnected; enabling failsafe mode") klog.Errorf("SAFETY: Pirani probe seems disconnected; enabling failsafe mode")
} }
if d.safety.failsafe && mbar > 1e2 { if d.safety.failsafe && mbar > 1e2 {
d.safety.failsafe = false d.safety.failsafe = false

View file

@ -7,7 +7,6 @@ import "k8s.io/klog"
// //
// This is a subset of daemon functions limited to a safe, explicit subset. // This is a subset of daemon functions limited to a safe, explicit subset.
type daemonController interface { type daemonController interface {
loopLoad() int64
// snapshot returns an internally consistent copy of the daemon state. // snapshot returns an internally consistent copy of the daemon state.
snapshot() *daemonState snapshot() *daemonState
// rpSet enables/disables the roughing pump. // rpSet enables/disables the roughing pump.
@ -20,10 +19,6 @@ type daemonController interface {
ventPress() ventPress()
} }
func (d *daemon) loopLoad() int64 {
return d.load.Load()
}
func (d *daemon) snapshot() *daemonState { func (d *daemon) snapshot() *daemonState {
d.mu.RLock() d.mu.RLock()
ds := d.daemonState ds := d.daemonState