package drivers import ( "finally-a-monolithic-linux-hw-monitor/app/common" "fmt" "os" "path/filepath" "sort" "strconv" "strings" ) type SysDriver struct{} func NewSysDriver() (*SysDriver, error) { r := SysDriver{} _, err := r.Read() return &r, err } func (r *SysDriver) Render(term common.Terminal) error { c, err := r.Read() if err != nil { return err } clock := c.([]ClockSensor) term.Subheader("Frequency /sys/devices/system/cpu/*/cpufreq") for _, sensor := range clock { // \033[K clears from cursor to end of line (prevents lingering chars) term.Print(fmt.Sprintf("%-16s | %.2f GHz", sensor.Name, sensor.FrequencyGHz)) } return nil } func (r *SysDriver) Read() (any, error) { // Glob directly targets scaling_cur_freq for all numerical CPU core paths freqFiles, err := filepath.Glob("/sys/devices/system/cpu/cpu[0-9]*/cpufreq/scaling_cur_freq") if err != nil { return nil, fmt.Errorf("failed to glob cpufreq files: %w", err) } clockSensors := []ClockSensor{} for _, path := range freqFiles { // Example path: /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq // Extract core ID from path segments parts := strings.Split(path, "/") if len(parts) < 6 { continue } // Parse "cpu0" -> 0 cpuDir := parts[5] coreIDStr := strings.TrimPrefix(cpuDir, "cpu") coreID, err := strconv.Atoi(coreIDStr) if err != nil { continue } // Read frequency in kHz directly from the matched file path data, err := os.ReadFile(path) if err != nil { continue } khz, err := strconv.ParseFloat(strings.TrimSpace(string(data)), 64) if err != nil { continue } clockSensors = append(clockSensors, ClockSensor{ path: path, number: coreID, Name: fmt.Sprintf("core %d", coreID), FrequencyGHz: khz / 1000000.0, // Convert KHz to GHz }) } // Guarantee numerical order by core ID sort.Slice(clockSensors, func(i, j int) bool { return clockSensors[i].number < clockSensors[j].number }) return clockSensors, nil }