For example, there is a Thread X make some I/O request.
Thread X
-> request reading file A -> Non-blocking I/O request to read file -> DMA write data back to MEM -> interrupt CPU
-> request reading file B -> Non-blocking I/O request to read file -> DMA write data back to MEM -> interrupt CPU
Thread X is not blocked there to wait for any response. The hardware controller will handle I/O operation and write data back to MEM with the DMA mechanism, then interrupt the CPU to inform the I/O is finished.
My question is, after the I/O operations finish, what is a mechanism to trigger Thread X or any other idle threads to get response data of the corresponding request?
Since the data is now stored in MEM, the hardware controller interrupts (informs) the CPU. So, how does the CPU interact with an available thread to get the response data from MEM?
Does CPU/OS maintain an event list somewhere to help map the thread request info to the response data stored in MEM?
Since the application is easy to maintain what threads are requested. Ideally, they are stored in a queue. However, I have no clue how the thread knows and read data from MEM after a non-blocking I/O finish.
All above is just my understanding, please correct me if I misunderstood somewhere.
In Java NIO the File API is not non-blocking. It is still blocking - as far as I know (it was last time I checked).
However, the SocketChannel API can run in non-blocking mode.
In non-blocking mode, the thread reading bytes from a SocketChannel only gets whatever bytes are ready immediately. Bytes that arrive later will be returned the next time the SocketChannel calls the .read() method.
If a thread is not blocked waiting for an IO operation to finish, there is no way for the background IO functionality to notify the thread that bytes are ready. Only when the thread decides to check for ready bytes the next time - will the thread detect the new bytes. This check can be directly on a SocketChannel or via a Selector which can check across many SocketChannel's.
In general, non-blocking IO is quite hard to control well. That is why we are now getting the virtual threads (Project Loom) - but they will not really solve the problems for "routers" - only for "servers" (too long to elaborate here).