* @brief This function will allocate a block from slab object. * * @note the RT_NULL is returned if * - the nbytes is less than zero. * - there is no nbytes sized memory valid in system. * * @param m the slab memory management object. * * @param size is the size of memory to be allocated. * * @return the allocated memory. */
| 488 | * @return the allocated memory. |
| 489 | */ |
| 490 | void *rt_slab_alloc(rt_slab_t m, rt_size_t size) |
| 491 | { |
| 492 | struct rt_slab_zone *z; |
| 493 | rt_int32_t zi; |
| 494 | struct rt_slab_chunk *chunk; |
| 495 | struct rt_slab_memusage *kup; |
| 496 | struct rt_slab *slab = (struct rt_slab *)m; |
| 497 | |
| 498 | /* zero size, return RT_NULL */ |
| 499 | if (size == 0) |
| 500 | return RT_NULL; |
| 501 | |
| 502 | /* |
| 503 | * Handle large allocations directly. There should not be very many of |
| 504 | * these so performance is not a big issue. |
| 505 | */ |
| 506 | if (size >= slab->zone_limit) |
| 507 | { |
| 508 | size = RT_ALIGN(size, RT_MM_PAGE_SIZE); |
| 509 | |
| 510 | chunk = rt_slab_page_alloc(m, size >> RT_MM_PAGE_BITS); |
| 511 | if (chunk == RT_NULL) |
| 512 | return RT_NULL; |
| 513 | |
| 514 | /* set kup */ |
| 515 | kup = btokup(chunk); |
| 516 | kup->type = PAGE_TYPE_LARGE; |
| 517 | kup->size = size >> RT_MM_PAGE_BITS; |
| 518 | |
| 519 | LOG_D("alloc a large memory 0x%x, page cnt %d, kup %d", |
| 520 | size, |
| 521 | size >> RT_MM_PAGE_BITS, |
| 522 | ((rt_uintptr_t)chunk - slab->heap_start) >> RT_MM_PAGE_BITS); |
| 523 | /* mem stat */ |
| 524 | slab->parent.used += size; |
| 525 | if (slab->parent.used > slab->parent.max) |
| 526 | slab->parent.max = slab->parent.used; |
| 527 | return chunk; |
| 528 | } |
| 529 | |
| 530 | /* |
| 531 | * Attempt to allocate out of an existing zone. First try the free list, |
| 532 | * then allocate out of unallocated space. If we find a good zone move |
| 533 | * it to the head of the list so later allocations find it quickly |
| 534 | * (we might have thousands of zones in the list). |
| 535 | * |
| 536 | * Note: zoneindex() will panic of size is too large. |
| 537 | */ |
| 538 | zi = zoneindex(&size); |
| 539 | RT_ASSERT(zi < RT_SLAB_NZONES); |
| 540 | |
| 541 | LOG_D("try to alloc 0x%x on zone: %d", size, zi); |
| 542 | |
| 543 | if ((z = slab->zone_array[zi]) != RT_NULL) |
| 544 | { |
| 545 | RT_ASSERT(z->z_nfree > 0); |
| 546 | |
| 547 | /* Remove us from the zone_array[] when we become full */ |
no test coverage detected