Changes in kernel/generic/src/lib/ra.c [02667d9:feeac0d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/lib/ra.c
r02667d9 rfeeac0d 43 43 */ 44 44 45 #include <assert.h>46 45 #include <lib/ra.h> 47 46 #include <typedefs.h> 48 47 #include <mm/slab.h> 49 48 #include <bitops.h> 49 #include <debug.h> 50 50 #include <panic.h> 51 51 #include <adt/list.h> 52 #include <adt/hash.h>53 52 #include <adt/hash_table.h> 54 53 #include <align.h> … … 58 57 static slab_cache_t *ra_segment_cache; 59 58 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 61 static size_t used_hash(sysarg_t *key) 62 { 63 return ((*key >> 2) & (USED_BUCKETS - 1)); 64 } 65 66 static 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 74 static hash_table_operations_t used_ops = { 83 75 .hash = used_hash, 84 . key_hash = used_key_hash,85 . key_equal = used_key_equal76 .compare = used_compare, 77 .remove_callback = NULL, 86 78 }; 87 79 … … 105 97 106 98 link_initialize(&seg->segment_link); 107 link_initialize(&seg->f l_link);99 link_initialize(&seg->fu_link); 108 100 109 101 seg->base = base; … … 168 160 list_initialize(&span->segments); 169 161 170 hash_table_create(&span->used, 0, 0, &used_ops);162 hash_table_create(&span->used, USED_BUCKETS, 1, &used_ops); 171 163 172 164 for (i = 0; i <= span->max_order; i++) … … 179 171 180 172 /* Insert the first segment into the respective free list. */ 181 list_append(&seg->f l_link, &span->free[span->max_order]);173 list_append(&seg->fu_link, &span->free[span->max_order]); 182 174 183 175 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);200 176 } 201 177 … … 215 191 } 216 192 217 void ra_arena_destroy(ra_arena_t *arena)218 {219 /*220 * No locking necessary as this is the cleanup and all users should have221 * 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 232 193 /** Add a span to arena. */ 233 194 bool ra_span_add(ra_arena_t *arena, uintptr_t base, size_t size) 234 195 { 235 196 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; 236 205 237 206 span = ra_span_create(base, size); … … 246 215 } 247 216 248 static bool 249 ra_span_alloc(ra_span_t *span, size_t size, size_t align, uintptr_t *base) 217 static uintptr_t ra_span_alloc(ra_span_t *span, size_t size, size_t align) 250 218 { 251 219 /* … … 271 239 /* Take the first segment from the free list. */ 272 240 seg = list_get_instance(list_first(&span->free[order]), 273 ra_segment_t, f l_link);274 275 assert(seg->flags & RA_SEGMENT_FREE);241 ra_segment_t, fu_link); 242 243 ASSERT(seg->flags & RA_SEGMENT_FREE); 276 244 277 245 /* … … 291 259 newbase = ALIGN_UP(seg->base, align); 292 260 if (newbase + size != seg->base + ra_segment_size_get(seg)) { 293 assert(newbase + (size - 1) < seg->base +261 ASSERT(newbase + (size - 1) < seg->base + 294 262 (ra_segment_size_get(seg) - 1)); 295 263 succ = ra_segment_create(newbase + size); … … 313 281 &seg->segment_link); 314 282 pred_order = fnzb(ra_segment_size_get(pred)); 315 list_append(&pred->f l_link, &span->free[pred_order]);283 list_append(&pred->fu_link, &span->free[pred_order]); 316 284 } 317 285 if (succ) { … … 321 289 &seg->segment_link); 322 290 succ_order = fnzb(ra_segment_size_get(succ)); 323 list_append(&succ->f l_link, &span->free[succ_order]);291 list_append(&succ->fu_link, &span->free[succ_order]); 324 292 } 325 293 326 294 /* Now remove the found segment from the free list. */ 327 list_remove(&seg->f l_link);295 list_remove(&seg->fu_link); 328 296 seg->base = newbase; 329 297 seg->flags &= ~RA_SEGMENT_FREE; 330 298 331 299 /* 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; 339 307 } 340 308 … … 342 310 { 343 311 sysarg_t key = base; 344 ht_link_t *link;312 link_t *link; 345 313 ra_segment_t *seg; 346 314 ra_segment_t *pred; … … 356 324 PRIxn ", size=%" PRIdn ").", base, size); 357 325 } 358 seg = hash_table_get_inst (link, ra_segment_t, uh_link);326 seg = hash_table_get_instance(link, ra_segment_t, fu_link); 359 327 360 328 /* 361 329 * Hash out the segment. 362 330 */ 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); 368 336 369 337 /* … … 371 339 */ 372 340 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, 374 342 ra_segment_t, segment_link); 375 343 376 assert(pred->base < seg->base);344 ASSERT(pred->base < seg->base); 377 345 378 346 if (pred->flags & RA_SEGMENT_FREE) { … … 383 351 * away. 384 352 */ 385 list_remove(&pred->f l_link);353 list_remove(&pred->fu_link); 386 354 list_remove(&pred->segment_link); 387 355 seg->base = pred->base; … … 393 361 * Check whether the segment can be coalesced with its right neighbor. 394 362 */ 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, 396 364 segment_link); 397 assert(succ->base > seg->base);365 ASSERT(succ->base > seg->base); 398 366 if (succ->flags & RA_SEGMENT_FREE) { 399 367 /* … … 402 370 * and throw it away. 403 371 */ 404 list_remove(&succ->f l_link);372 list_remove(&succ->fu_link); 405 373 list_remove(&succ->segment_link); 406 374 ra_segment_destroy(succ); … … 410 378 seg->flags |= RA_SEGMENT_FREE; 411 379 order = fnzb(ra_segment_size_get(seg)); 412 list_append(&seg->f l_link, &span->free[order]);380 list_append(&seg->fu_link, &span->free[order]); 413 381 } 414 382 415 383 /** 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)); 384 uintptr_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)); 424 391 425 392 irq_spinlock_lock(&arena->lock, true); 426 393 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) 429 396 break; 430 397 } 431 398 irq_spinlock_unlock(&arena->lock, true); 432 399 433 return success;400 return base; 434 401 } 435 402
Note:
See TracChangeset
for help on using the changeset viewer.