Improved support for concurrent IPC requests
|Reported by:||Jiri Svoboda||Owned by:|
|Blocker for:||Depends on:|
Currently it is difficult to handle requests from one client to one server concurrently. This not only hurts parallelism, but it can lead to deadlocks and difficult-to-solve problems. Ad-hoc solving with pending requests is cumbersome.
For the purpose of concurrent requests it is useful to establish notion of two objects:
- transaction is a sequence of related IPC requests and responses (similar to a SCSI exchange)
- relation is a logical data path between a client and a server
In current code the grouping of requests/response pairs into transactions is mostly implicit. Requests and responses are paired by the kernel. A transaction often consists of sending more than one request (one with user method, other with method such as M_READ, M_WRITE, etc.) and finally waiting for all the responses In this situation concurrent requests occurring at the same phone line can be separated as long as the requests of two transactions do not intermix (responses can happen anytime, because they can be always paired with requests).
What we cannot do is allow delays between requests in a transaction or allow transactions consisting of several consecutive 'send request-wait response' cycles.
Even in the current situation, separating transactions and routing requests to appropriate fibrils can be difficult. Thus, we propose extending the async API so that the transaction to which a request belongs can be specified explicitly. The relation object is need to represent the frameworks idea of a logical connection to the server.
To sum up, the application would first create a relation to a server, start and terminate transactions on the relation, and issue requests within a transaction.
There are different possible implementation of this functionality. The currently proposed one is to use multiple physical connections (phones) for each relation, as many as there are concurrent transactions. The phones would not be hanged up immediately after finishing a transaction, but rather kept around for later use. On the server side there would be simply one fibril per connection.
The advantage of this solution is simplicity of routing, the disadvantage is the possible wasting of kernel resources (phones) if the number of concurrent transactions in tasks is bursty.
An alternative implementation proposal was to use a single phone and demux the transactions in the server's async framework. However, this would probably require sending a transaction ID with each request, which could be costly and difficult.