Figure 74 Relationship between cache and slab descriptors

7.2.4 General and Specific Caches

Caches are divided into two types: general and specific. General caches are used only by the slab allocator for its own purposes, while specific caches are used by the remaining parts of the kernel.

The general caches are:

• A first cache contains the cache descriptors of the remaining caches used by the kernel. The cache_cache variable contains its descriptor.

• Twenty-six additional caches contain geometrically distributed memory areas. The table, called cache_sizes (whose elements are of type cache_sizes_t), points to the 26 cache descriptors associated with memory areas of size 32, 64, 128, 256, 512, 1,024, 2,048, 4,096, 8,192, 16,384, 32,768, 65,536, and 131,072 bytes, respectively. For each size, there are two caches: one suitable for ISA DMA allocations and the other for normal allocations. The table cache_sizes is used to efficiently derive the cache address corresponding to a given size.

The kmem_cache_init( ) and kmem_cache_sizes_init( ) functions are invoked during system initialization to set up the general caches.

Specific caches are created by the kmem_cache_create( ) function. Depending on the parameters, the function first determines the best way to handle the new cache (for instance, whether to include the slab descriptor inside or outside of the slab). It then creates a new cache descriptor for the new cache and inserts the descriptor in the cache_cache general cache.

It is also possible to destroy a cache by invoking kmem_cache_destroy( ) . This function is mostly useful to modules that create their own caches when loaded and destroy them when unloaded. To avoid wasting memory space, the kernel must destroy all slabs before destroying the cache itself. The kmem_cache_shrink( ) function destroys all the slabs in a cache by invoking kmem_slab_destroy( ) iteratively (see the later section Section 7.2.7). The growing field of the cache descriptor is used to prevent kmem_cache_shrink( ) from shrinking a cache while another kernel control path attempts to allocate a new slab for it.

The names of all general and specific caches can be obtained at runtime by reading /proc/slabinfo; this file also specifies the number of free objects and the number of allocated objects in each cache.

7.2.5 Interfacing the Slab Allocator with the Buddy System

When the slab allocator creates new slabs, it relies on the buddy system algorithm to obtain a group of free contiguous page frames. For this purpose, it invokes the kmem_getpages( ) function:

void * kmem_getpages(kmem_cache_t *cachep, unsigned long flags) {

void *addr;

flags |= cachep->gfpflags;

addr = (void*) _ _get_free_pages(flags, cachep->gfporder); return addr;

The parameters have the following meaning:

cachep

Points to the cache descriptor of the cache that needs additional page frames (the number of required page frames is determined by the order in the cachep->gfporder field)

flags

Specifies how the page frame is requested (see Section 7.1.5 earlier in this chapter). This set of flags is combined with the specific cache allocation flags stored in the gfpflags of the cache descriptor.

In the reverse operation, page frames assigned to a slab allocator can be released (see Section 7.2.7 later in this chapter) by invoking the kmem_freepages( ) function:

void kmem_freepages(kmem_cache_t *cachep, void *addr) {

struct page *page = & mem_map[_ _pa(addr) >> PAGE_SHIFT];

PageClearSlab(page); page++;

free_pages((unsigned long) addr, cachep->gfporder);

The function releases the page frames, starting from the one having the linear address addr, that had been allocated to the slab of the cache identified by cachep.

Was this article helpful?

0 0

Post a comment