Changeset 5bee897 in mainline


Ignore:
Timestamp:
2010-11-30T13:42:11Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
703d19c
Parents:
1b2981aa
Message:

Fix deadlock in devman

The driver mutex is released during device adding to release the
deadlock when adding child device driven by the same task.

Location:
uspace/srv/devman
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/devman/devman.c

    r1b2981aa r5bee897  
    508508/** Notify driver about the devices to which it was assigned.
    509509 *
    510  * The driver's mutex must be locked.
    511  *
    512510 * @param driver        The driver to which the devices are passed.
    513511 */
     
    520518        printf(NAME ": pass_devices_to_driver\n");
    521519
     520        fibril_mutex_lock(&driver->driver_mutex);
     521
    522522        phone = ipc_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0);
    523         if (phone > 0) {
    524                
     523
     524        if (phone < 0) {
     525                fibril_mutex_unlock(&driver->driver_mutex);
     526                return;
     527        }
     528
     529        /*
     530         * Go through devices list as long as there is some device
     531         * that has not been passed to the driver.
     532         */
     533        link = driver->devices.next;
     534        while (link != &driver->devices) {
     535                dev = list_get_instance(link, node_t, driver_devices);
     536                if (dev->passed_to_driver) {
     537                        link = link->next;
     538                        continue;
     539                }
     540
     541                /*
     542                 * Unlock to avoid deadlock when adding device
     543                 * handled by itself.
     544                 */
     545                fibril_mutex_unlock(&driver->driver_mutex);
     546
     547                add_device(phone, driver, dev, tree);
     548
     549                /*
     550                 * Lock again as we will work with driver's
     551                 * structure.
     552                 */
     553                fibril_mutex_lock(&driver->driver_mutex);
     554
     555                /*
     556                 * Restart the cycle to go through all devices again.
     557                 */
    525558                link = driver->devices.next;
    526                 while (link != &driver->devices) {
    527                         dev = list_get_instance(link, node_t, driver_devices);
    528                         add_device(phone, driver, dev, tree);
    529                         link = link->next;
    530                 }
    531                
    532                 ipc_hangup(phone);
    533         }
     559        }
     560
     561        ipc_hangup(phone);
     562
     563        /*
     564         * Once we passed all devices to the driver, we need to mark the
     565         * driver as running.
     566         * It is vital to do it here and inside critical section.
     567         *
     568         * If we would change the state earlier, other devices added to
     569         * the driver would be added to the device list and started
     570         * immediately and possibly started here as well.
     571         */
     572        driver->state = DRIVER_RUNNING;
     573
     574        fibril_mutex_unlock(&driver->driver_mutex);
    534575}
    535576
     
    546587{
    547588        printf(NAME ": initialize_running_driver\n");
    548         fibril_mutex_lock(&driver->driver_mutex);
    549589       
    550590        /*
     
    553593         */
    554594        pass_devices_to_driver(driver, tree);
    555        
    556         /* Change driver's state to running. */
    557         driver->state = DRIVER_RUNNING;
    558        
    559         fibril_mutex_unlock(&driver->driver_mutex);
    560595}
    561596
     
    637672void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree)
    638673{
    639         printf(NAME ": add_device\n");
     674        /*
     675         * We do not expect to have driver's mutex locked as we do not
     676         * access any structures that would affect driver_t.
     677         */
     678        printf(NAME ": add_device (driver `%s', device `%s')\n", drv->name,
     679            node->name);
    640680       
    641681        ipcarg_t rc;
     
    649689                parent_handle = 0;
    650690        }
     691
    651692        aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, node->handle,
    652693            parent_handle, &answer);
     
    661702        /* Wait for answer from the driver. */
    662703        async_wait_for(req, &rc);
     704
    663705        switch(rc) {
    664706        case EOK:
     
    673715        }
    674716       
     717        node->passed_to_driver = true;
     718
    675719        return;
    676720}
  • uspace/srv/devman/devman.h

    r1b2981aa r5bee897  
    168168         */
    169169        link_t devmap_link;
     170
     171        /**
     172         * Whether this device was already passed to the driver.
     173         */
     174        bool passed_to_driver;
    170175};
    171176
Note: See TracChangeset for help on using the changeset viewer.