![Paul Mundt](/assets/img/avatar_default.png)
This adds preliminary NUMA support to SLOB, primarily aimed at systems with small nodes (tested all the way down to a 128kB SRAM block), whether asymmetric or otherwise. We follow the same conventions as SLAB/SLUB, preferring current node placement for new pages, or with explicit placement, if a node has been specified. Presently on UP NUMA this has the side-effect of preferring node#0 allocations (since numa_node_id() == 0, though this could be reworked if we could hand off a pfn to determine node placement), so single-CPU NUMA systems will want to place smaller nodes further out in terms of node id. Once a page has been bound to a node (via explicit node id typing), we only do block allocations from partial free pages that have a matching node id in the page flags. The current implementation does have some scalability problems, in that all partial free pages are tracked in the global freelist (with contention due to the single spinlock). However, these are things that are being reworked for SMP scalability first, while things like per-node freelists can easily be built on top of this sort of functionality once it's been added. More background can be found in: http://marc.info/?l=linux-mm&m=118117916022379&w=2 http://marc.info/?l=linux-mm&m=118170446306199&w=2 http://marc.info/?l=linux-mm&m=118187859420048&w=2 and subsequent threads. Acked-by: Christoph Lameter <clameter@sgi.com> Acked-by: Matt Mackall <mpm@selenic.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org> Acked-by: Nick Piggin <nickpiggin@yahoo.com.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
120 lines
2.8 KiB
C
120 lines
2.8 KiB
C
#ifndef _LINUX_SLAB_DEF_H
|
|
#define _LINUX_SLAB_DEF_H
|
|
|
|
/*
|
|
* Definitions unique to the original Linux SLAB allocator.
|
|
*
|
|
* What we provide here is a way to optimize the frequent kmalloc
|
|
* calls in the kernel by selecting the appropriate general cache
|
|
* if kmalloc was called with a size that can be established at
|
|
* compile time.
|
|
*/
|
|
|
|
#include <linux/init.h>
|
|
#include <asm/page.h> /* kmalloc_sizes.h needs PAGE_SIZE */
|
|
#include <asm/cache.h> /* kmalloc_sizes.h needs L1_CACHE_BYTES */
|
|
#include <linux/compiler.h>
|
|
|
|
/* Size description struct for general caches. */
|
|
struct cache_sizes {
|
|
size_t cs_size;
|
|
struct kmem_cache *cs_cachep;
|
|
#ifdef CONFIG_ZONE_DMA
|
|
struct kmem_cache *cs_dmacachep;
|
|
#endif
|
|
};
|
|
extern struct cache_sizes malloc_sizes[];
|
|
|
|
void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
|
|
void *__kmalloc(size_t size, gfp_t flags);
|
|
|
|
static inline void *kmalloc(size_t size, gfp_t flags)
|
|
{
|
|
if (__builtin_constant_p(size)) {
|
|
int i = 0;
|
|
#define CACHE(x) \
|
|
if (size <= x) \
|
|
goto found; \
|
|
else \
|
|
i++;
|
|
#include "kmalloc_sizes.h"
|
|
#undef CACHE
|
|
{
|
|
extern void __you_cannot_kmalloc_that_much(void);
|
|
__you_cannot_kmalloc_that_much();
|
|
}
|
|
found:
|
|
#ifdef CONFIG_ZONE_DMA
|
|
if (flags & GFP_DMA)
|
|
return kmem_cache_alloc(malloc_sizes[i].cs_dmacachep,
|
|
flags);
|
|
#endif
|
|
return kmem_cache_alloc(malloc_sizes[i].cs_cachep, flags);
|
|
}
|
|
return __kmalloc(size, flags);
|
|
}
|
|
|
|
static inline void *kzalloc(size_t size, gfp_t flags)
|
|
{
|
|
if (__builtin_constant_p(size)) {
|
|
int i = 0;
|
|
#define CACHE(x) \
|
|
if (size <= x) \
|
|
goto found; \
|
|
else \
|
|
i++;
|
|
#include "kmalloc_sizes.h"
|
|
#undef CACHE
|
|
{
|
|
extern void __you_cannot_kzalloc_that_much(void);
|
|
__you_cannot_kzalloc_that_much();
|
|
}
|
|
found:
|
|
#ifdef CONFIG_ZONE_DMA
|
|
if (flags & GFP_DMA)
|
|
return kmem_cache_zalloc(malloc_sizes[i].cs_dmacachep,
|
|
flags);
|
|
#endif
|
|
return kmem_cache_zalloc(malloc_sizes[i].cs_cachep, flags);
|
|
}
|
|
return __kzalloc(size, flags);
|
|
}
|
|
|
|
#ifdef CONFIG_NUMA
|
|
extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
|
|
extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
|
|
|
|
static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
|
|
{
|
|
if (__builtin_constant_p(size)) {
|
|
int i = 0;
|
|
#define CACHE(x) \
|
|
if (size <= x) \
|
|
goto found; \
|
|
else \
|
|
i++;
|
|
#include "kmalloc_sizes.h"
|
|
#undef CACHE
|
|
{
|
|
extern void __you_cannot_kmalloc_that_much(void);
|
|
__you_cannot_kmalloc_that_much();
|
|
}
|
|
found:
|
|
#ifdef CONFIG_ZONE_DMA
|
|
if (flags & GFP_DMA)
|
|
return kmem_cache_alloc_node(malloc_sizes[i].cs_dmacachep,
|
|
flags, node);
|
|
#endif
|
|
return kmem_cache_alloc_node(malloc_sizes[i].cs_cachep,
|
|
flags, node);
|
|
}
|
|
return __kmalloc_node(size, flags, node);
|
|
}
|
|
|
|
#endif /* CONFIG_NUMA */
|
|
|
|
extern const struct seq_operations slabinfo_op;
|
|
ssize_t slabinfo_write(struct file *, const char __user *, size_t, loff_t *);
|
|
|
|
#endif /* _LINUX_SLAB_DEF_H */
|