Changes between Initial Version and Version 1 of AsyncSessions


Ignore:
Timestamp:
2010-12-26T18:59:11Z (13 years ago)
Author:
Jiri Svoboda
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • AsyncSessions

    v1 v1  
     1= Async Sessions =
     2
     3== The problem ==
     4
     5Traditionally, functions of the Async framework that perform requests (such as async_req()) operate on phones (they are passed a phone ID). In any non-trivial IPC protocol there are operations that consist of more than one IPC call (e.g. VFS_IN_READ) performed either in parallel or in series. (Here we call an operation a set of IPC calls that causes the server to perform a well-defined action). For such protocol it is not possible to perform several operations concurrently on the same phone, because the calls from different operations would get mixed up.
     6
     7For illustration, consider the following client API stub functions:
     8
     9{{{
     10int cd_phone;
     11
     12int chardev_connect()
     13{
     14    // connect phone to the character device
     15}
     16
     17int chardev_read()
     18{
     19    // R1:send CHARDEV_READ
     20    // R2:send IPC_READ
     21    // wait for R1
     22    // wait for R2
     23}
     24}}}
     25
     26Were we to call chardev_read() from two different fibrils A and B concurrently, the server fibril would see some mixture of the sequence (AR1, AR2) with (BR1, BR2), e.g. (AR1, BR1, AR2, BR2) which would be incorrect from the server point of view. Note that the server has no way of telling which request belongs to which operation.
     27
     28We often want to allow such function to be called concurrently in different fibrils. chardev_read() can block so we cannot serialize calls to it. If we stay with the character device example, we often want to allow one fibril to call chardev_write() while another is blocked in chardev_read().
     29
     30== Enter sessions ==
     31
     32Session is a ''logical'' datapath from a client to a server which can support ''concurrent'' operations. Each operation is performed in the context of an ''exchange''. An exchange can support an IPC operation (or, ''optionally'', a sequence of operations), but, in any case, only one operation is performed in an exchange at any time. (The ''session''/''connection'' terminology is borrowed from iSCSI and ''exchange'' is borrowed from Fibre Channel transport layer).
     33
     34A client first needs to create a session (to a server) by calling `async_session_create()`. Whenever the client needs to perform an operation, it starts an exchange by calling `async_exchange_begin()` and performs the operation in context of that exchange. Then the client ends the exchange by calling `async_exchange_end()`.
     35
     36We can ammend the example above as follows:
     37
     38{{{
     39async_sess_t cd_session;
     40
     41int chardev_connect()
     42{
     43    // connect phone to the character device
     44    // create session
     45}
     46
     47int chardev_read()
     48{
     49    // begin exchange
     50    // R1:send CHARDEV_READ
     51    // R2:send IPC_READ
     52    // wait for R1
     53    // wait for R2
     54    // end exchange
     55}
     56}}}
     57
     58Now we can run chardev_read() in parallel in any number of fibrils/threads. Each IPC request has a context (the exchange) so the different parallel operations will not mix up.
     59
     60Behind the scenes the async framework will do the magic necessary to distinguish the exchanges. In the current implementation it clones the session phone and uses as many separate physical connections as there are concurrent exchanges. It caches the open connections to avoid setting them up and tearing them down too often.
     61
     62In a future implementation the async framework could instead embed an additional qualifier into each IPC request that would allow to distinguish requests from different exchanges (e.g. a virtual path ID).