>Synopsis: apmd(8) poll timer off by 10x
>Category: system
>Environment:
System : OpenBSD 6.3
Details : OpenBSD 6.3-current (GENERIC.MP) #54: Wed May 30 23:03:50
MDT 2018
[email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
Architecture: OpenBSD.amd64
Machine : amd64
>Description:
With apmd_flags="-Az10", expected apmd(8) to suspend when
battery is at 10%, however, it didn't check in time and
laptop ran of out power.
>How-To-Repeat:
Disconnect A/C adapter and run with -z percent greater
than current estimated battery life reported by apm(8);
poll every minute, for example...
# rcctl stop apmd
# apmd -A -z90 -t60
should suspend in a minute, however, it suspends after 10
minutes.
>Fix:
The following diff...
1. Provides a dedicated timer that fires every 10 seconds
instead of relying on EVFILT_READ freqency.
2. Increments a counter and checks against timeout value,
if it exceeds, invokes auto-action.
3. Wraps a few long lines that exceed 80 cols upon code
shuffle.
Index: apmd.c
===================================================================
RCS file: /cvs/src/usr.sbin/apmd/apmd.c,v
retrieving revision 1.81
diff -u -p -w -r1.81 apmd.c
--- apmd.c 15 Oct 2017 15:14:49 -0000 1.81
+++ apmd.c 7 Jun 2018 10:56:06 -0000
@@ -56,6 +56,9 @@
#define AUTO_SUSPEND 1
#define AUTO_HIBERNATE 2
+#define TIMO (10*60) /* 10 minutes */
+#define TIMER_ID 1
+
const char apmdev[] = _PATH_APM_CTLDEV;
const char sockfile[] = _PATH_APM_SOCKET;
@@ -341,8 +344,6 @@ hibernate(int ctl_fd)
ioctl(ctl_fd, APM_IOC_HIBERNATE, 0);
}
-#define TIMO (10*60) /* 10 minutes */
-
int
main(int argc, char *argv[])
{
@@ -353,13 +354,12 @@ main(int argc, char *argv[])
int statonly = 0;
int powerstatus = 0, powerbak = 0, powerchange = 0;
int noacsleep = 0;
- struct timespec ts = {TIMO, 0}, sts = {0, 0};
struct apm_power_info pinfo;
- time_t apmtimeout = 0;
+ time_t apmtimeout = TIMO, counter = 0;
const char *sockname = sockfile;
const char *errstr;
int kq, nchanges;
- struct kevent ev[2];
+ struct kevent ev[3];
int ncpu_mib[2] = { CTL_HW, HW_NCPU };
int ncpu;
size_t ncpu_sz = sizeof(ncpu);
@@ -379,8 +379,8 @@ main(int argc, char *argv[])
sockname = optarg;
break;
case 't':
- ts.tv_sec = strtoul(optarg, NULL, 0);
- if (ts.tv_sec == 0)
+ apmtimeout = strtoul(optarg, NULL, 0);
+ if (apmtimeout == 0)
usage();
break;
case 's': /* status only */
@@ -466,14 +466,15 @@ main(int argc, char *argv[])
EV_SET(&ev[0], sock_fd, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR,
0, 0, NULL);
+ EV_SET(&ev[1], TIMER_ID, EVFILT_TIMER, EV_ADD, 0, 10000, NULL);
if (ctl_fd == -1)
- nchanges = 1;
+ nchanges = 2;
else {
- EV_SET(&ev[1], ctl_fd, EVFILT_READ, EV_ADD | EV_ENABLE |
+ EV_SET(&ev[2], ctl_fd, EVFILT_READ, EV_ADD | EV_ENABLE |
EV_CLEAR, 0, 0, NULL);
- nchanges = 2;
+ nchanges = 3;
}
- if (kevent(kq, ev, nchanges, NULL, 0, &sts) < 0)
+ if (kevent(kq, ev, nchanges, NULL, 0, NULL) < 0)
error("kevent", NULL);
if (sysctl(ncpu_mib, 2, &ncpu, &ncpu_sz, NULL, 0) < 0)
@@ -482,41 +483,14 @@ main(int argc, char *argv[])
for (;;) {
int rv;
- sts = ts;
-
- apmtimeout += 1;
- if ((rv = kevent(kq, NULL, 0, ev, 1, &sts)) < 0)
+ if ((rv = kevent(kq, NULL, 0, ev, 1, NULL)) < 0)
break;
- if (apmtimeout >= ts.tv_sec) {
- apmtimeout = 0;
-
- /* wakeup for timeout: take status */
- powerbak = power_status(ctl_fd, 0, &pinfo);
- if (powerstatus != powerbak) {
- powerstatus = powerbak;
- powerchange = 1;
- }
-
- if (!powerstatus && autoaction &&
- autolimit > (int)pinfo.battery_life) {
- syslog(LOG_NOTICE,
- "estimated battery life %d%%, "
- "autoaction limit set to %d%% .",
- pinfo.battery_life,
- autolimit
- );
-
- if (autoaction == AUTO_SUSPEND)
- suspend(ctl_fd);
- else
- hibernate(ctl_fd);
- }
- }
-
if (!rv)
continue;
+ switch (ev->filter) {
+ case EVFILT_READ:
if (ev->ident == ctl_fd) {
suspends = standbys = hibernates = resumes = 0;
syslog(LOG_DEBUG, "apmevent %04x index %d",
@@ -545,7 +519,8 @@ main(int argc, char *argv[])
case APM_NORMAL_RESUME:
case APM_CRIT_RESUME:
case APM_SYS_STANDBY_RESUME:
- powerbak = power_status(ctl_fd, 0, &pinfo);
+ powerbak = power_status(ctl_fd, 0,
+ &pinfo);
if (powerstatus != powerbak) {
powerstatus = powerbak;
powerchange = 1;
@@ -553,7 +528,8 @@ main(int argc, char *argv[])
resumes++;
break;
case APM_POWER_CHANGE:
- powerbak = power_status(ctl_fd, 0, &pinfo);
+ powerbak = power_status(ctl_fd, 0,
+ &pinfo);
if (powerstatus != powerbak) {
powerstatus = powerbak;
powerchange = 1;
@@ -565,7 +541,8 @@ main(int argc, char *argv[])
if ((standbys || suspends) && noacsleep &&
power_status(ctl_fd, 0, &pinfo))
- syslog(LOG_DEBUG, "no! sleep! till brooklyn!");
+ syslog(LOG_DEBUG,
+ "no! sleep! till brooklyn!");
else if (suspends)
suspend(ctl_fd);
else if (standbys)
@@ -579,9 +556,8 @@ main(int argc, char *argv[])
}
if (powerchange) {
- if (powerstatus)
- do_etc_file(_PATH_APM_ETC_POWERUP);
- else
+ powerstatus ?
+ do_etc_file(_PATH_APM_ETC_POWERUP) :
do_etc_file(_PATH_APM_ETC_POWERDOWN);
powerchange = 0;
}
@@ -600,6 +576,40 @@ main(int argc, char *argv[])
hibernate(ctl_fd);
break;
}
+
+ break;
+ case EVFILT_TIMER:
+ if (ev->ident != TIMER_ID)
+ error("invalid timer id", NULL);
+
+ counter += 10;
+ if (counter >= apmtimeout) {
+ counter = 0;
+
+ /* wakeup for timeout: take status */
+ powerbak = power_status(ctl_fd, 0, &pinfo);
+ if (powerstatus != powerbak) {
+ powerstatus = powerbak;
+ powerchange = 1;
+ }
+
+ if (!powerstatus && autoaction &&
+ autolimit > (int)pinfo.battery_life) {
+ syslog(LOG_NOTICE,
+ "estimated battery life %d%%, "
+ "autoaction limit set to %d%% .",
+ pinfo.battery_life,
+ autolimit
+ );
+
+ if (autoaction == AUTO_SUSPEND)
+ suspend(ctl_fd);
+ else
+ hibernate(ctl_fd);
+ }
+ }
+ break;
+ }
}
error("kevent loop", NULL);
dmesg:
OpenBSD 6.3-current (GENERIC.MP) #54: Wed May 30 23:03:50 MDT 2018
[email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
real mem = 16844517376 (16064MB)
avail mem = 16325857280 (15569MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.7 @ 0xdae9d000 (68 entries)
bios0: vendor LENOVO version "G2ET99WW (2.59 )" date 12/04/2013
bios0: LENOVO 23252EG
acpi0 at bios0: rev 2
acpi0: sleep states S0 S3 S4 S5
acpi0: tables DSDT FACP SLIC TCPA SSDT SSDT SSDT HPET APIC MCFG ECDT FPDT ASF!
UEFI UEFI POAT SSDT SSDT DMAR UEFI DBG2
acpi0: wakeup devices LID_(S4) SLPB(S3) IGBE(S4) EXP3(S4) XHCI(S3) EHC1(S3)
EHC2(S3) HDEF(S4)
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpihpet0 at acpi0: 14318179 Hz
Acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz, 1197.50 MHz
cpu0:
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,RDTSCP,LONG,LAHF,PERF,ITSC,FSGSBASE,SMEP,ERMS,IBRS,IBPB,STIBP,SENSOR,ARAT,MELTDOWN
cpu0: 256KB 64b/line 8-way L2 cache
cpu0: smt 0, core 0, package 0
mtrr: Pentium Pro MTRR support, 10 var ranges, 88 fixed ranges
using xsaveopt
cpu0: apic clock running at 99MHz
cpu0: mwait min=64, max=64, C-substates=0.2.1.1.2, IBE
cpu1 at mainbus0: apid 1 (application processor)
cpu1: Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz, 1197.29 MHz
cpu1:
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,RDTSCP,LONG,LAHF,PERF,ITSC,FSGSBASE,SMEP,ERMS,IBRS,IBPB,STIBP,SENSOR,ARAT,MELTDOWN
cpu1: 256KB 64b/line 8-way L2 cache
cpu1: smt 1, core 0, package 0
cpu2 at mainbus0: apid 2 (application processor)
cpu2: Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz, 1197.29 MHz
cpu2:
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,RDTSCP,LONG,LAHF,PERF,ITSC,FSGSBASE,SMEP,ERMS,IBRS,IBPB,STIBP,SENSOR,ARAT,MELTDOWN
cpu2: 256KB 64b/line 8-way L2 cache
cpu2: smt 0, core 1, package 0
cpu3 at mainbus0: apid 3 (application processor)
cpu3: Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz, 1197.29 MHz
cpu3:
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,RDTSCP,LONG,LAHF,PERF,ITSC,FSGSBASE,SMEP,ERMS,IBRS,IBPB,STIBP,SENSOR,ARAT,MELTDOWN
cpu3: 256KB 64b/line 8-way L2 cache
cpu3: smt 1, core 1, package 0
ioapic0 at mainbus0: apid 2 pa 0xfec00000, version 20, 24 pins
acpimcfg0 at acpi0 addr 0xf8000000, bus 0-63
acpiec0 at acpi0
acpiprt0 at acpi0: bus 0 (PCI0)
acpiprt1 at acpi0: bus -1 (PEG_)
acpiprt2 at acpi0: bus 2 (EXP1)
acpiprt3 at acpi0: bus 3 (EXP2)
acpiprt4 at acpi0: bus 4 (EXP3)
acpicpu0 at acpi0: C3(200@87 mwait.1@0x30), C2(500@59 mwait.1@0x10), C1(1000@1
mwait.1), PSS
acpicpu1 at acpi0: C3(200@87 mwait.1@0x30), C2(500@59 mwait.1@0x10), C1(1000@1
mwait.1), PSS
acpicpu2 at acpi0: C3(200@87 mwait.1@0x30), C2(500@59 mwait.1@0x10), C1(1000@1
mwait.1), PSS
acpicpu3 at acpi0: C3(200@87 mwait.1@0x30), C2(500@59 mwait.1@0x10), C1(1000@1
mwait.1), PSS
acpipwrres0 at acpi0: PUBS, resource for XHCI, EHC1, EHC2
acpitz0 at acpi0: critical temperature is 103 degC
acpibtn0 at acpi0: LID_
acpibtn1 at acpi0: SLPB
acpicmos0 at acpi0
"LEN0071" at acpi0 not configured
"LEN0020" at acpi0 not configured
"SMO1200" at acpi0 not configured
acpibat0 at acpi0: BAT0 model "45N1027" serial 4492 type LION oem "SANYO"
acpiac0 at acpi0: AC unit offline
"LEN0078" at acpi0 not configured
acpithinkpad0 at acpi0
"PNP0C14" at acpi0 not configured
"PNP0C14" at acpi0 not configured
acpidock0 at acpi0: GDCK not docked (0)
acpivideo0 at acpi0: VID_
acpivout at acpivideo0 not configured
acpivideo1 at acpi0: VID_
cpu0: Enhanced SpeedStep 1197 MHz: speeds: 2901, 2900, 2800, 2700, 2500, 2400,
2300, 2200, 2000, 1900, 1800, 1700, 1600, 1400, 1300, 1200 MHz
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "Intel Core 3G Host" rev 0x09
inteldrm0 at pci0 dev 2 function 0 "Intel HD Graphics 4000" rev 0x09
drm0 at inteldrm0
inteldrm0: msi
inteldrm0: 1366x768, 32bpp
wsdisplay0 at inteldrm0 mux 1: console (std, vt100 emulation)
wsdisplay0: screen 1-5 added (std, vt100 emulation)
xhci0 at pci0 dev 20 function 0 "Intel 7 Series xHCI" rev 0x04: msi, xHCI 1.0
usb0 at xhci0: USB revision 3.0
uhub0 at usb0 configuration 1 interface 0 "Intel xHCI root hub" rev 3.00/1.00
addr 1
"Intel 7 Series MEI" rev 0x04 at pci0 dev 22 function 0 not configured
em0 at pci0 dev 25 function 0 "Intel 82579LM" rev 0x04: msi, address
3c:97:0e:48:bd:49
ehci0 at pci0 dev 26 function 0 "Intel 7 Series USB" rev 0x04: apic 2 int 16
usb1 at ehci0: USB revision 2.0
uhub1 at usb1 configuration 1 interface 0 "Intel EHCI root hub" rev 2.00/1.00
addr 1
azalia0 at pci0 dev 27 function 0 "Intel 7 Series HD Audio" rev 0x04: msi
azalia0: codecs: Realtek ALC269, Intel/0x2806, using Realtek ALC269
audio0 at azalia0
ppb0 at pci0 dev 28 function 0 "Intel 7 Series PCIE" rev 0xc4: msi
pci1 at ppb0 bus 2
sdhc0 at pci1 dev 0 function 0 "Ricoh 5U822 SD/MMC" rev 0x07: apic 2 int 16
sdhc0: SDHC 3.0, 50 MHz base clock
sdmmc0 at sdhc0: 4-bit, sd high-speed, mmc high-speed, dma
ppb1 at pci0 dev 28 function 1 "Intel 7 Series PCIE" rev 0xc4: msi
pci2 at ppb1 bus 3
iwn0 at pci2 dev 0 function 0 "Intel Centrino Advanced-N 6205" rev 0x34: msi,
MIMO 2T2R, MoW, address 6c:88:14:70:92:08
ppb2 at pci0 dev 28 function 2 "Intel 7 Series PCIE" rev 0xc4: msi
pci3 at ppb2 bus 4
ehci1 at pci0 dev 29 function 0 "Intel 7 Series USB" rev 0x04: apic 2 int 23
usb2 at ehci1: USB revision 2.0
uhub2 at usb2 configuration 1 interface 0 "Intel EHCI root hub" rev 2.00/1.00
addr 1
pcib0 at pci0 dev 31 function 0 "Intel QM77 LPC" rev 0x04
ahci0 at pci0 dev 31 function 2 "Intel 7 Series AHCI" rev 0x04: msi, AHCI 1.3
ahci0: port 0: 6.0Gb/s
scsibus1 at ahci0: 32 targets
sd0 at scsibus1 targ 0 lun 0: <ATA, INTEL SSDSC2BW18, LE1i> SCSI3 0/direct
fixed naa.5001517bb28b066b
sd0: 171705MB, 512 bytes/sector, 351651888 sectors, thin
ichiic0 at pci0 dev 31 function 3 "Intel 7 Series SMBus" rev 0x04: apic 2 int 18
iic0 at ichiic0
spdmem0 at iic0 addr 0x50: 8GB DDR3 SDRAM PC3-12800 SO-DIMM
spdmem1 at iic0 addr 0x51: 8GB DDR3 SDRAM PC3-12800 SO-DIMM
isa0 at pcib0
isadma0 at isa0
pckbc0 at isa0 port 0x60/5 irq 1 irq 12
pckbd0 at pckbc0 (kbd slot)
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pms0 at pckbc0 (aux slot)
wsmouse0 at pms0 mux 0
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
vmm0 at mainbus0: VMX/EPT
error: [drm:pid0:cpt_set_fifo_underrun_reporting] *ERROR* uncleared pch fifo
underrun on pch transcoder A
error: [drm:pid0:intel_pch_fifo_underrun_irq_handler] *ERROR* PCH transcoder A
FIFO underrun
umodem0 at uhub0 port 4 configuration 1 interface 1 "Lenovo H5321 gw" rev
2.00/0.00 addr 2
umodem0: data interface 2, has CM over data, has break
umodem0: status change notification available
ucom0 at umodem0
umodem1 at uhub0 port 4 configuration 1 interface 3 "Lenovo H5321 gw" rev
2.00/0.00 addr 2
umodem1: data interface 4, has CM over data, has break
umodem1: status change notification available
ucom1 at umodem1
umodem2 at uhub0 port 4 configuration 1 interface 9 "Lenovo H5321 gw" rev
2.00/0.00 addr 2
umodem2: data interface 10, has CM over data, has break
umodem2: status change notification available
ucom2 at umodem2
ugen0 at uhub0 port 4 configuration 1 "Lenovo H5321 gw" rev 2.00/0.00 addr 2
uhub3 at uhub1 port 1 configuration 1 interface 0 "Intel Rate Matching Hub" rev
2.00/0.00 addr 2
umass0 at uhub3 port 2 configuration 1 interface 0 "Corsair Flash Voyager" rev
2.00/11.00 addr 3
umass0: using SCSI over Bulk-Only
scsibus2 at umass0: 2 targets, initiator 0
sd1 at scsibus2 targ 1 lun 0: <Corsair, Flash Voyager, 1100> SCSI0 0/direct
removable serial.090c1000000000000288
sd1: 483MB, 512 bytes/sector, 990208 sectors
ugen1 at uhub3 port 3 "Auth Biometric Coprocessor" rev 1.10/0.01 addr 4
ugen2 at uhub3 port 4 "Broadcom Corp BCM20702A0" rev 2.00/1.12 addr 5
uvideo0 at uhub3 port 6 configuration 1 interface 0 "Chicony Electronics Co.,
Ltd. Integrated Camera" rev 2.00/5.18 addr 6
video0 at uvideo0
uhub4 at uhub2 port 1 configuration 1 interface 0 "Intel Rate Matching Hub" rev
2.00/0.00 addr 2
vscsi0 at root
scsibus3 at vscsi0: 256 targets
softraid0 at root
scsibus4 at softraid0: 256 targets
sd2 at scsibus4 targ 1 lun 0: <OPENBSD, SR CRYPTO, 006> SCSI2 0/direct fixed
sd2: 171702MB, 512 bytes/sector, 351646193 sectors
root on sd2a (0803bf6b6750ef01.a) swap on sd2b dump on sd2b
usbdevs:
Controller /dev/usb0:
addr 1: super speed, self powered, config 1, xHCI root hub(0x0000),
Intel(0x8086), rev 1.00
port 1 disabled
port 2 disabled
port 3 disabled
port 4 addr 2: high speed, self powered, config 1, H5321 gw(0x1926),
Lenovo(0x0bdb), rev 0.00, iSerialNumber 50DE928394CDDEC0
port 5 disabled
port 6 disabled
port 7 disabled
port 8 disabled
Controller /dev/usb1:
addr 1: high speed, self powered, config 1, EHCI root hub(0x0000),
Intel(0x8086), rev 1.00
port 1 addr 2: high speed, self powered, config 1, Rate Matching Hub(0x0024),
Intel(0x8087), rev 0.00
port 1 powered
port 2 powered
port 3 addr 4: full speed, power 100 mA, config 1, Biometric
Coprocessor(0x2020), Auth(0x147e), rev 0.01
port 4 addr 5: full speed, self powered, config 1, BCM20702A0(0x21e6),
Broadcom Corp(0x0a5c), rev 1.12, iSerialNumber 9CB70DD09CA7
port 5 powered
port 6 addr 6: high speed, power 200 mA, config 1, Integrated Camera(0xb2ea),
Chicony Electronics Co., Ltd.(0x04f2), rev 5.18
port 2 powered
port 3 powered
Controller /dev/usb2:
addr 1: high speed, self powered, config 1, EHCI root hub(0x0000),
Intel(0x8086), rev 1.00
port 1 addr 2: high speed, self powered, config 1, Rate Matching Hub(0x0024),
Intel(0x8087), rev 0.00
port 1 powered
port 2 powered
port 3 powered
port 4 powered
port 5 powered
port 6 powered
port 7 powered
port 8 powered
port 2 powered
port 3 powered