Changeset 957cfa58 in mainline


Ignore:
Timestamp:
2010-05-26T20:25:43Z (14 years ago)
Author:
Lenka Trochtova <trochtova.lenka@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c9f3b45c
Parents:
d51ee2b
Message:

devman - use hash table to lookup device according to its handle.

Location:
uspace/srv/devman
Files:
3 edited

Legend:

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

    rd51ee2b r957cfa58  
    3939#include "devman.h"
    4040
     41// hash table operations
     42
     43static hash_index_t devices_hash(unsigned long key[])
     44{
     45        return key[0] % DEVICE_BUCKETS;
     46}
     47
     48static int devman_devices_compare(unsigned long key[], hash_count_t keys, link_t *item)
     49{
     50        node_t *dev = hash_table_get_instance(item, node_t, devman_link);
     51        return (dev->handle == (device_handle_t) key[0]);
     52}
     53
     54static int devmap_devices_compare(unsigned long key[], hash_count_t keys, link_t *item)
     55{
     56        node_t *dev = hash_table_get_instance(item, node_t, devmap_link);
     57        return (dev->devmap_handle == (dev_handle_t) key[0]);
     58}
     59
     60static void devices_remove_callback(link_t *item)
     61{
     62}
     63
     64static hash_table_operations_t devman_devices_ops = {
     65        .hash = devices_hash,
     66        .compare = devman_devices_compare,
     67        .remove_callback = devices_remove_callback
     68};
     69
     70static hash_table_operations_t devmap_devices_ops = {
     71        .hash = devices_hash,
     72        .compare = devmap_devices_compare,
     73        .remove_callback = devices_remove_callback
     74};
     75
    4176/** Allocate and initialize a new driver structure.
    4277 *
     
    584619        printf(NAME ": init_device_tree.\n");
    585620       
    586         memset(tree->node_map, 0, MAX_DEV * sizeof(node_t *));
    587        
    588         atomic_set(&tree->current_handle, 0);
     621        tree->current_handle = 0;
     622       
     623        hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1, &devman_devices_ops);
     624        hash_table_create(&tree->devmap_devices, DEVICE_BUCKETS, 1, &devmap_devices_ops);
     625       
     626        fibril_rwlock_initialize(&tree->rwlock);
    589627       
    590628        // create root node and add it to the device tree
     
    630668/** Insert new device into device tree.
    631669 *
     670 * The device tree's rwlock should be already held exclusively when calling this function.
     671 *
    632672 * @param tree the device tree.
    633673 * @param node the newly added device node.
     
    644684        node->name = dev_name;
    645685        if (!set_dev_path(node, parent)) {
     686                fibril_rwlock_write_unlock(&tree->rwlock);
    646687                return false;           
    647688        }
    648689       
    649690        // add the node to the handle-to-node map
    650         node->handle = atomic_postinc(&tree->current_handle);
    651         if (node->handle >= MAX_DEV) {
    652                 printf(NAME ": failed to add device to device tree, because maximum number of devices was reached.\n");
    653                 free(node->pathname);
    654                 node->pathname = NULL;
    655                 atomic_postdec(&tree->current_handle);
    656                 return false;
    657         }
    658         tree->node_map[node->handle] = node;
     691        node->handle = ++tree->current_handle;
     692        unsigned long key = node->handle;
     693        hash_table_insert(&tree->devman_devices, &key, &node->devman_link);
    659694
    660695        // add the node to the list of its parent's children
    661696        node->parent = parent;
    662697        if (NULL != parent) {
    663                 fibril_mutex_lock(&parent->children_mutex);
    664                 list_append(&node->sibling, &parent->children);
    665                 fibril_mutex_unlock(&parent->children_mutex);
    666         }       
     698                list_append(&node->sibling, &parent->children);         
     699        }
    667700        return true;
    668701}
     
    678711node_t * find_dev_node_by_path(dev_tree_t *tree, char *path)
    679712{
     713        fibril_rwlock_read_lock(&tree->rwlock);
     714       
    680715        node_t *dev = tree->root_node;
    681716        // relative path to the device from its parent (but with '/' at the beginning)
     
    702737        }
    703738       
     739        fibril_rwlock_read_unlock(&tree->rwlock);
     740       
    704741        return dev;
    705742}
     
    708745 * Find child device node with a specified name.
    709746 *
     747 * Device tree rwlock should be held at least for reading.
     748 *
    710749 * @param parent the parent device node.
    711750 * @param name the name of the child device node.
     
    717756        node_t *dev;
    718757        link_t *link;
    719        
    720         fibril_mutex_lock(&parent->children_mutex);             
     758                       
    721759        link = parent->children.next;
    722760       
     
    725763               
    726764                if (0 == str_cmp(name, dev->name)) {
    727                         fibril_mutex_unlock(&parent->children_mutex);
    728765                        return dev;                     
    729766                }
     
    731768                link = link->next;
    732769        }       
    733        
    734         fibril_mutex_unlock(&parent->children_mutex);   
     770               
    735771        return NULL;
    736772}
  • uspace/srv/devman/devman.h

    rd51ee2b r957cfa58  
    3939#include <str.h>
    4040#include <adt/list.h>
     41#include <adt/hash_table.h>
    4142#include <ipc/ipc.h>
    4243#include <ipc/devman.h>
     
    5051
    5152#define MATCH_EXT ".ma"
    52 #define MAX_DEV 256
     53#define DEVICE_BUCKETS 256
    5354
    5455struct node;
     
    115116        /** List of child device nodes. */
    116117        link_t children;
    117         /** Fibril mutex for the list of child device nodes of this node. */
    118         fibril_mutex_t children_mutex;
    119118        /** List of device ids for device-to-driver matching.*/
    120119        match_id_list_t match_ids;
     
    128127        /** The list of device classes to which this device belongs.*/
    129128        link_t classes;
     129        /** Devmap handle if the device is registered by devmapper. */
     130        dev_handle_t devmap_handle;
     131        /** Used by the hash table of devices indexed by devman device handles.*/
     132        link_t devman_link;
     133        /** Used by the hash table of devices indexed by devmap device handles.*/
     134        link_t devmap_link;
    130135};
     136
    131137
    132138/** Represents device tree.
     
    136142        node_t *root_node;
    137143        /** The next available handle - handles are assigned in a sequential manner.*/
    138         atomic_t current_handle;
    139         /** Handle-to-node mapping. */
    140         node_t * node_map[MAX_DEV];
     144        device_handle_t current_handle;
     145        /** Synchronize access to the device tree.*/
     146        fibril_rwlock_t rwlock;
     147        /** Hash table of all devices indexed by devman handles.*/
     148        hash_table_t devman_devices;
     149        /** Hash table of devices registered by devmapper, indexed by devmap handles.*/
     150        hash_table_t devmap_devices;
     151       
    141152} dev_tree_t;
    142153
     
    277288        list_initialize(&res->children);
    278289        list_initialize(&res->match_ids.ids);
    279         fibril_mutex_initialize(&res->children_mutex);
    280290       
    281291        return res;
     
    301311 * Find the device node structure of the device witch has the specified handle.
    302312 *
     313 * Device tree's rwlock should be held at least for reading.
     314 *
    303315 * @param tree the device tree where we look for the device node.
    304316 * @param handle the handle of the device.
    305317 * @return the device node.
    306318 */
    307 static inline node_t * find_dev_node(dev_tree_t *tree, long handle)
    308 {
    309         if (handle < MAX_DEV) {
    310                 return tree->node_map[handle];
    311         }
    312         return NULL;
     319static inline node_t * find_dev_node_no_lock(dev_tree_t *tree, device_handle_t handle)
     320{
     321        unsigned long key = handle;
     322        link_t *link = hash_table_find(&tree->devman_devices, &key);
     323        return hash_table_get_instance(link, node_t, devman_link);
     324}
     325
     326/**
     327 * Find the device node structure of the device witch has the specified handle.
     328 *
     329 * @param tree the device tree where we look for the device node.
     330 * @param handle the handle of the device.
     331 * @return the device node.
     332 */
     333static inline node_t * find_dev_node(dev_tree_t *tree, device_handle_t handle)
     334{
     335        node_t *node = NULL;
     336       
     337        fibril_rwlock_read_lock(&tree->rwlock);
     338       
     339        node = find_dev_node_no_lock(tree, handle);
     340       
     341        fibril_rwlock_read_unlock(&tree->rwlock);
     342       
     343        return node;
    313344}
    314345
  • uspace/srv/devman/main.c

    rd51ee2b r957cfa58  
    246246static void devman_add_child(ipc_callid_t callid, ipc_call_t *call)
    247247{
    248         // printf(NAME ": devman_add_child\n");
     248        //printf(NAME ": devman_add_child\n");
    249249       
    250250        device_handle_t parent_handle = IPC_GET_ARG1(*call);
    251251        ipcarg_t match_count = IPC_GET_ARG2(*call);
    252        
    253         node_t *parent =  find_dev_node(&device_tree, parent_handle);
     252        dev_tree_t *tree = &device_tree;
     253       
     254        fibril_rwlock_write_lock(&tree->rwlock);
     255        node_t *parent =  find_dev_node_no_lock(&device_tree, parent_handle);
    254256       
    255257        if (NULL == parent) {
     258                fibril_rwlock_write_unlock(&tree->rwlock);
    256259                ipc_answer_0(callid, ENOENT);
    257260                return;
     
    261264        int rc = async_string_receive(&dev_name, DEVMAN_NAME_MAXLEN, NULL);     
    262265        if (EOK != rc) {
     266                fibril_rwlock_write_unlock(&tree->rwlock);
    263267                ipc_answer_0(callid, rc);
    264268                return;
    265269        }
    266         // printf(NAME ": newly added child device's name is '%s'.\n", dev_name);
     270        //printf(NAME ": newly added child device's name is '%s'.\n", dev_name);
    267271       
    268272        node_t *node = create_dev_node();
    269273        if (!insert_dev_node(&device_tree, node, dev_name, parent)) {
     274                fibril_rwlock_write_unlock(&tree->rwlock);
    270275                delete_dev_node(node);
    271276                ipc_answer_0(callid, ENOMEM);
    272277                return;
    273278        }       
     279        fibril_rwlock_write_unlock(&tree->rwlock);
    274280       
    275281        printf(NAME ": devman_add_child %s\n", node->pathname);
     
    281287       
    282288        // try to find suitable driver and assign it to the device     
    283         assign_driver(node, &drivers_list);
     289        assign_driver(node, &drivers_list);     
    284290}
    285291
Note: See TracChangeset for help on using the changeset viewer.