Commit c4fb7f0a authored by Liam R. Howlett's avatar Liam R. Howlett Committed by Vlastimil Babka
Browse files

tools/testing: Add support for changes to slab for sheaves



The slab changes for sheaves requires more effort in the testing code.
Unite all the kmem_cache work into the tools/include slab header for
both the vma and maple tree testing.

The vma test code also requires importing more #defines to allow for
seamless use of the shared kmem_cache code.

This adds the pthread header to the slab header in the tools directory
to allow for the pthread_mutex in linux.c.

Signed-off-by: default avatarLiam R. Howlett <Liam.Howlett@oracle.com>
Reviewed-by: default avatarSuren Baghdasaryan <surenb@google.com>
Signed-off-by: default avatarVlastimil Babka <vbabka@suse.cz>
parent d09a61a3
Loading
Loading
Loading
Loading
+133 −4
Original line number Diff line number Diff line
@@ -4,11 +4,31 @@

#include <linux/types.h>
#include <linux/gfp.h>
#include <pthread.h>

#define SLAB_PANIC 2
#define SLAB_RECLAIM_ACCOUNT    0x00020000UL            /* Objects are reclaimable */

#define kzalloc_node(size, flags, node) kmalloc(size, flags)
enum _slab_flag_bits {
	_SLAB_KMALLOC,
	_SLAB_HWCACHE_ALIGN,
	_SLAB_PANIC,
	_SLAB_TYPESAFE_BY_RCU,
	_SLAB_ACCOUNT,
	_SLAB_FLAGS_LAST_BIT
};

#define __SLAB_FLAG_BIT(nr)	((unsigned int __force)(1U << (nr)))
#define __SLAB_FLAG_UNUSED	((unsigned int __force)(0U))

#define SLAB_HWCACHE_ALIGN	__SLAB_FLAG_BIT(_SLAB_HWCACHE_ALIGN)
#define SLAB_PANIC		__SLAB_FLAG_BIT(_SLAB_PANIC)
#define SLAB_TYPESAFE_BY_RCU	__SLAB_FLAG_BIT(_SLAB_TYPESAFE_BY_RCU)
#ifdef CONFIG_MEMCG
# define SLAB_ACCOUNT		__SLAB_FLAG_BIT(_SLAB_ACCOUNT)
#else
# define SLAB_ACCOUNT		__SLAB_FLAG_UNUSED
#endif

void *kmalloc(size_t size, gfp_t gfp);
void kfree(void *p);
@@ -23,6 +43,86 @@ enum slab_state {
	FULL
};

struct kmem_cache {
	pthread_mutex_t lock;
	unsigned int size;
	unsigned int align;
	unsigned int sheaf_capacity;
	int nr_objs;
	void *objs;
	void (*ctor)(void *);
	bool non_kernel_enabled;
	unsigned int non_kernel;
	unsigned long nr_allocated;
	unsigned long nr_tallocated;
	bool exec_callback;
	void (*callback)(void *);
	void *private;
};

struct kmem_cache_args {
	/**
	 * @align: The required alignment for the objects.
	 *
	 * %0 means no specific alignment is requested.
	 */
	unsigned int align;
	/**
	 * @sheaf_capacity: The maximum size of the sheaf.
	 */
	unsigned int sheaf_capacity;
	/**
	 * @useroffset: Usercopy region offset.
	 *
	 * %0 is a valid offset, when @usersize is non-%0
	 */
	unsigned int useroffset;
	/**
	 * @usersize: Usercopy region size.
	 *
	 * %0 means no usercopy region is specified.
	 */
	unsigned int usersize;
	/**
	 * @freeptr_offset: Custom offset for the free pointer
	 * in &SLAB_TYPESAFE_BY_RCU caches
	 *
	 * By default &SLAB_TYPESAFE_BY_RCU caches place the free pointer
	 * outside of the object. This might cause the object to grow in size.
	 * Cache creators that have a reason to avoid this can specify a custom
	 * free pointer offset in their struct where the free pointer will be
	 * placed.
	 *
	 * Note that placing the free pointer inside the object requires the
	 * caller to ensure that no fields are invalidated that are required to
	 * guard against object recycling (See &SLAB_TYPESAFE_BY_RCU for
	 * details).
	 *
	 * Using %0 as a value for @freeptr_offset is valid. If @freeptr_offset
	 * is specified, %use_freeptr_offset must be set %true.
	 *
	 * Note that @ctor currently isn't supported with custom free pointers
	 * as a @ctor requires an external free pointer.
	 */
	unsigned int freeptr_offset;
	/**
	 * @use_freeptr_offset: Whether a @freeptr_offset is used.
	 */
	bool use_freeptr_offset;
	/**
	 * @ctor: A constructor for the objects.
	 *
	 * The constructor is invoked for each object in a newly allocated slab
	 * page. It is the cache user's responsibility to free object in the
	 * same state as after calling the constructor, or deal appropriately
	 * with any differences between a freshly constructed and a reallocated
	 * object.
	 *
	 * %NULL means no constructor.
	 */
	void (*ctor)(void *);
};

