|
<< Click to Display Table of Contents >> Navigation: ASA-EMulatR Reference Guide > Introduction > Architecture Overview > Chapter 16 – Device Model & DMA > 16.4 Asynchronous Device Threading (QThread Model) |
EMulatR uses Qt's QThread framework for all concurrent execution. Each AlphaCPU runs in its own QThread (managed by ExecutionCoordinator), and device I/O operations that cannot complete synchronously are dispatched to dedicated device worker threads.
The threading model enforces a strict separation between the CPU execution path and device I/O:
•CPU threads (one per vCPU) — Execute guest instructions, handle MMIO reads/writes synchronously, poll for interrupts. MMIO handler calls (onRead, onWrite) execute in the calling CPU's thread and must return immediately.
•Device I/O threads (per device or per manager) — Perform host-side disk I/O, network packet transmission/reception, DMA data movement, and long-running device operations. These threads are created by the device managers and communicate completion back to the CPU path via interrupt assertion.
The IDeviceEmulator contract explicitly specifies that onRead() and onWrite() must return immediately — they may not block on I/O. If an MMIO write triggers a long-running operation (e.g., a SCSI command that involves host-side disk access), the device handler queues the work to its I/O thread and returns MMIOStatus::OK. The I/O thread performs the actual work and asserts an interrupt upon completion.
Within a single device emulator, I/O operations must be serialized to preserve command ordering. When multiple vCPUs concurrently access the same device's MMIO registers, the device must ensure that:
•Register reads and writes are atomic with respect to the device's internal state
•Command submission ordering is preserved when one CPU writes a command register that another CPU also targets
•DMA descriptor reads occur after the CPU's writes are visible (enforced by the drainPostedWrites() pattern)
Device emulators typically use a QMutex to protect their internal register state and a command queue (QQueue or ring buffer) to serialize I/O requests submitted to the worker thread. The worker thread drains the command queue sequentially, performing host-side I/O for each request.
Different device managers operate independently. A SCSI disk I/O operation does not serialize against a network packet transmission. This concurrency is both intentional and necessary — real Alpha systems execute multiple device operations simultaneously, and guest OS drivers expect this parallelism. The shared resources that require cross-device synchronization are limited to GuestMemory (for DMA), the IRQ system (for interrupt assertion), and the DMACoherencyManager (for cache coherency operations).
See Also: 9.3 CPU Instantiation and Identity (QThread per CPU); mmioLib/IDeviceEmulator.h – onRead/onWrite threading contract.