Hi,

I was trying to get obsdfreqd to work (on 7.2), but it doesn't:

    obsdfreqd> doas obsdfreqd -v -T 70
    mode;Temperature;maximum_frequency;current_frequency;cpu
usage;inertia;new frequency
    obsdfreqd: sysctl to get temperature: No such file or directory
    1;

I had apmd running with -L, and obsdfreqd seems to work without
temperature limits (though my CPU was getting awfully hot...).

I grabbed the source code and checked what it was doing:

    mib[0] = CTL_HW;
    mib[1] = HW_SENSORS;
    mib[2] = 0;
    mib[3] = SENSOR_TEMP;
    mib[4] = 0;

    if (sysctl(mib, 5, &sensor, &len, NULL, 0) == -1)
        err(1, "sysctl to get temperature");

Bingo, so something's wrong there. I know I can read the temperature
with sysctl(1), so what's wrong?

According to the man page, mib[2] is the device name/number, but is 0
really the CPU device? I wrote a test program to dump the sensors, and
sure enough, on my machine, it is device 3... (test program and output
at the end; maybe OpenBSD already had this program, but I invoke the
"learning opportunity" card)

There might be another issue, though it's hard to check, and I don't
know exactly how OpenBSD works on most machines. I have another HP
laptop, which, OK, it's running Linux, but it reports no less than 10
different temperature readings, and they are all slightly different
(though within a few degrees of each other). I might check how many
temperature sensors OpenBSD will actually read on that machine, but I
need to find the time. The point is, grabbing the first temperature
sensor on the first device that has one might not actually be THE
temperature of the CPU whose frequency we're controlling.

I'm not sure what the fix here would be; if it were up to me, I'd add a
flag like "-S hw.sensors.cpu0.temp0" to tell it exactly which sensor I
want, then have the obsdfreqd code:
a) get a list of all sensordev devices (3-level mib loop)
b) find the one whose xname is 'cpu0'
c) parse 'temp0' and extract the '0'
d) run sysctl with a 5-level mib
   { CTL_HW, HW_SENSORS, sensordev.num, SENSOR_TEMP, atoi(tempidx) }

I could write that logic if everyone's on board. Actually, the logic to
parse those sysctl(1) style strings is already in sysctl's source code,
it's more a question of adding a parameter or conf file or something to
obsdfreqd to actually tell it what temperature sensor to look at.

