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