DebugServer documentation - Included a brief summary on event interrupts for blocking I/O operations in debug server implementations

This commit is contained in:
Nav
2022-03-31 21:23:04 +01:00
parent 18db2faa2d
commit a59eeac4de

View File

@@ -25,13 +25,35 @@ processed ASAP. How this is done is implementation-defined. A reference to the D
(`DebugServerComponent::eventListener`) can be passed to the server if need be (see (`DebugServerComponent::eventListener`) can be passed to the server if need be (see
`DebugServerComponent::getAvailableServersByName()` for an example of this). `DebugServerComponent::getAvailableServersByName()` for an example of this).
The server implementation does not have to service events - it can simply return from `ServerInterface::run()` upon A server implementation does not have to service events - it can simply return from `ServerInterface::run()` upon
an event being triggered. Returning from that function will allow control of the thread to be handed back to an event being triggered. Returning from that function will allow control of the thread to be handed back to
`DebugServerComponent::run()`, where any pending events will be processed. Afterwards, if the DebugServer is still `DebugServerComponent::run()`, where any pending events will be processed. Afterwards, if the DebugServer is still
running (it hasn't received an event which triggers a shutdown), the `ServerInterface::run()` function will be called running (it hasn't received an event which triggers a shutdown), the `ServerInterface::run()` function will be called
again, and control will be handed back to the server implementation. The AVR GDB server implementation employs this again, and control will be handed back to the server implementation. The AVR GDB server implementation employs this
method to ensure that events are processed ASAP. See the relevant documentation for more. method to ensure that events are processed ASAP. See the relevant documentation for more.
Any blocking I/O employed by a server implementation can support event interrupts using an
[`EventNotifier`](../Helpers/EventNotifier.hpp) and [`EpollInstance`](../Helpers/EpollInstance.hpp).
Key points:
- The `EventNotifier` class is an RAII wrapper for a Linux
[eventfd object](https://man7.org/linux/man-pages/man2/eventfd.2.html). An event can be recorded against the eventfd
object via a call to `EventNotifier::notify()`.
- The [`EventListener`](../EventManager/EventListener.hpp) class can accept an `EventNotifier` object via
`EventListener::setInterruptEventNotifier()`. If an `EventNotifier` has been set on an `EventListener`, the
`EventListener` will call `EventNotifer::notify()` everytime an event is registered for that listener.
- The `EpollInstance` class is an RAII wrapper for a Linux
[epoll instance](https://man7.org/linux/man-pages/man7/epoll.7.html). It allows us to wait for any activity on a set
of file descriptors. File descriptors can be added and removed from the epoll instance via `EpollInstance::addEntry()`
and `EpollInstance::removeEntry()`. Calling `EpollInstance::waitForEvent()` will block until there is activity on at
least one of the file descriptors, or a timeout has been reached.
With an `EventNotifer` and `EpollInstance`, one can perform a blocking I/O operation which can be interrupted by an
event. For an example of this, see the AVR GDB server implementation - it employs the method described above to allow
the interruption of blocking I/O operations when an event is triggered. Specifically,
[`GdbRspDebugServer::waitForConnection()`](./GdbRsp/GdbRspDebugServer.hpp) or
[`Gdb::Connection::read()`](./GdbRsp/Connection.hpp).
### Server implementations ### Server implementations
Currently, there is only one server implementation. Others may be added upon request. Currently, there is only one server implementation. Others may be added upon request.