From f0669f3ed0b300ebd5567afc3c1dd2d179551dc6 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Mon, 26 Jan 2015 09:08:01 -0500 Subject: Implement and document the buzzkill option. All regression tests pass. --- SConstruct | 1 + build.txt | 34 ++++++++++++++++++++++++++++++++++ gpsd.c | 18 +++++++++++++----- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/SConstruct b/SConstruct index f379e624..211c9a1b 100644 --- a/SConstruct +++ b/SConstruct @@ -155,6 +155,7 @@ boolopts = ( ("nofloats", False, "float ops are expensive, suppress error estimates"), ("squelch", False, "squelch gpsd_report/gpsd_hexdump to save cpu"), ("ncurses", True, "build with ncurses"), + ("buzzkill", True, "adaptive-delay logic to cope with select buzzing"), # Build control ("shared", True, "build shared libraries, not static"), ("implicit_link", imloads,"implicit linkage is supported in shared libs"), diff --git a/build.txt b/build.txt index 2847be60..baffd00b 100644 --- a/build.txt +++ b/build.txt @@ -352,6 +352,40 @@ scons minimal=yes socket_export=yes nmea0183=yes will do that. +== Configuration problem cases + +This section describes cases in which the default build is known to be +unavoidably broken and a custom configuration is required to do the +right thing. + +Presently there is only one such case; buzzkill=yes (the default) can +conflict with nmea2000=yes (the default), causing problems if you try +to watch both a CAN/NMEA2000 device and a serial device. The only +remedy is a custom build with buzzkill=no. + +The buzzkill option is intended to thwart problems due to gpsd's main +select(2) loop buzzing (spinning too fast). On battery-powered SBCs +and mobile devices this can cause serious and unnecessary power drain; +this has been observed on the Raspberry Pi and sporadically on +particular Android phone hardware. There are at least two reasons it +can happen; one is defective select(2) device-driver hooks that return +a data-ready when they shouldn't, the other is tty layers that return +data in single characters or small packets even when it's arriving in +packet-sized chunks. + +GPSD with buzzkill=yes watches the incoming data rate from all devices +and adaptively inserts delays in the main loop if it thinks it sees +buzzing. This logic is routed around if all devices have types that never +require delays, notably pseudo-ttys and UDP packet streams. + +With nmea2000=yes the code tries to read NME2000 packets from a CANbus +interface at high speed. The resulting data flow can look like +buzzing, but the CAN driver pretends to be a pseudo-tty to avoid delay +insertion. The problem arises if you try to watch both a conventional +tty and a CAN interface at the same time; this foils the buzzkill +guard, and you will lose CAN packets due to inserted delays. To +prevent this, build with buzzkill=no. + == Port and toolchain testing == 'scons check' will run a comprehensive regression-test suite. You diff --git a/gpsd.c b/gpsd.c index 1f89d1b8..efaa8d09 100644 --- a/gpsd.c +++ b/gpsd.c @@ -1778,6 +1778,7 @@ static void gpsd_terminate(struct gps_context_t *context CONDITIONALLY_UNUSED) #endif /* PPS_ENABLE */ } +#ifdef BUZZKILL_ENABLE static void adaptive_delay(void) /* sleep a calculated time only if we have a buggy select() */ { @@ -1826,6 +1827,7 @@ static void adaptive_delay(void) } return; } +#endif /* BUZZKILL_ENABLE */ /*@ -mustfreefresh @*/ int main(int argc, char *argv[]) @@ -2206,14 +2208,20 @@ int main(int argc, char *argv[]) while (0 == signalled) { fd_set efds; +#ifdef BUZZKILL_ENABLE /* - * Adaptive delay to prevent buzzing if the tty layer returns data - * one character at a time and too fast. This pushes CPU usage up and - * eats power. This has been directly observed as a problem on the - * Raspberry Pi, and is probably behind occasional reports of - * GPSD-related excessive power drain on Android phones. + * Adaptive delay to prevent buzzing if the tty layer returns + * data one character at a time and too fast. Buzzing pushes + * CPU usage up and eats power. + * + * This has been directly observed as a problem on the + * Raspberry Pi. A buzzing problem with outright defective + * select(2) implementations is probably behind occasional + * reports of GPSD-related excessive power drain on Android + * phones. */ (void) adaptive_delay(); +#endif /* BUZZKILL_ENABLE */ switch(gpsd_await_data(&rfds, &efds, maxfd, &all_fds, &context.errout)) { -- cgit v1.2.1