Linux Kernel Architecture

(Jacob Rumans) #1

Chapter3:MemoryManagement


The kernel must now findarray_cache->batchcountunused objects to refill the per-CPU cache by
first scanning the list of all partially free slabs (slabs_partial) and then taking all free objects one after
another byslab_get_objuntil no more objects are free in the relevant slab. The kernel then performs the
same procedure on all other slabs in theslabs_partiallist. If this finds the desired number of objects, the
kernel iterates over theslabs_freelist of all unused slabs. When objects are taken from a slab, the kernel
must also ensure that it places them on the correct slab list (slabs_fullorslabs_partial, depending
on whether the slab was totally emptied or still contains some objects). The above is implemented by the
following code:

mm/slab.c
static void *cache_alloc_refill(kmem_cache_t *cachep, gfp_t flags)
{
...
while (batchcount > 0) {
/* Select list from which slabs are to be taken
(first slabs_partial, then slabs_free) */
...

slabp = list_entry(entry, struct slab, list);
while (slabp->inuse < cachep->num && batchcount--) {
/* get obj pointer */
ac->entry[ac->avail++] = slab_get_obj(cachep, slabp,
node);
}
check_slabp(cachep, slabp);

/* move slabp to correct slabp list: */
list_del(&slabp->list);
if (slabp->free == BUFCTL_END)
list_add(&slabp->list, &l3->slabs_full);
else
list_add(&slabp->list, &l3->slabs_partial);
}
...
}

The key to removing one slab element after another is inslab_get_obj:

mm/slab.c
static void *slab_get_obj(struct kmem_cache *cachep, struct slab *slabp,
int nodeid)
{
void *objp = index_to_obj(cachep, slabp, slabp->free);
kmem_bufctl_t next;

slabp->inuse++;
next = slab_bufctl(slabp)[slabp->free];
slabp->free = next;

return objp;
}
Free download pdf