static inline void *kzalloc(size_t size, gfp_t gfp)
{
	return kmalloc(size, gfp | __GFP_ZERO);
@@ -37,9 +137,38 @@ static inline void *kmem_cache_alloc(struct kmem_cache *cachep, int flags)
}
void kmem_cache_free(struct kmem_cache *cachep, void *objp);

struct kmem_cache *kmem_cache_create(const char *name, unsigned int size,
			unsigned int align, unsigned int flags,
			void (*ctor)(void *));

struct kmem_cache *
__kmem_cache_create_args(const char *name, unsigned int size,
		struct kmem_cache_args *args, unsigned int flags);

/* If NULL is passed for @args, use this variant with default arguments. */
static inline struct kmem_cache *
__kmem_cache_default_args(const char *name, unsigned int size,
		struct kmem_cache_args *args, unsigned int flags)
{
	struct kmem_cache_args kmem_default_args = {};

	return __kmem_cache_create_args(name, size, &kmem_default_args, flags);
}

static inline struct kmem_cache *
__kmem_cache_create(const char *name, unsigned int size, unsigned int align,
		unsigned int flags, void (*ctor)(void *))
{
	struct kmem_cache_args kmem_args = {
		.align	= align,
		.ctor	= ctor,
	};

	return __kmem_cache_create_args(name, size, &kmem_args, flags);
}

#define kmem_cache_create(__name, __object_size, __args, ...)           \
	_Generic((__args),                                              \
		struct kmem_cache_args *: __kmem_cache_create_args,	\
		void *: __kmem_cache_default_args,			\
		default: __kmem_cache_create)(__name, __object_size, __args, __VA_ARGS__)

