ratchov 1cdc22aca6 Use the new sioctl_open(3) interface in place of /dev/mixer
Now xstatbar shows the same control as "sndioctl output.level".

ok sthen, rsadowski
2020-04-16 06:54:41 +00:00

405 lines
14 KiB
Plaintext

$OpenBSD: patch-stats_c,v 1.11 2020/04/16 06:54:41 ratchov Exp $
If devinfo.type != AUDIO_MIXER_CLASS is true, xstatbar will never make
progress and loop forever. Fix it by trying the next device.
Index: stats.c
--- stats.c.orig
+++ stats.c
@@ -61,118 +61,104 @@ fmtmem(int m)
* volume stuff
****************************************************************************/
-int
-volume_check_dev(int fd, int class, char *name)
+/*
+ * new control
+ */
+void
+volume_ondesc(void *unused, struct sioctl_desc *d, int val)
{
- mixer_devinfo_t devinfo;
+ if (d == NULL)
+ return;
- if (class < 0 || name == NULL)
- return (-1);
+ if (d->addr == volume.left_addr)
+ volume.left_addr = -1;
+ if (d->addr == volume.right_addr)
+ volume.right_addr = -1;
- devinfo.index = 0;
- while (ioctl(fd, AUDIO_MIXER_DEVINFO, &devinfo) >= 0) {
- if ((devinfo.type == AUDIO_MIXER_VALUE)
- && (devinfo.mixer_class == class)
- && (strncmp(devinfo.label.name, name, MAX_AUDIO_DEV_LEN) == 0))
- return (devinfo.index);
+ if (d->type == SIOCTL_NUM &&
+ strcmp(d->group, "") == 0 &&
+ strcmp(d->node0.name, "output") == 0 &&
+ strcmp(d->func, "level") == 0) {
- devinfo.index++;
+ switch (d->node0.unit) {
+ case -1: /* mono */
+ case 0: /* left */
+ volume.left_addr = d->addr;
+ volume.left_max = d->maxval;
+ volume.left = val;
+ break;
+ case 1: /* right */
+ volume.right_addr = d->addr;
+ volume.right_max = d->maxval;
+ volume.right = val;
+ }
}
+}
- return (-1);
+/*
+ * control value changed
+ */
+void
+volume_onval(void *unused, unsigned int addr, unsigned int value)
+{
+ if (addr == volume.left_addr)
+ volume.left = value;
+ if (addr == volume.right_addr)
+ volume.right = value;
}
void
volume_init()
{
- mixer_devinfo_t devinfo;
- int oclass_idx, iclass_idx;
-
volume.is_setup = false;
+ volume.left_addr = volume.right_addr = -1;
- /* open mixer */
- if ((volume.dev_fd = open("/dev/mixer", O_RDWR)) < 0) {
- warn("volume: failed to open /dev/mixer");
+ if ((volume.hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0)) == NULL) {
+ warn("volume: failed to open default device");
return;
}
- /* find the outputs and inputs classes */
- oclass_idx = iclass_idx = -1;
- devinfo.index = 0;
- while (ioctl(volume.dev_fd, AUDIO_MIXER_DEVINFO, &devinfo) >= 0) {
-
- if (devinfo.type != AUDIO_MIXER_CLASS)
- continue;
-
- if (strncmp(devinfo.label.name, AudioCoutputs, MAX_AUDIO_DEV_LEN) == 0)
- oclass_idx = devinfo.index;
- if (strncmp(devinfo.label.name, AudioCinputs, MAX_AUDIO_DEV_LEN) == 0)
- iclass_idx = devinfo.index;
-
- if (oclass_idx != -1 && iclass_idx != -1)
- break;
-
- devinfo.index++;
+ volume.pfds = calloc(sioctl_nfds(volume.hdl), sizeof(struct pollfd));
+ if (volume.pfds == NULL) {
+ warnx("volume: cannot allocate pfds\n");
+ goto bad_close;
}
+
- /* find the master device */
- volume.master_idx = volume_check_dev(volume.dev_fd, oclass_idx, AudioNmaster);
- if (volume.master_idx == -1)
- volume.master_idx = volume_check_dev(volume.dev_fd, iclass_idx, AudioNdac);
- if (volume.master_idx == -1)
- volume.master_idx = volume_check_dev(volume.dev_fd, oclass_idx, AudioNdac);
- if (volume.master_idx == -1)
- volume.master_idx = volume_check_dev(volume.dev_fd, oclass_idx, AudioNoutput);
-
- if (volume.master_idx == -1) {
- warnx("volume: failed to find \"master\" mixer device");
- return;
+ if (!sioctl_ondesc(volume.hdl, volume_ondesc, NULL)) {
+ warnx("volume: cannot get descriptions\n");
+ goto bad_free;
}
- devinfo.index = volume.master_idx;
- if (ioctl(volume.dev_fd, AUDIO_MIXER_DEVINFO, &devinfo) == -1) {
- warn("AUDIO_MIXER_DEVINFO");
- return;
+ if (!sioctl_onval(volume.hdl, volume_onval, NULL)) {
+ warnx("volume: cannot get values\n");
+ goto bad_free;
}
- volume.max = AUDIO_MAX_GAIN;
- volume.nchan = devinfo.un.v.num_channels;
-
- /* finished... now close the device and reopen as read only */
- close(volume.dev_fd);
- volume.dev_fd = open("/dev/mixer", O_RDONLY);
- if (volume.dev_fd < 0) {
- warn("volume: failed to re-open /dev/mixer");
- return;
- }
-
volume.is_setup = true;
+ return;
+bad_free:
+ free(volume.pfds);
+bad_close:
+ sioctl_close(volume.hdl);
}
void
volume_update()
{
- static mixer_ctrl_t vinfo;
+ int n;
if (!volume.is_setup)
return;
- /* query info */
- vinfo.dev = volume.master_idx;
- vinfo.type = AUDIO_MIXER_VALUE;
- vinfo.un.value.num_channels = volume.nchan;
- if (ioctl(volume.dev_fd, AUDIO_MIXER_READ, &(vinfo)) < 0) {
- warn("volume update: AUDIO_MIXER_READ");
- return;
+ n = sioctl_pollfd(volume.hdl, volume.pfds, POLLIN);
+ if (n > 0) {
+ n = poll(volume.pfds, n, 0);
+ if (n == -1)
+ return;
+ if (n > 0)
+ sioctl_revents(volume.hdl, volume.pfds);
}
-
- /* record in global struct */
- if (volume.nchan == 1)
- volume.left = volume.right = vinfo.un.value.level[AUDIO_MIXER_LEVEL_MONO];
- else {
- volume.left = vinfo.un.value.level[AUDIO_MIXER_LEVEL_LEFT];
- volume.right = vinfo.un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
- }
}
void
@@ -180,7 +166,7 @@ volume_close() {
if (!volume.is_setup)
return;
- close(volume.dev_fd);
+ sioctl_close(volume.hdl);
}
int
@@ -199,8 +185,9 @@ volume_draw(XColor color, int x, int y)
width = 5;
/* get volume as percents */
- left = roundf(100.0 * (float)volume.left / (float)volume.max);
- right = roundf(100.0 * (float)volume.right / (float)volume.max);
+ left = roundf(100.0 * (float)volume.left / (float)volume.left_max);
+ right = (volume.right_addr == -1) ?
+ left : roundf(100.0 * (float)volume.right / (float)volume.right_max);
/* determine height of green-part of bar graphs */
lheight = (int)(left * (float)XINFO.height / 100.0);
@@ -358,7 +345,7 @@ sysinfo_init(int hist_size)
err(1, "sysinfo init: memory calloc failed");
for (i = 0; i < hist_size; i++) {
- if ((sysinfo.memory[i] = calloc(3, sizeof(int))) == NULL)
+ if ((sysinfo.memory[i] = calloc(4, sizeof(int))) == NULL)
err(1, "sysinfo init: memory[%d] calloc failed", i);
for (j = 0; j < 3; j++)
@@ -372,6 +359,7 @@ sysinfo_init(int hist_size)
/* allocate cpu history */
sysinfo.cpu_raw = calloc(sysinfo.ncpu, sizeof(uint64_t**));
+ sysinfo.cpu_online = calloc(sysinfo.ncpu, sizeof(*sysinfo.cpu_online));
sysinfo.cpu_pcnts = calloc(sysinfo.ncpu, sizeof(int**));
if (sysinfo.cpu_raw == NULL || sysinfo.cpu_pcnts == NULL)
err(1, "sysinfo init: cpu_raw/cpu_pcnts calloc failed");
@@ -404,10 +392,14 @@ sysinfo_update()
{
static int mib_nprocs[] = { CTL_KERN, KERN_NPROCS };
static int mib_vm[] = { CTL_VM, VM_METER };
- static int mib_cpus[] = { CTL_KERN, 0, 0 };
+ static int mib_cpus[] = { CTL_KERN, KERN_CPTIME2, 0 };
+ static int mib_cpustats[] = { CTL_KERN, KERN_CPUSTATS, 0 };
+ static int mib_bcstats[] = {CTL_VFS, VFS_GENERIC, VFS_BCACHESTAT};
static int diffs[CPUSTATES] = { 0 };
struct vmtotal vminfo;
struct swapent *swapdev;
+ struct bcachestats bcstats;
+ struct cpustats cpustats;
size_t size;
int cpu, state;
int cur, prev;
@@ -431,9 +423,16 @@ sysinfo_update()
if (sysctl(mib_vm, 2, &vminfo, &size, NULL, 0) < 0)
err(1, "sysinfo update: VM.METER failed");
+ /* update bufcache statistics */
+ size = sizeof(bcstats);
+ if (sysctl(mib_bcstats, 3, &bcstats, &size, NULL, 0) < 0)
+ err(1, "sysinfo update: VFS_BCACHESTAT failed");
+
+
sysinfo.memory[cur][MEM_ACT] = vminfo.t_arm << sysinfo.pageshift;
sysinfo.memory[cur][MEM_TOT] = vminfo.t_rm << sysinfo.pageshift;
sysinfo.memory[cur][MEM_FRE] = vminfo.t_free << sysinfo.pageshift;
+ sysinfo.memory[cur][MEM_CCH] = bcstats.numbufpages << sysinfo.pageshift;
/* get swap status */
if ((nswaps = swapctl(SWAP_NSWAP, 0, 0)) == 0)
@@ -454,24 +453,15 @@ sysinfo_update()
/* get states for each cpu. note this is raw # of ticks */
size = CPUSTATES * sizeof(int64_t);
- if (sysinfo.ncpu > 1) {
- mib_cpus[1] = KERN_CPTIME2;
- for (cpu = 0; cpu < sysinfo.ncpu; cpu++) {
- mib_cpus[2] = cpu;
- if (sysctl(mib_cpus, 3, sysinfo.cpu_raw[cpu][cur], &size, NULL, 0) < 0)
- err(1, "sysinfo update: KERN.CPTIME2.%d failed", cpu);
- }
- } else {
- int i;
- long cpu_raw_tmp[CPUSTATES];
- size = sizeof(cpu_raw_tmp);
- mib_cpus[1] = KERN_CPTIME;
-
- if (sysctl(mib_cpus, 2, cpu_raw_tmp, &size, NULL, 0) < 0)
- err(1, "sysinfo update: KERN.CPTIME failed");
-
- for (i = 0; i < CPUSTATES; i++)
- sysinfo.cpu_raw[0][cur][i] = cpu_raw_tmp[i];
+ for (cpu = 0; cpu < sysinfo.ncpu; cpu++) {
+ mib_cpus[2] = cpu;
+ if (sysctl(mib_cpus, 3, sysinfo.cpu_raw[cpu][cur], &size, NULL, 0) < 0)
+ err(1, "sysinfo update: KERN.CPTIME2.%d failed", cpu);
+ mib_cpustats[2] = cpu;
+ size = sizeof(cpustats);
+ if (sysctl(mib_cpustats, 3, &cpustats, &size, NULL, 0) < 0)
+ err(1, "sysinfo update: KERN.CPUSTATS.%d failed", cpu);
+ sysinfo.cpu_online[cpu] = (cpustats.cs_flags & CPUSTATS_ONLINE) != 0;
}
/* convert ticks to percentages */
@@ -509,12 +499,16 @@ int
cpu_draw(int cpu, XColor color, int x, int y)
{
static char str[1000];
- static char *cpuStateNames[] = { "u", "n", "s", "i", "I" };
+ static char *cpuStateNames[] = { "u", "n", "s", "p", "i", "I" };
static XColor *cpuStateColors[] = {
- &COLOR_RED, &COLOR_BLUE, &COLOR_YELLOW, &COLOR_MAGENTA, &COLOR_GREEN
+ &COLOR_RED, &COLOR_BLUE, &COLOR_YELLOW, &COLOR_CYAN, &COLOR_MAGENTA, &COLOR_GREEN
};
int state, startx, time, col, h, i;
+ /* SMT CPU is offline (hw.smt=0) */
+ if(!sysinfo.cpu_online[cpu])
+ return 0;
+
startx = x;
snprintf(str, sizeof(str), "cpu%d:", cpu);
@@ -531,7 +525,7 @@ cpu_draw(int cpu, XColor color, int x, int y)
/* user time */
h = 0;
- for (i = 0; i < 4; i++) h += sysinfo.cpu_pcnts[cpu][time][i];
+ for (i = 0; i < 5; i++) h += sysinfo.cpu_pcnts[cpu][time][i];
h = h * XINFO.height / 100;
XSetForeground(XINFO.disp, XINFO.gc, COLOR_RED.pixel);
XDrawLine(XINFO.disp, XINFO.buf, XINFO.gc,
@@ -540,7 +534,7 @@ cpu_draw(int cpu, XColor color, int x, int y)
/* nice time */
h = 0;
- for (i = 1; i < 4; i++) h += sysinfo.cpu_pcnts[cpu][time][i];
+ for (i = 1; i < 5; i++) h += sysinfo.cpu_pcnts[cpu][time][i];
h = h * XINFO.height / 100;
XSetForeground(XINFO.disp, XINFO.gc, COLOR_BLUE.pixel);
XDrawLine(XINFO.disp, XINFO.buf, XINFO.gc,
@@ -549,15 +543,24 @@ cpu_draw(int cpu, XColor color, int x, int y)
/* system time */
h = 0;
- for (i = 2; i < 4; i++) h += sysinfo.cpu_pcnts[cpu][time][i];
+ for (i = 2; i < 5; i++) h += sysinfo.cpu_pcnts[cpu][time][i];
h = h * XINFO.height / 100;
XSetForeground(XINFO.disp, XINFO.gc, COLOR_YELLOW.pixel);
XDrawLine(XINFO.disp, XINFO.buf, XINFO.gc,
x + col, XINFO.height - h,
x + col, XINFO.height);
+ /* spin time */
+ h = 0;
+ for (i = 3; i < 5; i++) h += sysinfo.cpu_pcnts[cpu][time][i];
+ h = h * XINFO.height / 100;
+ XSetForeground(XINFO.disp, XINFO.gc, COLOR_CYAN.pixel);
+ XDrawLine(XINFO.disp, XINFO.buf, XINFO.gc,
+ x + col, XINFO.height - h,
+ x + col, XINFO.height);
+
/* interrupt time */
- h = sysinfo.cpu_pcnts[cpu][time][3];
+ h = sysinfo.cpu_pcnts[cpu][time][4];
h = h * XINFO.height / 100;
XSetForeground(XINFO.disp, XINFO.gc, COLOR_MAGENTA.pixel);
XDrawLine(XINFO.disp, XINFO.buf, XINFO.gc,
@@ -594,7 +597,8 @@ mem_draw(XColor color, int x, int y)
/* determine total memory */
total = sysinfo.memory[cur][MEM_ACT]
+ sysinfo.memory[cur][MEM_TOT]
- + sysinfo.memory[cur][MEM_FRE];
+ + sysinfo.memory[cur][MEM_FRE]
+ + sysinfo.memory[cur][MEM_CCH];
/* start drawing ... */
x += render_text(color, x, y, "mem:") + 1;
@@ -610,7 +614,8 @@ mem_draw(XColor color, int x, int y)
if ((sysinfo.memory[time][MEM_ACT] != 0)
|| (sysinfo.memory[time][MEM_TOT] != 0)
- || (sysinfo.memory[time][MEM_FRE] != 0)) {
+ || (sysinfo.memory[time][MEM_FRE] != 0)
+ || (sysinfo.memory[time][MEM_CCH] != 0)) {
/* draw yellow (total) bar */
@@ -627,6 +632,13 @@ mem_draw(XColor color, int x, int y)
XDrawLine(XINFO.disp, XINFO.buf, XINFO.gc,
x + col, XINFO.height - h,
x + col, XINFO.height);
+
+ /* draw magenta (cache) bar */
+ h = sysinfo.memory[time][MEM_CCH] * XINFO.height / total;
+ XSetForeground(XINFO.disp, XINFO.gc, COLOR_MAGENTA.pixel);
+ XDrawLine(XINFO.disp, XINFO.buf, XINFO.gc,
+ x + col, XINFO.height - h,
+ x + col, XINFO.height);
}
time = (time + 1) % sysinfo.hist_size;
@@ -639,6 +651,8 @@ mem_draw(XColor color, int x, int y)
x += render_text(COLOR_YELLOW, x, y, fmtmem(sysinfo.memory[cur][MEM_TOT]));
x += render_text(color, x, y, "/");
x += render_text(COLOR_GREEN, x, y, fmtmem(sysinfo.memory[cur][MEM_FRE]));
+ x += render_text(color, x, y, "/");
+ x += render_text(COLOR_MAGENTA, x, y, fmtmem(sysinfo.memory[cur][MEM_CCH]));
/* draw swap, if any is used */
if (sysinfo.swap_used > 0) {