Test program:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    #include <err.h>

    #include <sys/time.h>
    #include <sys/types.h>
    #include <sys/sensors.h>
    #include <sys/sysctl.h>

    #include <assert.h>

    const char* sensor_type_names[] = {
        "SENSOR_TEMP",
        "SENSOR_FANRPM",
        "SENSOR_VOLTS_DC",
        "SENSOR_VOLTS_AC",
        "SENSOR_OHMS",
        "SENSOR_WATTS",
        "SENSOR_AMPS",
        "SENSOR_WATTHOUR",
        "SENSOR_AMPHOUR",
        "SENSOR_INDICATOR",
        "SENSOR_INTEGER",
        "SENSOR_PERCENT",
        "SENSOR_LUX",
        "SENSOR_DRIVE",
        "SENSOR_TIMEDELTA",
        "SENSOR_HUMIDITY",
        "SENSOR_FREQ",
        "SENSOR_ANGLE",
        "SENSOR_DISTANCE",
        "SENSOR_PRESSURE",
        "SENSOR_ACCEL",
        "SENSOR_VELOCITY",
        "SENSOR_ENERGY",
    };

    int main(int argc, char* argv[])
    {
        int mib[5];
        size_t len = 0;
        struct sensordev *sensordevs = NULL;
        size_t sensorlen = sizeof(struct sensor);
        memset(mib, 0, sizeof(mib));
        mib[0] = CTL_HW;
        mib[1] = HW_SENSORS;
        for(int dev = 0; ; ++dev) {
            mib[2] = dev;
            if(-1 == sysctl(mib, 3, NULL, &len, NULL, 0)) {
                warn("Failed to get sensor count for dev %d, end of
array, exiting", dev);
                break;
            } // sysctl get num sensordevs
            assert((len % sizeof(struct sensordev)) == 0);
            size_t nsensordevs = len / sizeof(struct sensordev);
            printf("Device %d, %zd sensordevs\n", dev, nsensordevs);
            sensordevs = malloc(len);
            memset(sensordevs, 0, len);
            if(-1 == sysctl(mib, 3, sensordevs, &len, NULL, 0)) {
                warn("Failed to retrieve sensors for device %d", dev);
                continue;
            } // sysctl get sensordevs

            for(int sd = 0; sd < nsensordevs; ++sd) {
                char xname[17];
                memset(xname, 0, sizeof(xname));
                strncpy(xname, sensordevs[sd].xname, 16);
                printf(
                        "num: %d\n"
                        "xname: %s\n"
                        "sensors_count: %d\n",
                        sensordevs[sd].num,
                        xname,
                        sensordevs[sd].sensors_count);
                for(int st = 0; st < SENSOR_MAX_TYPES; ++st) {
                    if(sensordevs[sd].maxnumt[st] == 0) continue;
                    for(int s = 0; s < sensordevs[sd].maxnumt[st]; ++s) {
                        struct sensor sensor;
                        memset(&sensor, 0, sizeof(struct sensor));
                        mib[2] = sensordevs[sd].num;
                        mib[3] = st;
                        mib[4] = s;
                        if(-1 == sysctl(mib, 5, &sensor, &sensorlen, NULL, 0)) {
                            warn("Failed to get sensors of type %d for
sd %d for dev %d", st, sd, dev);
                            continue;
                        }
                        char desc[33];
                        memset(desc, 0, sizeof(desc));
                        strncpy(desc, sensor.desc, 32);
                        printf("\n");
                        printf(
                                "\tName: %s\n"
                                "\tValue: %llx\n"
                                "\tType: %d (%s)\n"
                                "\tnumt: %d\n",
                                desc,
                                sensor.value,
                                sensor.type, sensor_type_names[sensor.type],
                                sensor.numt);
                    } // for each sensor
                } // for each sensor type
            } // for each sensordev
            free(sensordevs);
        } // for each dev
        return 0;
    }

Compile with `cc -o sensors -g -O0 sensors.c` or whatever you usually do.

Output on my Toshiba NB250-101 running OpenBSD 7.2:

    Device 0, 1 sensordevs
    num: 0
    xname: acpiac0
    sensors_count: 1

        Name: power supply
        Value: 1
        Type: 9 (SENSOR_INDICATOR)
        numt: 0
    Device 1, 1 sensordevs
    num: 1
    xname: acpibat0
    sensors_count: 9

        Name: voltage
        Value: a4cb80
        Type: 2 (SENSOR_VOLTS_DC)
        numt: 0

        Name: current voltage
        Value: bf40f0
        Type: 2 (SENSOR_VOLTS_DC)
        numt: 1

        Name: rate
        Value: 3e7fc18
        Type: 6 (SENSOR_AMPS)
        numt: 0

        Name: last full capacity
        Value: 423d08
        Type: 8 (SENSOR_AMPHOUR)
        numt: 0

        Name: warning capacity
        Value: 68fb0
        Type: 8 (SENSOR_AMPHOUR)
        numt: 1

        Name: low capacity
        Value: 1f7e8
        Type: 8 (SENSOR_AMPHOUR)
        numt: 2

        Name: remaining capacity
        Value: 423d08
        Type: 8 (SENSOR_AMPHOUR)
        numt: 3

        Name: design capacity
        Value: 432380
        Type: 8 (SENSOR_AMPHOUR)
        numt: 4

        Name: battery full
        Value: 80
        Type: 10 (SENSOR_INTEGER)
        numt: 0
    Device 2, 1 sensordevs
    num: 2
    xname: acpibtn0
    sensors_count: 1

        Name: lid open
        Value: 1
        Type: 9 (SENSOR_INDICATOR)
        numt: 0
    Device 3, 1 sensordevs
    num: 3
    xname: cpu0
    sensors_count: 1

        Name:
        Value: 14093df0
        Type: 0 (SENSOR_TEMP)
        numt: 0
    Device 4, 1 sensordevs
    num: 4
    xname: softraid0
    sensors_count: 0

Strangely enough, the temperature sensor on this laptop seems to
be nameless. Huh.

Best regards,
Vlad Meşco



P.S., I really was not sure what the best way to get in touch with the
developer was, so I posted here. I hope it reaches them <3

Reply via email to