Commit 8ce59c5a authored by Reilly Grant's avatar Reilly Grant Committed by Commit Bot

serial: Reduce latency when receiving bytes on Windows

This change reduces the latency between when a byte is received and when
it is available to script by configuring the COMMTIMEOUTS structure so
that ReadFile() return immediately rather than either waiting for the
buffer to be full or a timeout to be exceeded.

The previous timeout of 1ms was insufficient because on Windows the
minimum timing interval is frequently 16ms and so this introduced a
sizable amount of latency.

Bug: 1142799
Change-Id: Ie02cb64162dcf7ee178ab9dfcca614d63f79c13e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2522196
Auto-Submit: Reilly Grant <reillyg@chromium.org>
Reviewed-by: default avatarJames Hollyer <jameshollyer@chromium.org>
Commit-Queue: James Hollyer <jameshollyer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#825434}
parent ebc457e4
......@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/sequence_checker.h"
#include "base/task/current_thread.h"
#include "base/time/time.h"
#include "components/device_event_log/device_event_log.h"
namespace device {
......@@ -156,8 +157,22 @@ bool SerialIoHandlerWin::PostOpen() {
read_context_.reset(new base::MessagePumpForIO::IOContext());
write_context_.reset(new base::MessagePumpForIO::IOContext());
// Based on the MSDN documentation setting both ReadIntervalTimeout and
// ReadTotalTimeoutMultiplier to MAXDWORD should cause ReadFile() to return
// immediately if there is data in the buffer or when a byte arrives while
// waiting.
//
// ReadTotalTimeoutConstant is set to a value low enough to ensure that the
// timeout case is exercised frequently but high enough to avoid unnecessary
// wakeups as it is not possible to have ReadFile() return immediately when a
// byte is received without specifying a timeout.
//
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-commtimeouts#remarks
COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = 1;
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
timeouts.ReadTotalTimeoutConstant =
base::TimeDelta::FromMinutes(5).InMilliseconds();
if (!::SetCommTimeouts(file().GetPlatformFile(), &timeouts)) {
SERIAL_PLOG(DEBUG) << "Failed to set serial timeouts";
return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment