Changeset 0ca7286 in mainline for uspace/srv/fs/exfat/exfat_idx.c


Ignore:
Timestamp:
2012-07-21T11:19:27Z (12 years ago)
Author:
Adam Hraska <adam.hraska+hos@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2732c94
Parents:
1c1da4b
Message:

Added resizing to user space (single-threaded) hash_table. Resizes in a way to mitigate effects of bad hash functions. Change of interface affected many files.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/exfat/exfat_idx.c

    r1c1da4b r0ca7286  
    112112static hash_table_t up_hash;
    113113
    114 #define UPH_BUCKETS_LOG 12
    115 #define UPH_BUCKETS     (1 << UPH_BUCKETS_LOG)
    116 
    117114#define UPH_SID_KEY     0
    118115#define UPH_PFC_KEY     1
    119116#define UPH_PDI_KEY     2
    120117
    121 static hash_index_t pos_hash(unsigned long key[])
    122 {
    123         service_id_t service_id = (service_id_t)key[UPH_SID_KEY];
    124         exfat_cluster_t pfc = (exfat_cluster_t)key[UPH_PFC_KEY];
    125         unsigned pdi = (unsigned)key[UPH_PDI_KEY];
    126 
    127         hash_index_t h;
    128 
    129         /*
    130          * The least significant half of all bits are the least significant bits
    131          * of the parent node's first cluster.
    132          *
    133          * The least significant half of the most significant half of all bits
    134          * are the least significant bits of the node's dentry index within the
    135          * parent directory node.
    136          *
    137          * The most significant half of the most significant half of all bits
    138          * are the least significant bits of the device handle.
    139          */
    140         h = pfc & ((1 << (UPH_BUCKETS_LOG / 2)) - 1);
    141         h |= (pdi & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
    142             (UPH_BUCKETS_LOG / 2);
    143         h |= (service_id & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
    144             (3 * (UPH_BUCKETS_LOG / 4));
    145 
    146         return h;
    147 }
    148 
    149 static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item)
     118static size_t pos_key_hash(unsigned long key[])
     119{
     120        /* Inspired by Effective Java, 2nd edition. */
     121        size_t hash = 17;
     122       
     123        hash = 31 * hash + key[UPH_PFC_KEY];
     124        hash = 31 * hash + key[UPH_PDI_KEY];
     125        hash = 31 * hash + key[UPH_SID_KEY];
     126       
     127        return hash;
     128}
     129
     130static size_t pos_hash(const link_t *item)
     131{
     132        exfat_idx_t *fidx = list_get_instance(item, exfat_idx_t, uph_link);
     133       
     134        unsigned long pkey[] = {
     135                [UPH_SID_KEY] = fidx->service_id,
     136                [UPH_PFC_KEY] = fidx->pfc,
     137                [UPH_PDI_KEY] = fidx->pdi,
     138        };
     139       
     140        return pos_key_hash(pkey);
     141}
     142
     143static bool pos_match(unsigned long key[], size_t keys, const link_t *item)
    150144{
    151145        service_id_t service_id = (service_id_t)key[UPH_SID_KEY];
     
    169163}
    170164
    171 static void pos_remove_callback(link_t *item)
    172 {
    173         /* nothing to do */
    174 }
    175 
    176 static hash_table_operations_t uph_ops = {
     165static hash_table_ops_t uph_ops = {
    177166        .hash = pos_hash,
    178         .compare = pos_compare,
    179         .remove_callback = pos_remove_callback,
     167        .key_hash = pos_key_hash,
     168        .match = pos_match,
     169        .equal = 0,
     170        .remove_callback = 0,
    180171};
    181172
     
    186177static hash_table_t ui_hash;
    187178
    188 #define UIH_BUCKETS_LOG 12
    189 #define UIH_BUCKETS     (1 << UIH_BUCKETS_LOG)
    190 
    191179#define UIH_SID_KEY     0
    192180#define UIH_INDEX_KEY   1
    193181
    194 static hash_index_t idx_hash(unsigned long key[])
     182static size_t idx_key_hash(unsigned long key[])
    195183{
    196184        service_id_t service_id = (service_id_t)key[UIH_SID_KEY];
    197185        fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY];
    198186
    199         hash_index_t h;
    200 
    201         h = service_id & ((1 << (UIH_BUCKETS_LOG / 2)) - 1);
    202         h |= (index & ((1 << (UIH_BUCKETS_LOG / 2)) - 1)) <<
    203             (UIH_BUCKETS_LOG / 2);
    204 
    205         return h;
    206 }
    207 
    208 static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item)
     187        /*
     188         * Compute a simple hash unlimited by specific table size as per:
     189         * Effective Java, 2nd edition.
     190         */
     191        size_t hash = 17;
     192        hash = 31 * hash + (size_t)service_id;
     193        hash = 31 * hash + (size_t)index;
     194        return hash;
     195}
     196
     197static size_t idx_hash(const link_t *item)
     198{
     199        exfat_idx_t *fidx = list_get_instance(item, exfat_idx_t, uih_link);
     200       
     201        unsigned long ikey[] = {
     202                [UIH_SID_KEY] = fidx->service_id,
     203                [UIH_INDEX_KEY] = fidx->index,
     204        };
     205
     206        return idx_key_hash(ikey);
     207}
     208
     209static bool idx_match(unsigned long key[], size_t keys, const link_t *item)
    209210{
    210211        service_id_t service_id = (service_id_t)key[UIH_SID_KEY];
     
    233234}
    234235
    235 static hash_table_operations_t uih_ops = {
     236static hash_table_ops_t uih_ops = {
    236237        .hash = idx_hash,
    237         .compare = idx_compare,
     238        .key_hash = idx_key_hash,
     239        .match = idx_match,
     240        .equal = 0,
    238241        .remove_callback = idx_remove_callback,
    239242};
     
    400403        }
    401404               
    402         unsigned long ikey[] = {
    403                 [UIH_SID_KEY] = service_id,
    404                 [UIH_INDEX_KEY] = fidx->index,
    405         };
    406        
    407         hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
     405        hash_table_insert(&ui_hash, &fidx->uih_link);
    408406        fibril_mutex_lock(&fidx->lock);
    409407        fibril_mutex_unlock(&used_lock);
     
    437435                }
    438436               
    439                 unsigned long ikey[] = {
    440                         [UIH_SID_KEY] = service_id,
    441                         [UIH_INDEX_KEY] = fidx->index,
    442                 };
    443        
    444437                fidx->pfc = pfc;
    445438                fidx->pdi = pdi;
    446439
    447                 hash_table_insert(&up_hash, pkey, &fidx->uph_link);
    448                 hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
     440                hash_table_insert(&up_hash, &fidx->uph_link);
     441                hash_table_insert(&ui_hash, &fidx->uih_link);
    449442        }
    450443        fibril_mutex_lock(&fidx->lock);
     
    456449void exfat_idx_hashin(exfat_idx_t *idx)
    457450{
    458         unsigned long pkey[] = {
    459                 [UPH_SID_KEY] = idx->service_id,
    460                 [UPH_PFC_KEY] = idx->pfc,
    461                 [UPH_PDI_KEY] = idx->pdi,
    462         };
    463 
    464         fibril_mutex_lock(&used_lock);
    465         hash_table_insert(&up_hash, pkey, &idx->uph_link);
     451        fibril_mutex_lock(&used_lock);
     452        hash_table_insert(&up_hash, &idx->uph_link);
    466453        fibril_mutex_unlock(&used_lock);
    467454}
     
    532519int exfat_idx_init(void)
    533520{
    534         if (!hash_table_create(&up_hash, UPH_BUCKETS, 3, &uph_ops))
     521        if (!hash_table_create(&up_hash, 0, 3, &uph_ops))
    535522                return ENOMEM;
    536         if (!hash_table_create(&ui_hash, UIH_BUCKETS, 2, &uih_ops)) {
     523        if (!hash_table_create(&ui_hash, 0, 2, &uih_ops)) {
    537524                hash_table_destroy(&up_hash);
    538525                return ENOMEM;
Note: See TracChangeset for help on using the changeset viewer.