Ignore:
File:
1 edited

Legend:

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

    r64d2b10 r9934f7d  
    3030#include <str.h>
    3131#include <ipc/services.h>
    32 #include <ipc/ns.h>
     32#include <ns.h>
    3333#include <ipc/devmap.h>
    3434#include <devmap.h>
     35#include <fibril_synch.h>
    3536#include <async.h>
    3637#include <errno.h>
     
    3839#include <bool.h>
    3940
    40 static int devmap_phone_driver = -1;
    41 static int devmap_phone_client = -1;
    42 
    43 /** Get phone to device mapper task. */
    44 int devmap_get_phone(devmap_interface_t iface, unsigned int flags)
     41static FIBRIL_MUTEX_INITIALIZE(devmap_driver_block_mutex);
     42static FIBRIL_MUTEX_INITIALIZE(devmap_client_block_mutex);
     43
     44static FIBRIL_MUTEX_INITIALIZE(devmap_driver_mutex);
     45static FIBRIL_MUTEX_INITIALIZE(devmap_client_mutex);
     46
     47static async_sess_t *devmap_driver_block_sess = NULL;
     48static async_sess_t *devmap_client_block_sess = NULL;
     49
     50static async_sess_t *devmap_driver_sess = NULL;
     51static async_sess_t *devmap_client_sess = NULL;
     52
     53static 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 */
     71async_exch_t *devmap_exchange_begin_blocking(devmap_interface_t iface)
    4572{
    4673        switch (iface) {
    4774        case DEVMAP_DRIVER:
    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;
     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);
    5993        case DEVMAP_CLIENT:
    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;
     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);
    71112        default:
    72                 return -1;
    73         }
    74 }
    75 
    76 void devmap_hangup_phone(devmap_interface_t iface)
     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 */
     124async_exch_t *devmap_exchange_begin(devmap_interface_t iface)
    77125{
    78126        switch (iface) {
    79127        case DEVMAP_DRIVER:
    80                 if (devmap_phone_driver >= 0) {
    81                         async_hangup(devmap_phone_driver);
    82                         devmap_phone_driver = -1;
    83                 }
    84                 break;
     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);
    85141        case DEVMAP_CLIENT:
    86                 if (devmap_phone_client >= 0) {
    87                         async_hangup(devmap_phone_client);
    88                         devmap_phone_client = -1;
    89                 }
    90                 break;
     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);
    91155        default:
    92                 break;
    93         }
     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 */
     165void devmap_exchange_end(async_exch_t *exch)
     166{
     167        async_exchange_end(exch);
    94168}
    95169
     
    97171int devmap_driver_register(const char *name, async_client_conn_t conn)
    98172{
    99         int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
    100        
    101         if (phone < 0)
    102                 return phone;
    103        
    104         async_serialize_start();
     173        async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_DRIVER);
    105174       
    106175        ipc_call_t answer;
    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));
     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       
    110181        if (retval != EOK) {
    111182                async_wait_for(req, NULL);
    112                 async_serialize_end();
    113                 return -1;
     183                return retval;
    114184        }
    115185       
    116186        async_set_client_connection(conn);
    117187       
    118         async_connect_to_me(phone, 0, 0, 0, NULL);
     188        exch = devmap_exchange_begin(DEVMAP_DRIVER);
     189        async_connect_to_me(exch, 0, 0, 0, NULL, NULL);
     190        devmap_exchange_end(exch);
     191       
    119192        async_wait_for(req, &retval);
    120        
    121         async_serialize_end();
    122        
    123193        return retval;
    124194}
     
    129199 * If not 0, the first argument is the interface and the second argument
    130200 * is the devmap handle of the device.
     201 *
    131202 * When the interface is zero (default), the first argument is directly
    132203 * the handle (to ensure backward compatibility).
    133204 *
    134  * @param fqdn Fully qualified device name.
    135  * @param[out] handle Handle to the created instance of device.
    136  * @param interface Interface when forwarding.
     205 * @param      fqdn      Fully qualified device name.
     206 * @param[out] handle    Handle to the created instance of device.
     207 * @param      interface Interface when forwarding.
    137208 *
    138209 */
     
    140211    devmap_handle_t *handle, sysarg_t interface)
    141212{
    142         int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
    143        
    144         if (phone < 0)
    145                 return phone;
    146        
    147         async_serialize_start();
     213        async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_DRIVER);
    148214       
    149215        ipc_call_t answer;
    150         aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, interface, 0,
     216        aid_t req = async_send_2(exch, DEVMAP_DEVICE_REGISTER, interface, 0,
    151217            &answer);
    152        
    153         sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
     218        sysarg_t retval = async_data_write_start(exch, fqdn, str_size(fqdn));
     219       
     220        devmap_exchange_end(exch);
     221       
    154222        if (retval != EOK) {
    155223                async_wait_for(req, NULL);
    156                 async_serialize_end();
    157224                return retval;
    158225        }
    159226       
    160227        async_wait_for(req, &retval);
    161        
    162         async_serialize_end();
    163228       
    164229        if (retval != EOK) {
    165230                if (handle != NULL)
    166231                        *handle = -1;
     232               
    167233                return retval;
    168234        }
     
    176242/** Register new device.
    177243 *
    178  * @param fqdn      Fully qualified device name.
    179  * @param handle    Output: Handle to the created instance of device.
     244 * @param fqdn   Fully qualified device name.
     245 * @param handle Output: Handle to the created instance of device.
    180246 *
    181247 */
     
    185251}
    186252
    187 
    188 int 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();
     253int 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        }
    196265       
    197266        ipc_call_t answer;
    198         aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
     267        aid_t req = async_send_2(exch, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
    199268            &answer);
    200        
    201         sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
     269        sysarg_t retval = async_data_write_start(exch, fqdn, str_size(fqdn));
     270       
     271        devmap_exchange_end(exch);
     272       
    202273        if (retval != EOK) {
    203274                async_wait_for(req, NULL);
    204                 async_serialize_end();
    205275                return retval;
    206276        }
    207277       
    208278        async_wait_for(req, &retval);
    209        
    210         async_serialize_end();
    211279       
    212280        if (retval != EOK) {
    213281                if (handle != NULL)
    214282                        *handle = (devmap_handle_t) -1;
     283               
    215284                return retval;
    216285        }
     
    222291}
    223292
    224 int 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();
     293int 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        }
    232305       
    233306        ipc_call_t answer;
    234         aid_t req = async_send_2(phone, DEVMAP_NAMESPACE_GET_HANDLE, flags, 0,
     307        aid_t req = async_send_2(exch, DEVMAP_NAMESPACE_GET_HANDLE, flags, 0,
    235308            &answer);
    236        
    237         sysarg_t retval = async_data_write_start(phone, name, str_size(name));
     309        sysarg_t retval = async_data_write_start(exch, name, str_size(name));
     310       
     311        devmap_exchange_end(exch);
     312       
    238313        if (retval != EOK) {
    239314                async_wait_for(req, NULL);
    240                 async_serialize_end();
    241315                return retval;
    242316        }
    243317       
    244318        async_wait_for(req, &retval);
    245        
    246         async_serialize_end();
    247319       
    248320        if (retval != EOK) {
    249321                if (handle != NULL)
    250322                        *handle = (devmap_handle_t) -1;
     323               
    251324                return retval;
    252325        }
     
    260333devmap_handle_type_t devmap_handle_probe(devmap_handle_t handle)
    261334{
    262         int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
    263        
    264         if (phone < 0)
    265                 return phone;
     335        async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
    266336       
    267337        sysarg_t type;
    268         int retval = async_req_1_1(phone, DEVMAP_HANDLE_PROBE, handle, &type);
     338        int retval = async_req_1_1(exch, DEVMAP_HANDLE_PROBE, handle, &type);
     339       
     340        devmap_exchange_end(exch);
     341       
    269342        if (retval != EOK)
    270343                return DEV_HANDLE_NONE;
     
    273346}
    274347
    275 int 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,
     348async_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,
    281355                    DEVMAP_CONNECT_TO_DEVICE, handle);
    282         } else {
    283                 phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
     356        else
     357                sess = service_connect(mgmt, SERVICE_DEVMAP,
    284358                    DEVMAP_CONNECT_TO_DEVICE, handle);
    285         }
    286        
    287         return phone;
     359       
     360        return sess;
    288361}
    289362
    290363int devmap_null_create(void)
    291364{
    292         int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
    293        
    294         if (phone < 0)
    295                 return -1;
     365        async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
    296366       
    297367        sysarg_t null_id;
    298         int retval = async_req_0_1(phone, DEVMAP_NULL_CREATE, &null_id);
     368        int retval = async_req_0_1(exch, DEVMAP_NULL_CREATE, &null_id);
     369       
     370        devmap_exchange_end(exch);
     371       
    299372        if (retval != EOK)
    300373                return -1;
     
    305378void devmap_null_destroy(int null_id)
    306379{
    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 
    315 static size_t devmap_count_namespaces_internal(int phone)
     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
     385static size_t devmap_count_namespaces_internal(async_exch_t *exch)
    316386{
    317387        sysarg_t count;
    318         int retval = async_req_0_1(phone, DEVMAP_GET_NAMESPACE_COUNT, &count);
     388        int retval = async_req_0_1(exch, DEVMAP_GET_NAMESPACE_COUNT, &count);
    319389        if (retval != EOK)
    320390                return 0;
     
    323393}
    324394
    325 static size_t devmap_count_devices_internal(int phone, devmap_handle_t ns_handle)
     395static size_t devmap_count_devices_internal(async_exch_t *exch,
     396    devmap_handle_t ns_handle)
    326397{
    327398        sysarg_t count;
    328         int retval = async_req_1_1(phone, DEVMAP_GET_DEVICE_COUNT, ns_handle, &count);
     399        int retval = async_req_1_1(exch, DEVMAP_GET_DEVICE_COUNT, ns_handle,
     400            &count);
    329401        if (retval != EOK)
    330402                return 0;
     
    335407size_t devmap_count_namespaces(void)
    336408{
    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);
     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;
    343414}
    344415
    345416size_t devmap_count_devices(devmap_handle_t ns_handle)
    346417{
    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);
     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;
    353423}
    354424
    355425size_t devmap_get_namespaces(dev_desc_t **data)
    356426{
    357         int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
    358        
    359         if (phone < 0)
    360                 return 0;
    361        
    362427        /* Loop until namespaces read succesful */
    363428        while (true) {
    364                 size_t count = devmap_count_namespaces_internal(phone);
     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               
    365433                if (count == 0)
    366434                        return 0;
     
    370438                        return 0;
    371439               
    372                 async_serialize_start();
     440                exch = devmap_exchange_begin(DEVMAP_CLIENT);
    373441               
    374442                ipc_call_t answer;
    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));
     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               
    378448                if (rc == EOVERFLOW) {
    379449                        /*
     
    381451                         * the last call of DEVMAP_DEVICE_GET_NAMESPACE_COUNT
    382452                         */
    383                         async_serialize_end();
    384453                        free(devs);
    385454                        continue;
     
    388457                if (rc != EOK) {
    389458                        async_wait_for(req, NULL);
    390                         async_serialize_end();
    391459                        free(devs);
    392460                        return 0;
     
    395463                sysarg_t retval;
    396464                async_wait_for(req, &retval);
    397                 async_serialize_end();
    398465               
    399466                if (retval != EOK)
     
    407474size_t devmap_get_devices(devmap_handle_t ns_handle, dev_desc_t **data)
    408475{
    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 */
     476        /* Loop until devices read succesful */
    415477        while (true) {
    416                 size_t count = devmap_count_devices_internal(phone, ns_handle);
     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               
    417482                if (count == 0)
    418483                        return 0;
     
    422487                        return 0;
    423488               
    424                 async_serialize_start();
     489                exch = devmap_exchange_begin(DEVMAP_CLIENT);
    425490               
    426491                ipc_call_t answer;
    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));
     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               
    430497                if (rc == EOVERFLOW) {
    431498                        /*
     
    433500                         * the last call of DEVMAP_DEVICE_GET_DEVICE_COUNT
    434501                         */
    435                         async_serialize_end();
    436502                        free(devs);
    437503                        continue;
     
    440506                if (rc != EOK) {
    441507                        async_wait_for(req, NULL);
    442                         async_serialize_end();
    443508                        free(devs);
    444509                        return 0;
     
    447512                sysarg_t retval;
    448513                async_wait_for(req, &retval);
    449                 async_serialize_end();
    450514               
    451515                if (retval != EOK)
Note: See TracChangeset for help on using the changeset viewer.