Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/lib/ra.c

    r02667d9 rfeeac0d  
    4343 */
    4444
    45 #include <assert.h>
    4645#include <lib/ra.h>
    4746#include <typedefs.h>
    4847#include <mm/slab.h>
    4948#include <bitops.h>
     49#include <debug.h>
    5050#include <panic.h>
    5151#include <adt/list.h>
    52 #include <adt/hash.h>
    5352#include <adt/hash_table.h>
    5453#include <align.h>
     
    5857static slab_cache_t *ra_segment_cache;
    5958
    60 /** Return the hash of the key stored in the item */
    61 static size_t used_hash(const ht_link_t *item)
    62 {
    63         ra_segment_t *seg = hash_table_get_inst(item, ra_segment_t, uh_link);
    64         return hash_mix(seg->base);
    65 }
    66 
    67 /** Return the hash of the key */
    68 static size_t used_key_hash(void *key)
    69 {
    70         uintptr_t *base = (uintptr_t *) key;
    71         return hash_mix(*base);
    72 }
    73 
    74 /** Return true if the key is equal to the item's lookup key */
    75 static bool used_key_equal(void *key, const ht_link_t *item)
    76 {
    77         uintptr_t *base = (uintptr_t *) key;
    78         ra_segment_t *seg = hash_table_get_inst(item, ra_segment_t, uh_link);
    79         return seg->base == *base;
    80 }
    81 
    82 static hash_table_ops_t used_ops = {
     59#define USED_BUCKETS    1024
     60
     61static size_t used_hash(sysarg_t *key)
     62{
     63        return ((*key >> 2) & (USED_BUCKETS - 1));
     64}
     65
     66static bool used_compare(sysarg_t *key, size_t keys, link_t *item)
     67{
     68        ra_segment_t *seg;
     69
     70        seg = hash_table_get_instance(item, ra_segment_t, fu_link);
     71        return seg->base == *key;
     72}
     73
     74static hash_table_operations_t used_ops = {
    8375        .hash = used_hash,
    84         .key_hash = used_key_hash,
    85         .key_equal = used_key_equal
     76        .compare = used_compare,
     77        .remove_callback = NULL,
    8678};
    8779
     
    10597
    10698        link_initialize(&seg->segment_link);
    107         link_initialize(&seg->fl_link);
     99        link_initialize(&seg->fu_link);
    108100
    109101        seg->base = base;
     
    168160        list_initialize(&span->segments);
    169161
    170         hash_table_create(&span->used, 0, 0, &used_ops);
     162        hash_table_create(&span->used, USED_BUCKETS, 1, &used_ops);
    171163
    172164        for (i = 0; i <= span->max_order; i++)
     
    179171
    180172        /* Insert the first segment into the respective free list. */
    181         list_append(&seg->fl_link, &span->free[span->max_order]);
     173        list_append(&seg->fu_link, &span->free[span->max_order]);
    182174
    183175        return span;
    184 }
    185 
    186 static void ra_span_destroy(ra_span_t *span)
    187 {
    188         hash_table_destroy(&span->used);
    189 
    190         list_foreach_safe(span->segments, cur, next) {
    191                 ra_segment_t *seg = list_get_instance(cur, ra_segment_t,
    192                     segment_link);
    193                 list_remove(&seg->segment_link);
    194                 if (seg->flags & RA_SEGMENT_FREE)
    195                         list_remove(&seg->fl_link);
    196                 ra_segment_destroy(seg);
    197         }
    198 
    199         free(span);
    200176}
    201177
     
    215191}
    216192
    217 void ra_arena_destroy(ra_arena_t *arena)
    218 {
    219         /*
    220          * No locking necessary as this is the cleanup and all users should have
    221          * stopped using the arena already.
    222          */
    223         list_foreach_safe(arena->spans, cur, next) {
    224                 ra_span_t *span = list_get_instance(cur, ra_span_t, span_link);
    225                 list_remove(&span->span_link);
    226                 ra_span_destroy(span);
    227         }
    228 
    229         free(arena);
    230 }
    231 
    232193/** Add a span to arena. */
    233194bool ra_span_add(ra_arena_t *arena, uintptr_t base, size_t size)
    234195{
    235196        ra_span_t *span;
     197
     198        /*
     199         * At the moment, we can only create resources that don't include 0.
     200         * If 0 needs to be considered as a valid resource, we would need to
     201         * slightly change the API of the resource allocator.
     202         */
     203        if (base == 0)
     204                return false;
    236205
    237206        span = ra_span_create(base, size);
     
    246215}
    247216
    248 static bool
    249 ra_span_alloc(ra_span_t *span, size_t size, size_t align, uintptr_t *base)
     217static uintptr_t ra_span_alloc(ra_span_t *span, size_t size, size_t align)
    250218{
    251219        /*
     
    271239                /* Take the first segment from the free list. */
    272240                seg = list_get_instance(list_first(&span->free[order]),
    273                     ra_segment_t, fl_link);
    274 
    275                 assert(seg->flags & RA_SEGMENT_FREE);
     241                    ra_segment_t, fu_link);
     242
     243                ASSERT(seg->flags & RA_SEGMENT_FREE);
    276244
    277245                /*
     
    291259                newbase = ALIGN_UP(seg->base, align);
    292260                if (newbase + size != seg->base + ra_segment_size_get(seg)) {
    293                         assert(newbase + (size - 1) < seg->base +
     261                        ASSERT(newbase + (size - 1) < seg->base +
    294262                            (ra_segment_size_get(seg) - 1));
    295263                        succ = ra_segment_create(newbase + size);
     
    313281                            &seg->segment_link);
    314282                        pred_order = fnzb(ra_segment_size_get(pred));
    315                         list_append(&pred->fl_link, &span->free[pred_order]);
     283                        list_append(&pred->fu_link, &span->free[pred_order]);
    316284                }
    317285                if (succ) {
     
    321289                            &seg->segment_link);
    322290                        succ_order = fnzb(ra_segment_size_get(succ));
    323                         list_append(&succ->fl_link, &span->free[succ_order]);
     291                        list_append(&succ->fu_link, &span->free[succ_order]);
    324292                }
    325293
    326294                /* Now remove the found segment from the free list. */
    327                 list_remove(&seg->fl_link);
     295                list_remove(&seg->fu_link);
    328296                seg->base = newbase;
    329297                seg->flags &= ~RA_SEGMENT_FREE;
    330298
    331299                /* Hash-in the segment into the used hash. */
    332                 hash_table_insert(&span->used, &seg->uh_link);
    333 
    334                 *base = newbase;
    335                 return true;
    336         }
    337 
    338         return false;
     300                sysarg_t key = seg->base;
     301                hash_table_insert(&span->used, &key, &seg->fu_link);
     302
     303                return newbase;
     304        }
     305
     306        return 0;
    339307}
    340308
     
    342310{
    343311        sysarg_t key = base;
    344         ht_link_t *link;
     312        link_t *link;
    345313        ra_segment_t *seg;
    346314        ra_segment_t *pred;
     
    356324                    PRIxn ", size=%" PRIdn ").", base, size);
    357325        }
    358         seg = hash_table_get_inst(link, ra_segment_t, uh_link);
     326        seg = hash_table_get_instance(link, ra_segment_t, fu_link);
    359327
    360328        /*
    361329         * Hash out the segment.
    362330         */
    363         hash_table_remove_item(&span->used, link);
    364 
    365         assert(!(seg->flags & RA_SEGMENT_FREE));
    366         assert(seg->base == base);
    367         assert(ra_segment_size_get(seg) == size);
     331        hash_table_remove(&span->used, &key, 1);
     332
     333        ASSERT(!(seg->flags & RA_SEGMENT_FREE));
     334        ASSERT(seg->base == base);
     335        ASSERT(ra_segment_size_get(seg) == size);
    368336
    369337        /*
     
    371339         */
    372340        if (list_first(&span->segments) != &seg->segment_link) {
    373                 pred = hash_table_get_inst(seg->segment_link.prev,
     341                pred = hash_table_get_instance(seg->segment_link.prev,
    374342                    ra_segment_t, segment_link);
    375343
    376                 assert(pred->base < seg->base);
     344                ASSERT(pred->base < seg->base);
    377345
    378346                if (pred->flags & RA_SEGMENT_FREE) {
     
    383351                         * away.
    384352                         */
    385                         list_remove(&pred->fl_link);
     353                        list_remove(&pred->fu_link);
    386354                        list_remove(&pred->segment_link);
    387355                        seg->base = pred->base;
     
    393361         * Check whether the segment can be coalesced with its right neighbor.
    394362         */
    395         succ = hash_table_get_inst(seg->segment_link.next, ra_segment_t,
     363        succ = hash_table_get_instance(seg->segment_link.next, ra_segment_t,
    396364            segment_link);
    397         assert(succ->base > seg->base);
     365        ASSERT(succ->base > seg->base);
    398366        if (succ->flags & RA_SEGMENT_FREE) {
    399367                /*
     
    402370                 * and throw it away.
    403371                 */
    404                 list_remove(&succ->fl_link);
     372                list_remove(&succ->fu_link);
    405373                list_remove(&succ->segment_link);
    406374                ra_segment_destroy(succ);
     
    410378        seg->flags |= RA_SEGMENT_FREE;
    411379        order = fnzb(ra_segment_size_get(seg));
    412         list_append(&seg->fl_link, &span->free[order]);
     380        list_append(&seg->fu_link, &span->free[order]);
    413381}
    414382
    415383/** Allocate resources from arena. */
    416 bool
    417 ra_alloc(ra_arena_t *arena, size_t size, size_t alignment, uintptr_t *base)
    418 {
    419         bool success = false;
    420 
    421         assert(size >= 1);
    422         assert(alignment >= 1);
    423         assert(ispwr2(alignment));
     384uintptr_t ra_alloc(ra_arena_t *arena, size_t size, size_t alignment)
     385{
     386        uintptr_t base = 0;
     387
     388        ASSERT(size >= 1);
     389        ASSERT(alignment >= 1);
     390        ASSERT(ispwr2(alignment));
    424391
    425392        irq_spinlock_lock(&arena->lock, true);
    426393        list_foreach(arena->spans, span_link, ra_span_t, span) {
    427                 success = ra_span_alloc(span, size, alignment, base);
    428                 if (success)
     394                base = ra_span_alloc(span, size, alignment);
     395                if (base)
    429396                        break;
    430397        }
    431398        irq_spinlock_unlock(&arena->lock, true);
    432399
    433         return success;
     400        return base;
    434401}
    435402
Note: See TracChangeset for help on using the changeset viewer.