void kmem_cache_free_bulk(struct kmem_cache *cachep, size_t size, void **list);
int kmem_cache_alloc_bulk(struct kmem_cache *cachep, gfp_t gfp, size_t size,
+7 −19
Original line number Diff line number Diff line
@@ -16,21 +16,6 @@ int nr_allocated;
int preempt_count;
int test_verbose;

struct kmem_cache {
	pthread_mutex_t lock;
	unsigned int size;
	unsigned int align;
	int nr_objs;
	void *objs;
	void (*ctor)(void *);
	unsigned int non_kernel;
	unsigned long nr_allocated;
	unsigned long nr_tallocated;
	bool exec_callback;
	void (*callback)(void *);
	void *private;
};

void kmem_cache_set_callback(struct kmem_cache *cachep, void (*callback)(void *))
{
	cachep->callback = callback;
@@ -234,23 +219,26 @@ int kmem_cache_alloc_bulk(struct kmem_cache *cachep, gfp_t gfp, size_t size,
}

struct kmem_cache *
kmem_cache_create(const char *name, unsigned int size, unsigned int align,
		unsigned int flags, void (*ctor)(void *))
__kmem_cache_create_args(const char *name, unsigned int size,
			  struct kmem_cache_args *args,
			  unsigned int flags)
{
	struct kmem_cache *ret = malloc(sizeof(*ret));

	pthread_mutex_init(&ret->lock, NULL);
	ret->size = size;
	ret->align = align;
	ret->align = args->align;
	ret->sheaf_capacity = args->sheaf_capacity;
	ret->nr_objs = 0;
	ret->nr_allocated = 0;
	ret->nr_tallocated = 0;
	ret->objs = NULL;
	ret->ctor = ctor;
	ret->ctor = args->ctor;
	ret->non_kernel = 0;
	ret->exec_callback = false;
	ret->callback = NULL;
	ret->private = NULL;

	return ret;
}

+1 −0
Original line number Diff line number Diff line
@@ -3,5 +3,6 @@
/* Very simple shim around the maple tree. */

#include "maple-shared.h"
#include <linux/slab.h>

#include "../../../lib/maple_tree.c"
+1 −91
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <linux/mm.h>
#include <linux/rbtree.h>
#include <linux/refcount.h>
#include <linux/slab.h>

extern unsigned long stack_guard_gap;
#ifdef CONFIG_MMU
@@ -509,65 +510,6 @@ struct pagetable_move_control {
		.len_in = len_,						\
	}

struct kmem_cache_args {
	/**
	 * @align: The required alignment for the objects.
	 *
	 * %0 means no specific alignment is requested.
	 */
	unsigned int align;
	/**
	 * @useroffset: Usercopy region offset.
	 *
	 * %0 is a valid offset, when @usersize is non-%0
	 */
	unsigned int useroffset;
	/**
	 * @usersize: Usercopy region size.
	 *
	 * %0 means no usercopy region is specified.
	 */
	unsigned int usersize;
	/**
	 * @freeptr_offset: Custom offset for the free pointer
	 * in &SLAB_TYPESAFE_BY_RCU caches
	 *
	 * By default &SLAB_TYPESAFE_BY_RCU caches place the free pointer
	 * outside of the object. This might cause the object to grow in size.
	 * Cache creators that have a reason to avoid this can specify a custom
	 * free pointer offset in their struct where the free pointer will be
	 * placed.
	 *
	 * Note that placing the free pointer inside the object requires the
	 * caller to ensure that no fields are invalidated that are required to
	 * guard against object recycling (See &SLAB_TYPESAFE_BY_RCU for
	 * details).
	 *
	 * Using %0 as a value for @freeptr_offset is valid. If @freeptr_offset
	 * is specified, %use_freeptr_offset must be set %true.
	 *
	 * Note that @ctor currently isn't supported with custom free pointers
	 * as a @ctor requires an external free pointer.
	 */
	unsigned int freeptr_offset;
	/**
	 * @use_freeptr_offset: Whether a @freeptr_offset is used.
	 */
	bool use_freeptr_offset;
	/**
	 * @ctor: A constructor for the objects.
	 *
	 * The constructor is invoked for each object in a newly allocated slab
	 * page. It is the cache user's responsibility to free object in the
	 * same state as after calling the constructor, or deal appropriately
	 * with any differences between a freshly constructed and a reallocated
	 * object.
	 *
	 * %NULL means no constructor.
	 */
	void (*ctor)(void *);
};

static inline void vma_iter_invalidate(struct vma_iterator *vmi)
{
	mas_pause(&vmi->mas);
@@ -652,38 +594,6 @@ static inline void vma_init(struct vm_area_struct *vma, struct mm_struct *mm)
	vma->vm_lock_seq = UINT_MAX;
}

struct kmem_cache {
	const char *name;
	size_t object_size;
	struct kmem_cache_args *args;
};

static inline struct kmem_cache *__kmem_cache_create(const char *name,
						     size_t object_size,
						     struct kmem_cache_args *args)
{
	struct kmem_cache *ret = malloc(sizeof(struct kmem_cache));

	ret->name = name;
	ret->object_size = object_size;
	ret->args = args;

	return ret;
}

#define kmem_cache_create(__name, __object_size, __args, ...)           \
	__kmem_cache_create((__name), (__object_size), (__args))

static inline void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags)
{
	return calloc(1, s->object_size);
}

static inline void kmem_cache_free(struct kmem_cache *s, void *x)
{
	free(x);
}

/*
 * These are defined in vma.h, but sadly vm_stat_account() is referenced by
 * kernel/fork.c, so we have to these broadly available there, and temporarily