4 * @brief Memory allocation with LEAK_DETECTION support
6 * Thread-save implementation
10 * Copyright (C) 2005 Jan Hutter, Martin Willi
11 * Hochschule fuer Technik Rapperswil
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
35 #include "allocator.h"
41 * Header of each allocated memory area
43 * Used to detect memory leaks
45 typedef union memory_hdr_u memory_hdr_t
;
50 * Filename withing memory was allocated
54 * Line number in given file
58 * Allocated memory size. Needed for reallocation
60 size_t size_of_memory
;
62 * Link to the previous and next memory area
64 memory_hdr_t
*older
, *newer
;
67 * force maximal alignment ?
73 * @brief Private allocator_t object.
75 * Contains private variables of allocator_t object.
77 typedef struct private_allocator_s private_allocator_t
;
79 struct private_allocator_s
82 * Public part of an allocator_t object.
87 * Global list of allocations
89 * Thread-save through mutex
91 memory_hdr_t
*allocations
;
94 * Mutex used to make sure, all functions are thread-save
96 pthread_mutex_t mutex
;
99 * Allocates memory with LEAK_DETECTION and
100 * returns an empty data area filled with zeros.
102 * @param this private_allocator_t object
103 * @param bytes number of bytes to allocate
104 * @param file filename from which the memory is allocated
105 * @param line line number in specific file
106 * @param use_mutex If FALSE no mutex is used for allocation
108 * - pointer to allocated memory area if successful
111 void * (*allocate_special
) (private_allocator_t
*this,size_t bytes
, char * file
,int line
, bool use_mutex
);
115 * Implements private_allocator_t's function allocate_special.
116 * See #private_allocator_s.allocate_special for description.
118 static void *allocate_special(private_allocator_t
*this,size_t bytes
, char * file
,int line
, bool use_mutex
)
120 memory_hdr_t
*allocated_memory
= malloc(sizeof(memory_hdr_t
) + bytes
);
122 if (allocated_memory
== NULL
)
124 return allocated_memory
;
129 pthread_mutex_lock( &(this->mutex
));
132 allocated_memory
->info
.line
= line
;
133 allocated_memory
->info
.filename
= file
;
134 allocated_memory
->info
.size_of_memory
= bytes
;
135 allocated_memory
->info
.older
= this->allocations
;
136 if (this->allocations
!= NULL
)
138 this->allocations
->info
.newer
= allocated_memory
;
140 this->allocations
= allocated_memory
;
141 allocated_memory
->info
.newer
= NULL
;
143 /* fill memory with zero's */
144 memset(allocated_memory
+1, '\0', bytes
);
147 pthread_mutex_unlock(&(this->mutex
));
150 /* real memory starts after header */
151 return (allocated_memory
+1);
155 * Implements allocator_t's function allocate.
156 * See #allocator_s.allocate for description.
158 static void * allocate(allocator_t
*allocator
,size_t bytes
, char * file
,int line
)
160 private_allocator_t
*this = (private_allocator_t
*) allocator
;
161 return (allocate_special(this,bytes
, file
,line
,TRUE
));
165 * Implements allocator_t's free_pointer allocate.
166 * See #allocator_s.free_pointer for description.
168 static void free_pointer(allocator_t
*allocator
, void * pointer
)
170 private_allocator_t
*this = (private_allocator_t
*) allocator
;
171 memory_hdr_t
*allocated_memory
;
177 pthread_mutex_lock( &(this->mutex
));
178 allocated_memory
= ((memory_hdr_t
*)pointer
) - 1;
180 if (allocated_memory
->info
.older
!= NULL
)
182 assert(allocated_memory
->info
.older
->info
.newer
== allocated_memory
);
183 allocated_memory
->info
.older
->info
.newer
= allocated_memory
->info
.newer
;
185 if (allocated_memory
->info
.newer
== NULL
)
187 assert(allocated_memory
== this->allocations
);
188 this->allocations
= allocated_memory
->info
.older
;
192 assert(allocated_memory
->info
.newer
->info
.older
== allocated_memory
);
193 allocated_memory
->info
.newer
->info
.older
= allocated_memory
->info
.older
;
195 pthread_mutex_unlock(&(this->mutex
));
196 free(allocated_memory
);
200 * Implements allocator_t's reallocate allocate.
201 * See #allocator_s.reallocate for description.
203 static void * reallocate(allocator_t
*allocator
, void * old
, size_t bytes
, char * file
,int line
)
205 private_allocator_t
*this = (private_allocator_t
*) allocator
;
206 memory_hdr_t
*allocated_memory
;
213 pthread_mutex_lock( &(this->mutex
));
214 allocated_memory
= ((memory_hdr_t
*)old
) - 1;
216 void *new_space
= this->allocate_special(this,bytes
,file
,line
,FALSE
);
218 if (new_space
== NULL
)
220 pthread_mutex_unlock(&(this->mutex
));
221 this->public.free_pointer(&(this->public),old
);
225 memcpy(new_space
,old
,allocated_memory
->info
.size_of_memory
);
226 pthread_mutex_unlock(&(this->mutex
));
232 * Implements allocator_t's report_memory_leaks allocate.
233 * See #allocator_s.report_memory_leaks for description.
235 static void allocator_report_memory_leaks(allocator_t
*allocator
)
237 private_allocator_t
*this = (private_allocator_t
*) allocator
;
238 memory_hdr_t
*p
= this->allocations
;
239 memory_hdr_t
*pprev
= NULL
;
242 pthread_mutex_lock(&(this->mutex
));
246 assert(pprev
== p
->info
.newer
);
250 if (p
== NULL
|| pprev
->info
.filename
!= p
->info
.filename
)
253 fprintf(stderr
,"LEAK: \"%lu * File %s, Line %d\"\n", n
, pprev
->info
.filename
,pprev
->info
.line
);
255 fprintf(stderr
,"LEAK: \"%s, Line %d\"\n", pprev
->info
.filename
,pprev
->info
.line
);
259 pthread_mutex_unlock( &(this->mutex
));
263 * Only initiation of allocator object.
265 * All allocation macros use this object.
267 static private_allocator_t allocator
= {
268 public: {allocate
: allocate
,
269 free_pointer
: free_pointer
,
270 reallocate
: reallocate
,
271 report_memory_leaks
: allocator_report_memory_leaks
},
273 allocate_special
: allocate_special
,
274 mutex
: PTHREAD_MUTEX_INITIALIZER
279 allocator_t
*global_allocator
= &(allocator
.public);