| lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  *  linux/mm/mem_tracker.c | 
 | 3 |  * | 
 | 4 |  *  Copyright (C) 1993  Linus Torvalds | 
 | 5 |  *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 | 
 | 6 |  *   vmalloc/vfree, Tigran Aivazian <tigran@veritas.com>, May 2000 | 
 | 7 |  *  Major rework to support vmap/vunmap, Christoph Hellwig, SGI, August 2002 | 
 | 8 |  *  Numa awareness, Christoph Lameter, SGI, June 2005 | 
 | 9 |  */ | 
 | 10 | #include <linux/mm.h> | 
 | 11 | #include <linux/sched.h> | 
 | 12 | #include <linux/spinlock.h> | 
 | 13 | #include <linux/interrupt.h> | 
 | 14 | #include <linux/kallsyms.h> | 
 | 15 | #include <linux/list.h> | 
 | 16 | #include <linux/pfn.h> | 
 | 17 | #include <linux/atomic.h> | 
 | 18 | #include <asm/stacktrace.h> | 
 | 19 | #include <mach/iomap.h> | 
 | 20 | #include <linux/kprobes.h> | 
 | 21 | #include <asm/traps.h> | 
 | 22 | #include <linux/mem_tracker_def.h> | 
 | 23 |  | 
 | 24 | /******************************************************************************* | 
 | 25 | *                                   ºê¶¨Òå                                     * | 
 | 26 | *******************************************************************************/ | 
 | 27 | #ifdef CONFIG_KALLSYMS | 
 | 28 | #define MEM_TRACKER_MAX_STACK_LEN  	(100)  /*Õ»º¯Êý¹ì¼£µÄ×Ö·û¸öÊýÉÏÏÞ£»*/ | 
 | 29 | #endif  | 
 | 30 | #define MEM_TRACKER_MAX_STACK_LEVEL (6)    /*Õ»µÄ²ãÊý*/ | 
 | 31 | #define MEM_TRACKER_NOT_TRACE_LEVEL (2) | 
 | 32 | #define MEM_TRACKER_ALLOCED         0x00 | 
 | 33 | #define MEM_TRACKER_FREED          	0x02 | 
 | 34 |  | 
 | 35 | /******************************************************************************* | 
 | 36 | *                                Êý¾ÝÀàÐͶ¨Òå                                  * | 
 | 37 | *******************************************************************************/ | 
 | 38 | struct heap_record { | 
 | 39 |     struct list_head    node; | 
 | 40 | 	void	 			*addr;    /*ÉêÇë³öµÄÄÚ´æµØÖ·*/ | 
 | 41 | 	unsigned int        employ:8; | 
 | 42 |     unsigned int 		size:24;	  /*¼Ç¼ÉêÇëµÄÄڴ泤¶È*/ | 
 | 43 | 	char                task_name[TASK_COMM_LEN]; | 
 | 44 | #ifdef CONFIG_KALLSYMS | 
 | 45 |     char				stack_frame[MEM_TRACKER_MAX_STACK_LEVEL][MEM_TRACKER_MAX_STACK_LEN]; | 
 | 46 | 								/*º¯Êý»ØËݹ켣*/ | 
 | 47 | #else | 
 | 48 | 	unsigned long 	    stack_frame[MEM_TRACKER_MAX_STACK_LEVEL]; | 
 | 49 | #endif | 
 | 50 | }; | 
 | 51 |  | 
 | 52 | /******************************************************************************* | 
 | 53 | *                                º¯ÊýÉùÃ÷                                  * | 
 | 54 | *******************************************************************************/ | 
 | 55 | /******************************************************************************* | 
 | 56 | *								 È«¾Ö±äÁ¿¶¨Òå								   * | 
 | 57 | *******************************************************************************/ | 
 | 58 | int 				kmem_node_max; | 
 | 59 | int 				node_list_max;      | 
 | 60 | static spinlock_t  	buddy_track_lock; | 
 | 61 | static spinlock_t  	kmem_track_lock; | 
 | 62 |  | 
 | 63 |  | 
 | 64 | /*ÕýÔÚʹÓõÄÊý¾ÝÁ´±í*/ | 
 | 65 | static LIST_HEAD(buddy_employ_head); | 
 | 66 | static LIST_HEAD(kmem_employ_head); | 
 | 67 |  | 
 | 68 | /*ÒѾÊͷŵÄÊý¾ÝÁ´±í*/ | 
 | 69 | static LIST_HEAD(buddy_free_head); | 
 | 70 | static LIST_HEAD(kmem_free_head); | 
 | 71 |  | 
 | 72 | /******************************************************************************* | 
 | 73 | *                                ¾Ö²¿º¯ÊýʵÏÖ                                  * | 
 | 74 | *******************************************************************************/ | 
 | 75 | static void memset_tracker(struct heap_record * node) | 
 | 76 | { | 
 | 77 | 	node->size = 0; | 
 | 78 | 	node->addr = NULL; | 
 | 79 | 	 | 
 | 80 | 	memset(node->task_name,0, TASK_COMM_LEN); | 
 | 81 | 	memset(node->stack_frame, 0, sizeof(node->stack_frame)); | 
 | 82 | } | 
 | 83 |  | 
 | 84 | /******************************************************************************* | 
 | 85 | * ¹¦ÄÜÃèÊö: 	¶Ôµ±Ç°Õ»½øÐлØËÝ£¬½«º¯Êý¹ì¼£±£´æ | 
 | 86 | * ²ÎÊý˵Ã÷: 	 | 
 | 87 | *	(´«Èë²ÎÊý)	my_frame:¹ì¼£ÐÅÏ¢±£´æµÄµØÖ· | 
 | 88 | *                | 
 | 89 | *	(´«³ö²ÎÊý)	void | 
 | 90 | * ·µ »Ø Öµ: 	void | 
 | 91 | * ÆäËü˵Ã÷: 	ÎÞ | 
 | 92 | *******************************************************************************/ | 
 | 93 | #ifdef CONFIG_KALLSYMS | 
 | 94 | void get_stack_process(unsigned char *my_frame) | 
 | 95 | #else | 
 | 96 | void get_stack_process(unsigned long *my_frame) | 
 | 97 | #endif  | 
 | 98 | { | 
 | 99 | 	int urc; | 
 | 100 | 	int i 	= 0; | 
 | 101 | #ifdef CONFIG_KALLSYMS | 
 | 102 | 	char mytmp[MEM_TRACKER_MAX_STACK_LEN] = {0}; | 
 | 103 | #endif | 
 | 104 | 	struct stackframe frame; | 
 | 105 | 	register unsigned long current_sp asm ("sp"); | 
 | 106 |  | 
 | 107 | #ifndef CONFIG_KALLSYMS | 
 | 108 |     memset(my_frame, 0, MEM_TRACKER_MAX_STACK_LEVEL * sizeof(unsigned long)); | 
 | 109 | #endif | 
 | 110 |  | 
 | 111 | 	frame.fp = (unsigned long)__builtin_frame_address(0); | 
 | 112 | 	frame.lr = (unsigned long)__builtin_return_address(0); | 
 | 113 | 	frame.sp = current_sp; | 
 | 114 | 	frame.pc = (unsigned long)get_stack_process; | 
 | 115 |  | 
 | 116 | 	while (1) {		 | 
 | 117 | 		urc = unwind_frame(&frame); | 
 | 118 | 		/*Èô»ØËݽáÊø£¬ÔòÁ¢¼´Í˳ö*/ | 
 | 119 | 		if (urc < 0) | 
 | 120 | 		    return; | 
 | 121 |  | 
 | 122 | 		/*ΪÁ˽ÚÊ¡Äڴ棬×îÉϲãµÄ2¸öº¯Êý²»¸ú×Ù*/ | 
 | 123 | 		if (++i >= MEM_TRACKER_NOT_TRACE_LEVEL) { | 
 | 124 | #ifdef CONFIG_KALLSYMS | 
 | 125 | 			snprintf(mytmp, MEM_TRACKER_MAX_STACK_LEN - 1, "<%ps>", (void *)frame.pc); | 
 | 126 | 			strcpy(my_frame + ((i - MEM_TRACKER_NOT_TRACE_LEVEL) * MEM_TRACKER_MAX_STACK_LEN), mytmp); | 
 | 127 | #else | 
 | 128 | 			my_frame[i - MEM_TRACKER_NOT_TRACE_LEVEL] = (unsigned long)frame.pc; | 
 | 129 | #endif	 | 
 | 130 | 			if (i - MEM_TRACKER_NOT_TRACE_LEVEL >= MEM_TRACKER_MAX_STACK_LEVEL - 1) | 
 | 131 | 				return; | 
 | 132 | 		} | 
 | 133 | 	} | 
 | 134 | } | 
 | 135 |  | 
 | 136 | /******************************************************************************* | 
 | 137 | * ¹¦ÄÜÃèÊö: 	»ñÈ¡×îºóÒ»¸ö½Úµã | 
 | 138 | * ²ÎÊý˵Ã÷: 	 | 
 | 139 | *	(´«Èë²ÎÊý)	head:Á´±íÍ· | 
 | 140 | *	(´«³ö²ÎÊý)	track¸ú×ÙÐÅÏ¢ | 
 | 141 | * ·µ »Ø Öµ: 	void | 
 | 142 | * ÆäËü˵Ã÷: 	ÎÞ | 
 | 143 | *******************************************************************************/ | 
 | 144 | static struct list_head *list_get_last_node(struct list_head *head) | 
 | 145 | { | 
 | 146 |  	struct heap_record 	*h 		   = NULL; | 
 | 147 | 	struct list_head 	*tail_node = NULL; | 
 | 148 | 	 | 
 | 149 |  	if (list_empty(head)) | 
 | 150 | 		return NULL; | 
 | 151 |  | 
 | 152 |     tail_node = head->prev; | 
 | 153 | 	 | 
 | 154 | 	h = container_of(tail_node, struct heap_record, node); | 
 | 155 | 	 | 
 | 156 |     if(h->employ == MEM_TRACKER_FREED) | 
 | 157 | 		list_del(head->prev);		 | 
 | 158 | 	else | 
 | 159 | 		panic("[MEM_TRACKER]list error"); | 
 | 160 | 	 | 
 | 161 | 	return tail_node; | 
 | 162 | } | 
 | 163 |  | 
 | 164 | /******************************************************************************* | 
 | 165 | * ¹¦ÄÜÃèÊö:     ÄÚ´æ¸ú×Ù³õʼ»¯ | 
 | 166 | * ²ÎÊý˵Ã÷:      | 
 | 167 | *   (´«Èë²ÎÊý)  void              | 
 | 168 | *   (´«³ö²ÎÊý)  void | 
 | 169 | * ·µ »Ø Öµ:     void | 
 | 170 | * ÆäËü˵Ã÷:    ΪʵÏÖÄÚ´æ¹ì¼£¸ú×Ùʱ²»Õ¼ÓÃÏÖÓÐÄڴ棬ʹÓÃ64MÒÔºóµÄÄÚ´æ  | 
 | 171 | *******************************************************************************/ | 
 | 172 | void mem_trace_init(void) | 
 | 173 | { | 
 | 174 |     int 				index; | 
 | 175 | 	unsigned long 		flags; | 
 | 176 |     struct heap_record *record = NULL; | 
 | 177 | 	void __iomem 		*base  = NULL; | 
 | 178 | 	 | 
 | 179 |     spin_lock_init(&buddy_track_lock); | 
 | 180 | 	 | 
 | 181 |     spin_lock_irqsave(&buddy_track_lock, flags); | 
 | 182 | 	 | 
 | 183 | 	base 			= ZX_MEM_TRACKER_BASE;  | 
 | 184 | 	node_list_max 	= ZX_MEM_TRACKER_SIZE / sizeof(struct heap_record); | 
 | 185 |  | 
 | 186 | 	/* ³õʼ»¯¿ÕÏÐÄÚ´æ½ÚµãÁ´±í */ | 
 | 187 |     for (index = 0; index < node_list_max; index++) | 
 | 188 |     { | 
 | 189 |         record = (struct heap_record *)(base + index * sizeof(struct heap_record)); | 
 | 190 | 		record->employ = MEM_TRACKER_FREED; | 
 | 191 | 		list_add(&record->node, &buddy_free_head); | 
 | 192 |     } | 
 | 193 | 	 | 
 | 194 |     spin_unlock_irqrestore(&buddy_track_lock, flags); | 
 | 195 | } | 
 | 196 |  | 
 | 197 |  | 
 | 198 | /******************************************************************************* | 
 | 199 | * ¹¦ÄÜÃèÊö:     kmallocÄÚ´æ¸ú×Ù³õʼ»¯ | 
 | 200 | * ²ÎÊý˵Ã÷:      | 
 | 201 | *   (´«Èë²ÎÊý)  void              | 
 | 202 | *   (´«³ö²ÎÊý)  void | 
 | 203 | * ·µ »Ø Öµ:     void | 
 | 204 | * ÆäËü˵Ã÷:    ΪʵÏÖÄÚ´æ¹ì¼£¸ú×Ùʱ²»Õ¼ÓÃÏÖÓÐÄڴ棬ʹÓÃ64MÒÔºóµÄÄÚ´æ  | 
 | 205 | *******************************************************************************/ | 
 | 206 | void kmalloc_trace_init(void) | 
 | 207 | { | 
 | 208 |     int 				index; | 
 | 209 | 	unsigned long 		flags; | 
 | 210 |     struct heap_record *record = NULL; | 
 | 211 | 	void __iomem 		*base  = NULL; | 
 | 212 | 	 | 
 | 213 | 	spin_lock_init(&kmem_track_lock); | 
 | 214 | 	spin_lock_irqsave(&kmem_track_lock, flags); | 
 | 215 |  | 
 | 216 | 	base 			= ZX_KMALLOC_TRACKER_BASE;  | 
 | 217 | 	kmem_node_max 	= ZX_KMALLOC_TRACKER_SIZE / sizeof(struct heap_record); | 
 | 218 |  | 
 | 219 | 	/* ³õʼ»¯¿ÕÏÐÄÚ´æ½ÚµãÁ´±í */ | 
 | 220 |     for (index = 0; index < kmem_node_max; index++) | 
 | 221 |     { | 
 | 222 |         record = (struct heap_record *)(base + index * sizeof(struct heap_record)); | 
 | 223 | 		record->employ = MEM_TRACKER_FREED; | 
 | 224 | 		list_add(&record->node, &kmem_free_head); | 
 | 225 |     } | 
 | 226 |  | 
 | 227 |     spin_unlock_irqrestore(&kmem_track_lock, flags); | 
 | 228 | } | 
 | 229 |  | 
 | 230 | /******************************************************************************* | 
 | 231 | * ¹¦ÄÜÃèÊö:     ÑéÖ¤entry½ÚµãºÏ·¨ÐÔ | 
 | 232 | * ²ÎÊý˵Ã÷:      | 
 | 233 | *   (´«Èë²ÎÊý)  void              | 
 | 234 | *   (´«³ö²ÎÊý)  void | 
 | 235 | * ·µ »Ø Öµ:     void | 
 | 236 | * ÆäËü˵Ã÷:    ΪʵÏÖÄÚ´æ¹ì¼£¸ú×Ùʱ²»Õ¼ÓÃÏÖÓÐÄڴ棬ʹÓÃ64MÒÔºóµÄÄÚ´æ  | 
 | 237 | *******************************************************************************/ | 
 | 238 | int check_node_entry(const int entry) | 
 | 239 | { | 
 | 240 | 	void __iomem *base	= NULL; | 
 | 241 | 	long		 limit  = 0;	  | 
 | 242 | 	 | 
 | 243 | 	base  = ZX_KMALLOC_TRACKER_BASE;  | 
 | 244 | 	limit = ZX_KMALLOC_TRACKER_SIZE + (int)base; | 
 | 245 | 	 | 
 | 246 | 	if ((entry >= base) && (entry < limit)) | 
 | 247 | 		return MEM_TRUE; | 
 | 248 | 	 | 
 | 249 | 	return MEM_FALSE; | 
 | 250 | } | 
 | 251 |  | 
 | 252 | /******************************************************************************* | 
 | 253 | * ¹¦ÄÜÃèÊö: 	ÉêÇëÄÚ´æµãµ÷Óøýӿڣ¬¼Ç¼ÄÚ´æÉêÇë¹ì¼£ | 
 | 254 | * ²ÎÊý˵Ã÷: 	 | 
 | 255 | *	(´«Èë²ÎÊý)	addr:ÄÚ´æµØÖ· | 
 | 256 | *               order:Äڴ泤¶È,orderΪµ¥Î»£¬2µÄorder´Î·½¸öÒ³ | 
 | 257 | *	(´«³ö²ÎÊý)	void | 
 | 258 | * ·µ »Ø Öµ: 	void | 
 | 259 | * ÆäËü˵Ã÷: 	ÎÞ | 
 | 260 | *******************************************************************************/ | 
 | 261 | void mem_alloc_tracker(void *addr, int order) | 
 | 262 | { | 
 | 263 |     unsigned long 		spin_flag; | 
 | 264 |     struct heap_record  *section    = NULL; | 
 | 265 | 	struct list_head 	*head_ptr  = NULL;  | 
 | 266 | 	struct page 		*page_addr = NULL; | 
 | 267 |  | 
 | 268 | 	if(!addr) | 
 | 269 | 		panic("[MEM_TRACKER] input item error\n"); | 
 | 270 |  | 
 | 271 | 	page_addr = (struct page *)(addr); | 
 | 272 |    	 | 
 | 273 |     spin_lock_irqsave(&buddy_track_lock, spin_flag); | 
 | 274 |     if (!(head_ptr = list_get_last_node(&buddy_free_head))) | 
 | 275 |     { | 
 | 276 | 		printk("[MEM_TRACKER]buddy free_link_node have no node!!!\n"); | 
 | 277 | 		spin_unlock_irqrestore(&buddy_track_lock, spin_flag); | 
 | 278 | 		return; | 
 | 279 |     } | 
 | 280 |     spin_unlock_irqrestore(&buddy_track_lock, spin_flag); | 
 | 281 | 	section = container_of(head_ptr, struct heap_record, node); | 
 | 282 |  | 
 | 283 | 	/*³õʼ»¯½ÚµãÐÅÏ¢*/ | 
 | 284 |     memset_tracker(section); | 
 | 285 | 	section->addr 	= addr; | 
 | 286 | 	section->size 	= (1 << order) * PAGE_SIZE; | 
 | 287 | 	section->employ = MEM_TRACKER_ALLOCED; | 
 | 288 | 	memcpy(section->task_name, current->comm, TASK_COMM_LEN);	 | 
 | 289 |  | 
 | 290 | 	/*»ñȡջ¹ì¼£*/ | 
 | 291 | 	get_stack_process(section->stack_frame); | 
 | 292 | 	page_addr->mem_track_entry = section; | 
 | 293 | 	 | 
 | 294 | 	/*¼ÓÈëÒÑÉêÇëÄÚ´æ½Úµã¼Ç¼Á´±í*/ | 
 | 295 |     spin_lock_irqsave(&buddy_track_lock, spin_flag); | 
 | 296 |     list_add(§ion->node, &buddy_employ_head); | 
 | 297 |     spin_unlock_irqrestore(&buddy_track_lock,spin_flag); | 
 | 298 | } | 
 | 299 | EXPORT_SYMBOL(mem_alloc_tracker); | 
 | 300 |  | 
 | 301 | /******************************************************************************* | 
 | 302 | * ¹¦ÄÜÃèÊö: 	kmallocÉêÇëÄÚ´æµãµ÷Óøýӿڣ¬¼Ç¼ÄÚ´æÉêÇë¹ì¼£ | 
 | 303 | * ²ÎÊý˵Ã÷: 	 | 
 | 304 | *	(´«Èë²ÎÊý)	addr:ÄÚ´æµØÖ· | 
 | 305 | *               len:Äڴ泤¶È | 
 | 306 | *	(´«³ö²ÎÊý)	void | 
 | 307 | * ·µ »Ø Öµ: 	void | 
 | 308 | * ÆäËü˵Ã÷: 	ÎÞ | 
 | 309 | *******************************************************************************/ | 
 | 310 | void kmalloc_alloc_tracker(void *addr, int len) | 
 | 311 | { | 
 | 312 |     unsigned long 		spin_flag; | 
 | 313 |     struct heap_record *section   		  = NULL; | 
 | 314 | 	struct list_head 	*head_ptr 	      = NULL; | 
 | 315 | 	struct list_head 	*free_node_head   = NULL;                                          | 
 | 316 | 	struct list_head 	*employ_node_head = NULL;   | 
 | 317 | 	struct page 		*page_addr 	      = NULL; | 
 | 318 |  | 
 | 319 | 	if(!addr) | 
 | 320 | 		panic("[MEM_TRACKER] input item error\n"); | 
 | 321 |  | 
 | 322 | 	free_node_head   = &kmem_free_head; | 
 | 323 | 	employ_node_head = &kmem_employ_head; | 
 | 324 | 	 | 
 | 325 |     spin_lock_irqsave(&kmem_track_lock, spin_flag); | 
 | 326 |      | 
 | 327 |     if (!(head_ptr = list_get_last_node(free_node_head))) | 
 | 328 |     { | 
 | 329 | 		printk("[MEM_TRACKER]kmalloc free_link_node have no node!!!\n"); | 
 | 330 | 		spin_unlock_irqrestore(&kmem_track_lock, spin_flag); | 
 | 331 | 		return; | 
 | 332 |     } | 
 | 333 |     spin_unlock_irqrestore(&kmem_track_lock, spin_flag); | 
 | 334 |  | 
 | 335 | 	section = container_of(head_ptr, struct heap_record, node); | 
 | 336 |  | 
 | 337 | 	/*³õʼ»¯½ÚµãÐÅÏ¢*/ | 
 | 338 |     memset_tracker(section); | 
 | 339 | 	section->addr 	= KMALLOC_SETUP(addr); | 
 | 340 | 	section->size 	= len; | 
 | 341 | 	section->employ = MEM_TRACKER_ALLOCED; | 
 | 342 | 	memcpy(section->task_name, current->comm, TASK_COMM_LEN);	 | 
 | 343 |  | 
 | 344 | 	/*»ñȡջ¹ì¼£*/ | 
 | 345 | 	get_stack_process(section->stack_frame); | 
 | 346 | 	KMALLOC_SET_ENTRY(addr, section); | 
 | 347 |  | 
 | 348 | 	if(MEM_FALSE == check_node_entry(section)) | 
 | 349 | 		panic("error"); | 
 | 350 |   | 
 | 351 | 	/*¼ÓÈëÒÑÉêÇëÄÚ´æ½Úµã¼Ç¼Á´±í*/ | 
 | 352 |     spin_lock_irqsave(&kmem_track_lock, spin_flag); | 
 | 353 |     list_add(§ion->node, employ_node_head); | 
 | 354 | 	 | 
 | 355 |     spin_unlock_irqrestore(&kmem_track_lock,spin_flag); | 
 | 356 | } | 
 | 357 | EXPORT_SYMBOL(kmalloc_alloc_tracker); | 
 | 358 |  | 
 | 359 | /******************************************************************************* | 
 | 360 | * ¹¦ÄÜÃèÊö: 	ÊÍ·ÅÄÚ´æµãµ÷ÓÃ¸Ã½Ó¿Ú | 
 | 361 | * ²ÎÊý˵Ã÷: 	 | 
 | 362 | *	(´«Èë²ÎÊý)	entry:ÄÚ´æµØÖ·         | 
 | 363 | *	(´«³ö²ÎÊý)	void | 
 | 364 | * ·µ »Ø Öµ: 	void | 
 | 365 | * ÆäËü˵Ã÷: 	ÎÞ | 
 | 366 | *******************************************************************************/ | 
 | 367 | void mem_free_tracker(void *entry, int type) | 
 | 368 | { | 
 | 369 |     unsigned long 	   spin_flag; | 
 | 370 | 	spinlock_t 		   *mem_lock       = NULL; | 
 | 371 | 	struct list_head   *free_node_head = NULL;      | 
 | 372 |     struct heap_record *free_node = (struct heap_record *)entry; | 
 | 373 |  | 
 | 374 |     if (entry == NULL) | 
 | 375 | 		return; | 
 | 376 |  | 
 | 377 | 	if (type == MEM_TRACKER_TYPE_BUDDY) | 
 | 378 | 	{ | 
 | 379 | 		mem_lock = &buddy_track_lock; | 
 | 380 | 		free_node_head = &buddy_free_head; | 
 | 381 | 	} | 
 | 382 | 	else if (type == MEM_TRACKER_TYPE_KMALLOC) | 
 | 383 | 	{ | 
 | 384 | 		mem_lock = &kmem_track_lock; | 
 | 385 | 		free_node_head = &kmem_free_head; | 
 | 386 | 	} | 
 | 387 | 	else | 
 | 388 | 		panic("mem_tracker type error\n"); | 
 | 389 |  | 
 | 390 |     spin_lock_irqsave(mem_lock, spin_flag); | 
 | 391 |  | 
 | 392 | 	if (free_node->employ == MEM_TRACKER_ALLOCED) | 
 | 393 | 	{ | 
 | 394 | 		free_node->employ = MEM_TRACKER_FREED;	 | 
 | 395 | 		list_move(&free_node->node, free_node_head); | 
 | 396 | 	} | 
 | 397 | 	else  | 
 | 398 | 	{		     | 
 | 399 | 		printk("[MEM_TRACKER]error: employ is 0x%x  employ_node MEM_TRACKER_FREED !!\n", free_node->employ); | 
 | 400 | 	} | 
 | 401 | 	 | 
 | 402 | 	spin_unlock_irqrestore(mem_lock, spin_flag);		   | 
 | 403 | } | 
 | 404 | EXPORT_SYMBOL(mem_free_tracker); | 
 | 405 |  | 
 | 406 |  | 
 | 407 |  |