Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/devmap.c

    r9934f7d r64d2b10  
    3030#include <str.h>
    3131#include <ipc/services.h>
    32 #include <ns.h>
     32#include <ipc/ns.h>
    3333#include <ipc/devmap.h>
    3434#include <devmap.h>
    35 #include <fibril_synch.h>
    3635#include <async.h>
    3736#include <errno.h>
     
    3938#include <bool.h>
    4039
    41 static FIBRIL_MUTEX_INITIALIZE(devmap_driver_block_mutex);
    42 static FIBRIL_MUTEX_INITIALIZE(devmap_client_block_mutex);
    43 
    44 static FIBRIL_MUTEX_INITIALIZE(devmap_driver_mutex);
    45 static FIBRIL_MUTEX_INITIALIZE(devmap_client_mutex);
    46 
    47 static async_sess_t *devmap_driver_block_sess = NULL;
    48 static async_sess_t *devmap_client_block_sess = NULL;
    49 
    50 static async_sess_t *devmap_driver_sess = NULL;
    51 static async_sess_t *devmap_client_sess = NULL;
    52 
    53 static void clone_session(fibril_mutex_t *mtx, async_sess_t *src,
    54     async_sess_t **dst)
    55 {
    56         fibril_mutex_lock(mtx);
    57        
    58         if ((*dst == NULL) && (src != NULL))
    59                 *dst = src;
    60        
    61         fibril_mutex_unlock(mtx);
    62 }
    63 
    64 /** Start an async exchange on the devmap session (blocking).
    65  *
    66  * @param iface Device mapper interface to choose
    67  *
    68  * @return New exchange.
    69  *
    70  */
    71 async_exch_t *devmap_exchange_begin_blocking(devmap_interface_t iface)
     40static int devmap_phone_driver = -1;
     41static int devmap_phone_client = -1;
     42
     43/** Get phone to device mapper task. */
     44int devmap_get_phone(devmap_interface_t iface, unsigned int flags)
    7245{
    7346        switch (iface) {
    7447        case DEVMAP_DRIVER:
    75                 fibril_mutex_lock(&devmap_driver_block_mutex);
    76                
    77                 while (devmap_driver_block_sess == NULL) {
    78                         clone_session(&devmap_driver_mutex, devmap_driver_sess,
    79                             &devmap_driver_block_sess);
    80                        
    81                         if (devmap_driver_block_sess == NULL)
    82                                 devmap_driver_block_sess =
    83                                     service_connect_blocking(EXCHANGE_SERIALIZE,
    84                                     SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
    85                 }
    86                
    87                 fibril_mutex_unlock(&devmap_driver_block_mutex);
    88                
    89                 clone_session(&devmap_driver_mutex, devmap_driver_block_sess,
    90                     &devmap_driver_sess);
    91                
    92                 return async_exchange_begin(devmap_driver_block_sess);
     48                if (devmap_phone_driver >= 0)
     49                        return devmap_phone_driver;
     50               
     51                if (flags & IPC_FLAG_BLOCKING)
     52                        devmap_phone_driver = service_connect_blocking(SERVICE_DEVMAP,
     53                            DEVMAP_DRIVER, 0);
     54                else
     55                        devmap_phone_driver = service_connect(SERVICE_DEVMAP,
     56                            DEVMAP_DRIVER, 0);
     57               
     58                return devmap_phone_driver;
    9359        case DEVMAP_CLIENT:
    94                 fibril_mutex_lock(&devmap_client_block_mutex);
    95                
    96                 while (devmap_client_block_sess == NULL) {
    97                         clone_session(&devmap_client_mutex, devmap_client_sess,
    98                             &devmap_client_block_sess);
    99                        
    100                         if (devmap_client_block_sess == NULL)
    101                                 devmap_client_block_sess =
    102                                     service_connect_blocking(EXCHANGE_SERIALIZE,
    103                                     SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
    104                 }
    105                
    106                 fibril_mutex_unlock(&devmap_client_block_mutex);
    107                
    108                 clone_session(&devmap_client_mutex, devmap_client_block_sess,
    109                     &devmap_client_sess);
    110                
    111                 return async_exchange_begin(devmap_client_block_sess);
     60                if (devmap_phone_client >= 0)
     61                        return devmap_phone_client;
     62               
     63                if (flags & IPC_FLAG_BLOCKING)
     64                        devmap_phone_client = service_connect_blocking(SERVICE_DEVMAP,
     65                            DEVMAP_CLIENT, 0);
     66                else
     67                        devmap_phone_client = service_connect(SERVICE_DEVMAP,
     68                            DEVMAP_CLIENT, 0);
     69               
     70                return devmap_phone_client;
    11271        default:
    113                 return NULL;
    114         }
    115 }
    116 
    117 /** Start an async exchange on the devmap session.
    118  *
    119  * @param iface Device mapper interface to choose
    120  *
    121  * @return New exchange.
    122  *
    123  */
    124 async_exch_t *devmap_exchange_begin(devmap_interface_t iface)
     72                return -1;
     73        }
     74}
     75
     76void devmap_hangup_phone(devmap_interface_t iface)
    12577{
    12678        switch (iface) {
    12779        case DEVMAP_DRIVER:
    128                 fibril_mutex_lock(&devmap_driver_mutex);
    129                
    130                 if (devmap_driver_sess == NULL)
    131                         devmap_driver_sess =
    132                             service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAP,
    133                             DEVMAP_DRIVER, 0);
    134                
    135                 fibril_mutex_unlock(&devmap_driver_mutex);
    136                
    137                 if (devmap_driver_sess == NULL)
    138                         return NULL;
    139                
    140                 return async_exchange_begin(devmap_driver_sess);
     80                if (devmap_phone_driver >= 0) {
     81                        async_hangup(devmap_phone_driver);
     82                        devmap_phone_driver = -1;
     83                }
     84                break;
    14185        case DEVMAP_CLIENT:
    142                 fibril_mutex_lock(&devmap_client_mutex);
    143                
    144                 if (devmap_client_sess == NULL)
    145                         devmap_client_sess =
    146                             service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAP,
    147                             DEVMAP_CLIENT, 0);
    148                
    149                 fibril_mutex_unlock(&devmap_client_mutex);
    150                
    151                 if (devmap_client_sess == NULL)
    152                         return NULL;
    153                
    154                 return async_exchange_begin(devmap_client_sess);
     86                if (devmap_phone_client >= 0) {
     87                        async_hangup(devmap_phone_client);
     88                        devmap_phone_client = -1;
     89                }
     90                break;
    15591        default:
    156                 return NULL;
    157         }
    158 }
    159 
    160 /** Finish an async exchange on the devmap session.
    161  *
    162  * @param exch Exchange to be finished.
    163  *
    164  */
    165 void devmap_exchange_end(async_exch_t *exch)
    166 {
    167         async_exchange_end(exch);
     92                break;
     93        }
    16894}
    16995
     
    17197int devmap_driver_register(const char *name, async_client_conn_t conn)
    17298{
    173         async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_DRIVER);
     99        int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
     100       
     101        if (phone < 0)
     102                return phone;
     103       
     104        async_serialize_start();
    174105       
    175106        ipc_call_t answer;
    176         aid_t req = async_send_2(exch, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
    177         sysarg_t retval = async_data_write_start(exch, name, str_size(name));
    178        
    179         devmap_exchange_end(exch);
    180        
     107        aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
     108       
     109        sysarg_t retval = async_data_write_start(phone, name, str_size(name));
    181110        if (retval != EOK) {
    182111                async_wait_for(req, NULL);
    183                 return retval;
     112                async_serialize_end();
     113                return -1;
    184114        }
    185115       
    186116        async_set_client_connection(conn);
    187117       
    188         exch = devmap_exchange_begin(DEVMAP_DRIVER);
    189         async_connect_to_me(exch, 0, 0, 0, NULL, NULL);
    190         devmap_exchange_end(exch);
    191        
     118        async_connect_to_me(phone, 0, 0, 0, NULL);
    192119        async_wait_for(req, &retval);
     120       
     121        async_serialize_end();
     122       
    193123        return retval;
    194124}
     
    199129 * If not 0, the first argument is the interface and the second argument
    200130 * is the devmap handle of the device.
    201  *
    202131 * When the interface is zero (default), the first argument is directly
    203132 * the handle (to ensure backward compatibility).
    204133 *
    205  * @param      fqdn      Fully qualified device name.
    206  * @param[out] handle    Handle to the created instance of device.
    207  * @param      interface Interface when forwarding.
     134 * @param fqdn Fully qualified device name.
     135 * @param[out] handle Handle to the created instance of device.
     136 * @param interface Interface when forwarding.
    208137 *
    209138 */
     
    211140    devmap_handle_t *handle, sysarg_t interface)
    212141{
    213         async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_DRIVER);
     142        int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
     143       
     144        if (phone < 0)
     145                return phone;
     146       
     147        async_serialize_start();
    214148       
    215149        ipc_call_t answer;
    216         aid_t req = async_send_2(exch, DEVMAP_DEVICE_REGISTER, interface, 0,
     150        aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, interface, 0,
    217151            &answer);
    218         sysarg_t retval = async_data_write_start(exch, fqdn, str_size(fqdn));
    219        
    220         devmap_exchange_end(exch);
    221        
     152       
     153        sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
    222154        if (retval != EOK) {
    223155                async_wait_for(req, NULL);
     156                async_serialize_end();
    224157                return retval;
    225158        }
    226159       
    227160        async_wait_for(req, &retval);
     161       
     162        async_serialize_end();
    228163       
    229164        if (retval != EOK) {
    230165                if (handle != NULL)
    231166                        *handle = -1;
    232                
    233167                return retval;
    234168        }
     
    242176/** Register new device.
    243177 *
    244  * @param fqdn   Fully qualified device name.
    245  * @param handle Output: Handle to the created instance of device.
     178 * @param fqdn      Fully qualified device name.
     179 * @param handle    Output: Handle to the created instance of device.
    246180 *
    247181 */
     
    251185}
    252186
    253 int devmap_device_get_handle(const char *fqdn, devmap_handle_t *handle,
    254     unsigned int flags)
    255 {
    256         async_exch_t *exch;
    257        
    258         if (flags & IPC_FLAG_BLOCKING)
    259                 exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
    260         else {
    261                 exch = devmap_exchange_begin(DEVMAP_CLIENT);
    262                 if (exch == NULL)
    263                         return errno;
    264         }
     187
     188int devmap_device_get_handle(const char *fqdn, devmap_handle_t *handle, unsigned int flags)
     189{
     190        int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
     191       
     192        if (phone < 0)
     193                return phone;
     194       
     195        async_serialize_start();
    265196       
    266197        ipc_call_t answer;
    267         aid_t req = async_send_2(exch, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
     198        aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
    268199            &answer);
    269         sysarg_t retval = async_data_write_start(exch, fqdn, str_size(fqdn));
    270        
    271         devmap_exchange_end(exch);
    272        
     200       
     201        sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
    273202        if (retval != EOK) {
    274203                async_wait_for(req, NULL);
     204                async_serialize_end();
    275205                return retval;
    276206        }
    277207       
    278208        async_wait_for(req, &retval);
     209       
     210        async_serialize_end();
    279211       
    280212        if (retval != EOK) {
    281213                if (handle != NULL)
    282214                        *handle = (devmap_handle_t) -1;
    283                
    284215                return retval;
    285216        }
     
    291222}
    292223
    293 int devmap_namespace_get_handle(const char *name, devmap_handle_t *handle,
    294     unsigned int flags)
    295 {
    296         async_exch_t *exch;
    297        
    298         if (flags & IPC_FLAG_BLOCKING)
    299                 exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
    300         else {
    301                 exch = devmap_exchange_begin(DEVMAP_CLIENT);
    302                 if (exch == NULL)
    303                         return errno;
    304         }
     224int devmap_namespace_get_handle(const char *name, devmap_handle_t *handle, unsigned int flags)
     225{
     226        int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
     227       
     228        if (phone < 0)
     229                return phone;
     230       
     231        async_serialize_start();
    305232       
    306233        ipc_call_t answer;
    307         aid_t req = async_send_2(exch, DEVMAP_NAMESPACE_GET_HANDLE, flags, 0,
     234        aid_t req = async_send_2(phone, DEVMAP_NAMESPACE_GET_HANDLE, flags, 0,
    308235            &answer);
    309         sysarg_t retval = async_data_write_start(exch, name, str_size(name));
    310        
    311         devmap_exchange_end(exch);
    312        
     236       
     237        sysarg_t retval = async_data_write_start(phone, name, str_size(name));
    313238        if (retval != EOK) {
    314239                async_wait_for(req, NULL);
     240                async_serialize_end();
    315241                return retval;
    316242        }
    317243       
    318244        async_wait_for(req, &retval);
     245       
     246        async_serialize_end();
    319247       
    320248        if (retval != EOK) {
    321249                if (handle != NULL)
    322250                        *handle = (devmap_handle_t) -1;
    323                
    324251                return retval;
    325252        }
     
    333260devmap_handle_type_t devmap_handle_probe(devmap_handle_t handle)
    334261{
    335         async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
     262        int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
     263       
     264        if (phone < 0)
     265                return phone;
    336266       
    337267        sysarg_t type;
    338         int retval = async_req_1_1(exch, DEVMAP_HANDLE_PROBE, handle, &type);
    339        
    340         devmap_exchange_end(exch);
    341        
     268        int retval = async_req_1_1(phone, DEVMAP_HANDLE_PROBE, handle, &type);
    342269        if (retval != EOK)
    343270                return DEV_HANDLE_NONE;
     
    346273}
    347274
    348 async_sess_t *devmap_device_connect(exch_mgmt_t mgmt, devmap_handle_t handle,
    349     unsigned int flags)
    350 {
    351         async_sess_t *sess;
    352        
    353         if (flags & IPC_FLAG_BLOCKING)
    354                 sess = service_connect_blocking(mgmt, SERVICE_DEVMAP,
     275int devmap_device_connect(devmap_handle_t handle, unsigned int flags)
     276{
     277        int phone;
     278       
     279        if (flags & IPC_FLAG_BLOCKING) {
     280                phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP,
    355281                    DEVMAP_CONNECT_TO_DEVICE, handle);
    356         else
    357                 sess = service_connect(mgmt, SERVICE_DEVMAP,
     282        } else {
     283                phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
    358284                    DEVMAP_CONNECT_TO_DEVICE, handle);
    359        
    360         return sess;
     285        }
     286       
     287        return phone;
    361288}
    362289
    363290int devmap_null_create(void)
    364291{
    365         async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
     292        int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
     293       
     294        if (phone < 0)
     295                return -1;
    366296       
    367297        sysarg_t null_id;
    368         int retval = async_req_0_1(exch, DEVMAP_NULL_CREATE, &null_id);
    369        
    370         devmap_exchange_end(exch);
    371        
     298        int retval = async_req_0_1(phone, DEVMAP_NULL_CREATE, &null_id);
    372299        if (retval != EOK)
    373300                return -1;
     
    378305void devmap_null_destroy(int null_id)
    379306{
    380         async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
    381         async_req_1_0(exch, DEVMAP_NULL_DESTROY, (sysarg_t) null_id);
    382         devmap_exchange_end(exch);
    383 }
    384 
    385 static size_t devmap_count_namespaces_internal(async_exch_t *exch)
     307        int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
     308       
     309        if (phone < 0)
     310                return;
     311       
     312        async_req_1_0(phone, DEVMAP_NULL_DESTROY, (sysarg_t) null_id);
     313}
     314
     315static size_t devmap_count_namespaces_internal(int phone)
    386316{
    387317        sysarg_t count;
    388         int retval = async_req_0_1(exch, DEVMAP_GET_NAMESPACE_COUNT, &count);
     318        int retval = async_req_0_1(phone, DEVMAP_GET_NAMESPACE_COUNT, &count);
    389319        if (retval != EOK)
    390320                return 0;
     
    393323}
    394324
    395 static size_t devmap_count_devices_internal(async_exch_t *exch,
    396     devmap_handle_t ns_handle)
     325static size_t devmap_count_devices_internal(int phone, devmap_handle_t ns_handle)
    397326{
    398327        sysarg_t count;
    399         int retval = async_req_1_1(exch, DEVMAP_GET_DEVICE_COUNT, ns_handle,
    400             &count);
     328        int retval = async_req_1_1(phone, DEVMAP_GET_DEVICE_COUNT, ns_handle, &count);
    401329        if (retval != EOK)
    402330                return 0;
     
    407335size_t devmap_count_namespaces(void)
    408336{
    409         async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
    410         size_t size = devmap_count_namespaces_internal(exch);
    411         devmap_exchange_end(exch);
    412        
    413         return size;
     337        int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
     338       
     339        if (phone < 0)
     340                return 0;
     341       
     342        return devmap_count_namespaces_internal(phone);
    414343}
    415344
    416345size_t devmap_count_devices(devmap_handle_t ns_handle)
    417346{
    418         async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
    419         size_t size = devmap_count_devices_internal(exch, ns_handle);
    420         devmap_exchange_end(exch);
    421        
    422         return size;
     347        int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
     348       
     349        if (phone < 0)
     350                return 0;
     351       
     352        return devmap_count_devices_internal(phone, ns_handle);
    423353}
    424354
    425355size_t devmap_get_namespaces(dev_desc_t **data)
    426356{
     357        int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
     358       
     359        if (phone < 0)
     360                return 0;
     361       
    427362        /* Loop until namespaces read succesful */
    428363        while (true) {
    429                 async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
    430                 size_t count = devmap_count_namespaces_internal(exch);
    431                 devmap_exchange_end(exch);
    432                
     364                size_t count = devmap_count_namespaces_internal(phone);
    433365                if (count == 0)
    434366                        return 0;
     
    438370                        return 0;
    439371               
    440                 exch = devmap_exchange_begin(DEVMAP_CLIENT);
     372                async_serialize_start();
    441373               
    442374                ipc_call_t answer;
    443                 aid_t req = async_send_0(exch, DEVMAP_GET_NAMESPACES, &answer);
    444                 int rc = async_data_read_start(exch, devs, count * sizeof(dev_desc_t));
    445                
    446                 devmap_exchange_end(exch);
    447                
     375                aid_t req = async_send_0(phone, DEVMAP_GET_NAMESPACES, &answer);
     376               
     377                int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
    448378                if (rc == EOVERFLOW) {
    449379                        /*
     
    451381                         * the last call of DEVMAP_DEVICE_GET_NAMESPACE_COUNT
    452382                         */
     383                        async_serialize_end();
    453384                        free(devs);
    454385                        continue;
     
    457388                if (rc != EOK) {
    458389                        async_wait_for(req, NULL);
     390                        async_serialize_end();
    459391                        free(devs);
    460392                        return 0;
     
    463395                sysarg_t retval;
    464396                async_wait_for(req, &retval);
     397                async_serialize_end();
    465398               
    466399                if (retval != EOK)
     
    474407size_t devmap_get_devices(devmap_handle_t ns_handle, dev_desc_t **data)
    475408{
    476         /* Loop until devices read succesful */
     409        int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
     410       
     411        if (phone < 0)
     412                return 0;
     413       
     414        /* Loop until namespaces read succesful */
    477415        while (true) {
    478                 async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
    479                 size_t count = devmap_count_devices_internal(exch, ns_handle);
    480                 devmap_exchange_end(exch);
    481                
     416                size_t count = devmap_count_devices_internal(phone, ns_handle);
    482417                if (count == 0)
    483418                        return 0;
     
    487422                        return 0;
    488423               
    489                 exch = devmap_exchange_begin(DEVMAP_CLIENT);
     424                async_serialize_start();
    490425               
    491426                ipc_call_t answer;
    492                 aid_t req = async_send_1(exch, DEVMAP_GET_DEVICES, ns_handle, &answer);
    493                 int rc = async_data_read_start(exch, devs, count * sizeof(dev_desc_t));
    494                
    495                 devmap_exchange_end(exch);
    496                
     427                aid_t req = async_send_1(phone, DEVMAP_GET_DEVICES, ns_handle, &answer);
     428               
     429                int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
    497430                if (rc == EOVERFLOW) {
    498431                        /*
     
    500433                         * the last call of DEVMAP_DEVICE_GET_DEVICE_COUNT
    501434                         */
     435                        async_serialize_end();
    502436                        free(devs);
    503437                        continue;
     
    506440                if (rc != EOK) {
    507441                        async_wait_for(req, NULL);
     442                        async_serialize_end();
    508443                        free(devs);
    509444                        return 0;
     
    512447                sysarg_t retval;
    513448                async_wait_for(req, &retval);
     449                async_serialize_end();
    514450               
    515451                if (retval != EOK)
Note: See TracChangeset for help on using the changeset viewer.