2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
3 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
\r
5 * This software is available to you under the OpenIB.org BSD license
\r
8 * Redistribution and use in source and binary forms, with or
\r
9 * without modification, are permitted provided that the following
\r
10 * conditions are met:
\r
12 * - Redistributions of source code must retain the above
\r
13 * copyright notice, this list of conditions and the following
\r
16 * - Redistributions in binary form must reproduce the above
\r
17 * copyright notice, this list of conditions and the following
\r
18 * disclaimer in the documentation and/or other materials
\r
19 * provided with the distribution.
\r
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
25 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
26 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
37 * Implementation of memory allocation tracking functions.
\r
44 #include "cl_memtrack.h"
\r
47 cl_mem_tracker_t *gp_mem_tracker = NULL;
\r
55 IN const size_t size,
\r
56 IN const boolean_t pageable );
\r
60 * Deallocates memory.
\r
64 IN void* const p_memory );
\r
68 * Allocate and initialize the memory tracker object.
\r
71 __cl_mem_track_start( void )
\r
75 if( gp_mem_tracker )
\r
78 /* Allocate the memory tracker object. */
\r
79 gp_mem_tracker = (cl_mem_tracker_t*)
\r
80 __cl_malloc_priv( sizeof(cl_mem_tracker_t), FALSE );
\r
82 if( !gp_mem_tracker )
\r
85 /* Initialize the free list. */
\r
86 cl_qlist_init( &gp_mem_tracker->free_hdr_list );
\r
87 /* Initialize the allocation list. */
\r
88 cl_qmap_init( &gp_mem_tracker->alloc_map );
\r
90 /* Initialize the spin lock to protect list operations. */
\r
91 status = cl_spinlock_init( &gp_mem_tracker->lock );
\r
92 if( status != CL_SUCCESS )
\r
94 __cl_free_priv( gp_mem_tracker );
\r
101 * Clean up memory tracking.
\r
104 __cl_mem_track_stop( void )
\r
106 cl_map_item_t *p_map_item;
\r
107 cl_list_item_t *p_list_item;
\r
109 if( !gp_mem_tracker )
\r
112 if( cl_qmap_count( &gp_mem_tracker->alloc_map ) )
\r
114 /* There are still items in the list. Print them out. */
\r
118 /* Free all allocated headers. */
\r
119 cl_spinlock_acquire( &gp_mem_tracker->lock );
\r
120 while( cl_qmap_count( &gp_mem_tracker->alloc_map ) )
\r
122 p_map_item = cl_qmap_head( &gp_mem_tracker->alloc_map );
\r
123 cl_qmap_remove_item( &gp_mem_tracker->alloc_map, p_map_item );
\r
125 PARENT_STRUCT( p_map_item, cl_malloc_hdr_t, map_item ) );
\r
128 while( cl_qlist_count( &gp_mem_tracker->free_hdr_list ) )
\r
130 p_list_item = cl_qlist_remove_head( &gp_mem_tracker->free_hdr_list );
\r
131 __cl_free_priv( PARENT_STRUCT(
\r
132 p_list_item, cl_malloc_hdr_t, map_item.pool_item.list_item ) );
\r
134 cl_spinlock_release( &gp_mem_tracker->lock );
\r
136 /* Destory all objects in the memory tracker object. */
\r
137 cl_spinlock_destroy( &gp_mem_tracker->lock );
\r
139 /* Free the memory allocated for the memory tracker object. */
\r
140 __cl_free_priv( gp_mem_tracker );
\r
141 gp_mem_tracker = NULL;
\r
146 * Enables memory allocation tracking.
\r
150 IN const boolean_t start )
\r
153 __cl_mem_track_start();
\r
155 __cl_mem_track_stop();
\r
160 * Display memory usage.
\r
163 cl_mem_display( void )
\r
165 cl_map_item_t *p_map_item;
\r
166 cl_malloc_hdr_t *p_hdr;
\r
168 if( !gp_mem_tracker )
\r
171 cl_spinlock_acquire( &gp_mem_tracker->lock );
\r
172 cl_msg_out( "\n\n\n*** Memory Usage ***\n" );
\r
173 p_map_item = cl_qmap_head( &gp_mem_tracker->alloc_map );
\r
174 while( p_map_item != cl_qmap_end( &gp_mem_tracker->alloc_map ) )
\r
177 * Get the pointer to the header. Note that the object member of the
\r
178 * list item will be used to store the pointer to the user's memory.
\r
180 p_hdr = PARENT_STRUCT( p_map_item, cl_malloc_hdr_t, map_item );
\r
182 cl_msg_out( "\tMemory block at %p allocated in file %s line %d\n",
\r
183 p_hdr->p_mem, p_hdr->file_name, p_hdr->line_num );
\r
185 p_map_item = cl_qmap_next( p_map_item );
\r
187 cl_msg_out( "*** End of Memory Usage ***\n\n" );
\r
188 cl_spinlock_release( &gp_mem_tracker->lock );
\r
193 * Allocates memory and stores information about the allocation in a list.
\r
194 * The contents of the list can be printed out by calling the function
\r
195 * "MemoryReportUsage". Memory allocation will succeed even if the list
\r
196 * cannot be created.
\r
200 IN const char* const p_file_name,
\r
201 IN const int32_t line_num,
\r
202 IN const size_t size,
\r
203 IN const boolean_t pageable )
\r
205 cl_malloc_hdr_t *p_hdr;
\r
206 cl_list_item_t *p_list_item;
\r
208 uint64_t temp_buf[FILE_NAME_LENGTH/sizeof(uint64_t)];
\r
212 * Allocate the memory first, so that we give the user's allocation
\r
213 * priority over the the header allocation.
\r
215 p_mem = __cl_malloc_priv( size, pageable );
\r
220 if( !gp_mem_tracker )
\r
224 * Make copies of the file name and line number in case those
\r
225 * parameters are in paged pool.
\r
227 temp_line = line_num;
\r
228 strncpy( (char*)temp_buf, p_file_name, FILE_NAME_LENGTH );
\r
229 /* Make sure the string is null terminated. */
\r
230 ((char*)temp_buf)[FILE_NAME_LENGTH - 1] = '\0';
\r
232 cl_spinlock_acquire( &gp_mem_tracker->lock );
\r
234 /* Get a header from the free header list. */
\r
235 p_list_item = cl_qlist_remove_head( &gp_mem_tracker->free_hdr_list );
\r
236 if( p_list_item != cl_qlist_end( &gp_mem_tracker->free_hdr_list ) )
\r
238 /* Set the header pointer to the header retrieved from the list. */
\r
239 p_hdr = PARENT_STRUCT( p_list_item, cl_malloc_hdr_t,
\r
240 map_item.pool_item.list_item );
\r
244 /* We failed to get a free header. Allocate one. */
\r
245 p_hdr = __cl_malloc_priv( sizeof(cl_malloc_hdr_t), FALSE );
\r
248 /* We failed to allocate the header. Return the user's memory. */
\r
249 cl_spinlock_release( &gp_mem_tracker->lock );
\r
253 cl_memcpy( p_hdr->file_name, temp_buf, FILE_NAME_LENGTH );
\r
254 p_hdr->line_num = temp_line;
\r
256 * We store the pointer to the memory returned to the user. This allows
\r
257 * searching the list of allocated memory even if the buffer allocated is
\r
258 * not in the list without dereferencing memory we do not own.
\r
260 p_hdr->p_mem = p_mem;
\r
262 /* Insert the header structure into our allocation list. */
\r
263 cl_qmap_insert( &gp_mem_tracker->alloc_map, (uintn_t)p_mem, &p_hdr->map_item );
\r
264 cl_spinlock_release( &gp_mem_tracker->lock );
\r
271 * Allocate non-tracked memory.
\r
275 IN const size_t size,
\r
276 IN const boolean_t pageable )
\r
278 return( __cl_malloc_priv( size, pageable ) );
\r
284 IN const char* const p_file_name,
\r
285 IN const int32_t line_num,
\r
286 IN const size_t size,
\r
287 IN const boolean_t pageable )
\r
291 p_buffer = __cl_malloc_trk( p_file_name, line_num, size, pageable );
\r
293 cl_memclr( p_buffer, size );
\r
295 return( p_buffer );
\r
301 IN const size_t size,
\r
302 IN const boolean_t pageable )
\r
306 p_buffer = __cl_malloc_priv( size, pageable );
\r
308 cl_memclr( p_buffer, size );
\r
310 return( p_buffer );
\r
316 IN void* const p_memory )
\r
318 cl_malloc_hdr_t *p_hdr;
\r
319 cl_map_item_t *p_map_item;
\r
321 if( gp_mem_tracker )
\r
323 cl_spinlock_acquire( &gp_mem_tracker->lock );
\r
326 * Removes an item from the allocation tracking list given a pointer
\r
327 * To the user's data and returns the pointer to header referencing the
\r
328 * allocated memory block.
\r
330 p_map_item = cl_qmap_get( &gp_mem_tracker->alloc_map, (uintn_t)p_memory );
\r
331 if( p_map_item != cl_qmap_end( &gp_mem_tracker->alloc_map ) )
\r
333 /* Get the pointer to the header. */
\r
334 p_hdr = PARENT_STRUCT( p_map_item, cl_malloc_hdr_t, map_item );
\r
335 /* Remove the item from the list. */
\r
336 cl_qmap_remove_item( &gp_mem_tracker->alloc_map, p_map_item );
\r
338 /* Return the header to the free header list. */
\r
339 cl_qlist_insert_head( &gp_mem_tracker->free_hdr_list,
\r
340 &p_hdr->map_item.pool_item.list_item );
\r
342 cl_spinlock_release( &gp_mem_tracker->lock );
\r
344 __cl_free_priv( p_memory );
\r
350 IN void* const p_memory )
\r
352 __cl_free_priv( p_memory );
\r