⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 debugobjects.c

📁 Lib files of linux kernel
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Generic infrastructure for lifetime debugging of objects. * * Started by Thomas Gleixner * * Copyright (C) 2008, Thomas Gleixner <tglx@linutronix.de> * * For licencing details see kernel-base/COPYING */#include <linux/debugobjects.h>#include <linux/interrupt.h>#include <linux/seq_file.h>#include <linux/debugfs.h>#include <linux/hash.h>#define ODEBUG_HASH_BITS	14#define ODEBUG_HASH_SIZE	(1 << ODEBUG_HASH_BITS)#define ODEBUG_POOL_SIZE	512#define ODEBUG_POOL_MIN_LEVEL	256#define ODEBUG_CHUNK_SHIFT	PAGE_SHIFT#define ODEBUG_CHUNK_SIZE	(1 << ODEBUG_CHUNK_SHIFT)#define ODEBUG_CHUNK_MASK	(~(ODEBUG_CHUNK_SIZE - 1))struct debug_bucket {	struct hlist_head	list;	spinlock_t		lock;};static struct debug_bucket	obj_hash[ODEBUG_HASH_SIZE];static struct debug_obj		obj_static_pool[ODEBUG_POOL_SIZE];static DEFINE_SPINLOCK(pool_lock);static HLIST_HEAD(obj_pool);static int			obj_pool_min_free = ODEBUG_POOL_SIZE;static int			obj_pool_free = ODEBUG_POOL_SIZE;static int			obj_pool_used;static int			obj_pool_max_used;static struct kmem_cache	*obj_cache;static int			debug_objects_maxchain __read_mostly;static int			debug_objects_fixups __read_mostly;static int			debug_objects_warnings __read_mostly;static int			debug_objects_enabled __read_mostly;static struct debug_obj_descr	*descr_test  __read_mostly;static int __init enable_object_debug(char *str){	debug_objects_enabled = 1;	return 0;}early_param("debug_objects", enable_object_debug);static const char *obj_states[ODEBUG_STATE_MAX] = {	[ODEBUG_STATE_NONE]		= "none",	[ODEBUG_STATE_INIT]		= "initialized",	[ODEBUG_STATE_INACTIVE]		= "inactive",	[ODEBUG_STATE_ACTIVE]		= "active",	[ODEBUG_STATE_DESTROYED]	= "destroyed",	[ODEBUG_STATE_NOTAVAILABLE]	= "not available",};static int fill_pool(void){	gfp_t gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;	struct debug_obj *new;	unsigned long flags;	if (likely(obj_pool_free >= ODEBUG_POOL_MIN_LEVEL))		return obj_pool_free;	if (unlikely(!obj_cache))		return obj_pool_free;	while (obj_pool_free < ODEBUG_POOL_MIN_LEVEL) {		new = kmem_cache_zalloc(obj_cache, gfp);		if (!new)			return obj_pool_free;		spin_lock_irqsave(&pool_lock, flags);		hlist_add_head(&new->node, &obj_pool);		obj_pool_free++;		spin_unlock_irqrestore(&pool_lock, flags);	}	return obj_pool_free;}/* * Lookup an object in the hash bucket. */static struct debug_obj *lookup_object(void *addr, struct debug_bucket *b){	struct hlist_node *node;	struct debug_obj *obj;	int cnt = 0;	hlist_for_each_entry(obj, node, &b->list, node) {		cnt++;		if (obj->object == addr)			return obj;	}	if (cnt > debug_objects_maxchain)		debug_objects_maxchain = cnt;	return NULL;}/* * Allocate a new object. If the pool is empty, switch off the debugger. * Must be called with interrupts disabled. */static struct debug_obj *alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr){	struct debug_obj *obj = NULL;	spin_lock(&pool_lock);	if (obj_pool.first) {		obj	    = hlist_entry(obj_pool.first, typeof(*obj), node);		obj->object = addr;		obj->descr  = descr;		obj->state  = ODEBUG_STATE_NONE;		hlist_del(&obj->node);		hlist_add_head(&obj->node, &b->list);		obj_pool_used++;		if (obj_pool_used > obj_pool_max_used)			obj_pool_max_used = obj_pool_used;		obj_pool_free--;		if (obj_pool_free < obj_pool_min_free)			obj_pool_min_free = obj_pool_free;	}	spin_unlock(&pool_lock);	return obj;}/* * Put the object back into the pool or give it back to kmem_cache: */static void free_object(struct debug_obj *obj){	unsigned long idx = (unsigned long)(obj - obj_static_pool);	unsigned long flags;	if (obj_pool_free < ODEBUG_POOL_SIZE || idx < ODEBUG_POOL_SIZE) {		spin_lock_irqsave(&pool_lock, flags);		hlist_add_head(&obj->node, &obj_pool);		obj_pool_free++;		obj_pool_used--;		spin_unlock_irqrestore(&pool_lock, flags);	} else {		spin_lock_irqsave(&pool_lock, flags);		obj_pool_used--;		spin_unlock_irqrestore(&pool_lock, flags);		kmem_cache_free(obj_cache, obj);	}}/* * We run out of memory. That means we probably have tons of objects * allocated. */static void debug_objects_oom(void){	struct debug_bucket *db = obj_hash;	struct hlist_node *node, *tmp;	HLIST_HEAD(freelist);	struct debug_obj *obj;	unsigned long flags;	int i;	printk(KERN_WARNING "ODEBUG: Out of memory. ODEBUG disabled\n");	for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) {		spin_lock_irqsave(&db->lock, flags);		hlist_move_list(&db->list, &freelist);		spin_unlock_irqrestore(&db->lock, flags);		/* Now free them */		hlist_for_each_entry_safe(obj, node, tmp, &freelist, node) {			hlist_del(&obj->node);			free_object(obj);		}	}}/* * We use the pfn of the address for the hash. That way we can check * for freed objects simply by checking the affected bucket. */static struct debug_bucket *get_bucket(unsigned long addr){	unsigned long hash;	hash = hash_long((addr >> ODEBUG_CHUNK_SHIFT), ODEBUG_HASH_BITS);	return &obj_hash[hash];}static void debug_print_object(struct debug_obj *obj, char *msg){	static int limit;	if (limit < 5 && obj->descr != descr_test) {		limit++;		WARN(1, KERN_ERR "ODEBUG: %s %s object type: %s\n", msg,		       obj_states[obj->state], obj->descr->name);	}	debug_objects_warnings++;}/* * Try to repair the damage, so we have a better chance to get useful * debug output. */static voiddebug_object_fixup(int (*fixup)(void *addr, enum debug_obj_state state),		   void * addr, enum debug_obj_state state){	if (fixup)		debug_objects_fixups += fixup(addr, state);}static void debug_object_is_on_stack(void *addr, int onstack){	int is_on_stack;	static int limit;	if (limit > 4)		return;	is_on_stack = object_is_on_stack(addr);	if (is_on_stack == onstack)		return;	limit++;	if (is_on_stack)		printk(KERN_WARNING		       "ODEBUG: object is on stack, but not annotated\n");	else		printk(KERN_WARNING		       "ODEBUG: object is not on stack, but annotated\n");	WARN_ON(1);}static void__debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack){	enum debug_obj_state state;	struct debug_bucket *db;	struct debug_obj *obj;	unsigned long flags;	fill_pool();	db = get_bucket((unsigned long) addr);	spin_lock_irqsave(&db->lock, flags);	obj = lookup_object(addr, db);	if (!obj) {		obj = alloc_object(addr, db, descr);		if (!obj) {			debug_objects_enabled = 0;			spin_unlock_irqrestore(&db->lock, flags);			debug_objects_oom();			return;		}		debug_object_is_on_stack(addr, onstack);	}	switch (obj->state) {	case ODEBUG_STATE_NONE:	case ODEBUG_STATE_INIT:	case ODEBUG_STATE_INACTIVE:		obj->state = ODEBUG_STATE_INIT;		break;	case ODEBUG_STATE_ACTIVE:		debug_print_object(obj, "init");		state = obj->state;		spin_unlock_irqrestore(&db->lock, flags);		debug_object_fixup(descr->fixup_init, addr, state);		return;	case ODEBUG_STATE_DESTROYED:		debug_print_object(obj, "init");		break;	default:		break;	}	spin_unlock_irqrestore(&db->lock, flags);}/** * debug_object_init - debug checks when an object is initialized * @addr:	address of the object * @descr:	pointer to an object specific debug description structure */void debug_object_init(void *addr, struct debug_obj_descr *descr){	if (!debug_objects_enabled)		return;	__debug_object_init(addr, descr, 0);}/** * debug_object_init_on_stack - debug checks when an object on stack is *				initialized * @addr:	address of the object * @descr:	pointer to an object specific debug description structure */void debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr){	if (!debug_objects_enabled)		return;	__debug_object_init(addr, descr, 1);}/** * debug_object_activate - debug checks when an object is activated * @addr:	address of the object * @descr:	pointer to an object specific debug description structure */void debug_object_activate(void *addr, struct debug_obj_descr *descr){	enum debug_obj_state state;	struct debug_bucket *db;	struct debug_obj *obj;	unsigned long flags;	if (!debug_objects_enabled)		return;	db = get_bucket((unsigned long) addr);	spin_lock_irqsave(&db->lock, flags);	obj = lookup_object(addr, db);	if (obj) {		switch (obj->state) {		case ODEBUG_STATE_INIT:		case ODEBUG_STATE_INACTIVE:			obj->state = ODEBUG_STATE_ACTIVE;			break;		case ODEBUG_STATE_ACTIVE:			debug_print_object(obj, "activate");			state = obj->state;			spin_unlock_irqrestore(&db->lock, flags);			debug_object_fixup(descr->fixup_activate, addr, state);			return;		case ODEBUG_STATE_DESTROYED:			debug_print_object(obj, "activate");			break;		default:			break;		}		spin_unlock_irqrestore(&db->lock, flags);		return;	}	spin_unlock_irqrestore(&db->lock, flags);	/*	 * This happens when a static object is activated. We	 * let the type specific code decide whether this is	 * true or not.	 */	debug_object_fixup(descr->fixup_activate, addr,			   ODEBUG_STATE_NOTAVAILABLE);}/** * debug_object_deactivate - debug checks when an object is deactivated * @addr:	address of the object * @descr:	pointer to an object specific debug description structure */void debug_object_deactivate(void *addr, struct debug_obj_descr *descr){	struct debug_bucket *db;	struct debug_obj *obj;	unsigned long flags;	if (!debug_objects_enabled)		return;	db = get_bucket((unsigned long) addr);	spin_lock_irqsave(&db->lock, flags);	obj = lookup_object(addr, db);	if (obj) {		switch (obj->state) {		case ODEBUG_STATE_INIT:		case ODEBUG_STATE_INACTIVE:		case ODEBUG_STATE_ACTIVE:			obj->state = ODEBUG_STATE_INACTIVE;			break;		case ODEBUG_STATE_DESTROYED:			debug_print_object(obj, "deactivate");			break;		default:			break;		}	} else {		struct debug_obj o = { .object = addr,				       .state = ODEBUG_STATE_NOTAVAILABLE,				       .descr = descr };		debug_print_object(&o, "deactivate");	}	spin_unlock_irqrestore(&db->lock, flags);}/** * debug_object_destroy - debug checks when an object is destroyed * @addr:	address of the object * @descr:	pointer to an object specific debug description structure */void debug_object_destroy(void *addr, struct debug_obj_descr *descr){	enum debug_obj_state state;	struct debug_bucket *db;	struct debug_obj *obj;	unsigned long flags;	if (!debug_objects_enabled)		return;	db = get_bucket((unsigned long) addr);	spin_lock_irqsave(&db->lock, flags);	obj = lookup_object(addr, db);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -