1 //-----------------------------------------------------------------------------
2 //
3 // ImageLib Sources
4 // Last modified: 08/17/2008
5 //
6 // Filename: src-IL/src/il_alloc.c
7 //
8 // Description: Memory allocation functions
9 //
10 //-----------------------------------------------------------------------------
11 
12 
13 #define __ALLOC_C
14 
15 // Memory leak detection
16 #ifdef _WIN32
17 	#ifdef _DEBUG
18 		#define _CRTDBG_MAP_ALLOC
19 		#include <stdlib.h>
20 		#ifndef _WIN32_WCE  // Does not have this header.
21 			#include <crtdbg.h>
22 		#endif
23 	#endif
24 #endif//_WIN32
25 
26 #include "il_internal.h"
27 #include <stdlib.h>
28 #include <math.h>
29 
30 #ifdef MM_MALLOC
31 #include <mm_malloc.h>
32 #endif
33 
34 static void ILAPIENTRY DefaultFreeFunc(const void * CONST_RESTRICT Ptr);
35 static void* ILAPIENTRY DefaultAllocFunc(const ILsizei Size);
36 
37 static mAlloc ialloc_ptr = DefaultAllocFunc;
38 static mFree  ifree_ptr = DefaultFreeFunc;
39 
40 /*** Vector Allocation/Deallocation Function ***/
41 #ifdef VECTORMEM
vec_malloc(const ILsizei size)42 void *vec_malloc(const ILsizei size)
43 {
44 	const ILsizei _size =  size % 16 > 0 ? size + 16 - (size % 16) : size; // align size value
45 
46 #ifdef MM_MALLOC
47 	return _mm_malloc(_size,16);
48 #else
49 #ifdef VALLOC
50 	return valloc( _size );
51 #else
52 #ifdef POSIX_MEMALIGN
53 	char *buffer;
54 	return posix_memalign((void**)&buffer, 16, _size) == 0 ? buffer : NULL;
55 #else
56 #ifdef MEMALIGN
57 	return memalign( 16, _size );
58 #else
59 	// Memalign hack from ffmpeg for MinGW
60 	void *ptr;
61 	int diff;
62 	ptr = malloc(_size+16+1);
63 	diff= ((-(int)ptr - 1)&15) + 1;
64 	ptr = (void*)(((char*)ptr)+diff);
65 	((char*)ptr)[-1]= diff;
66 	return ptr;
67 #endif //MEMALIGN
68 #endif //POSIX_MEMALIGN
69 #endif //VALLOC
70 #endif //MM_MALLOC
71 }
72 
ivec_align_buffer(void * buffer,const ILsizei size)73 void *ivec_align_buffer(void *buffer, const ILsizei size)
74 {
75 	if( (ILsizei)buffer % 16 != 0 ) {
76         void *aligned_buffer = vec_malloc( size );
77         memcpy( aligned_buffer, buffer, size );
78         ifree( buffer );
79         return aligned_buffer;
80     }
81     return buffer;
82 }
83 #endif
84 
85 
86 /*** Allocation/Deallocation Function ***/
ialloc(const ILsizei Size)87 void* ILAPIENTRY ialloc(const ILsizei Size)
88 {
89 	void *Ptr = ialloc_ptr(Size);
90 	if (Ptr == NULL)
91 		ilSetError(IL_OUT_OF_MEMORY);
92 	return Ptr;
93 }
94 
ifree(const void * CONST_RESTRICT Ptr)95 void ILAPIENTRY ifree(const void * CONST_RESTRICT Ptr)
96 {
97 	if (Ptr == NULL)
98 		return;
99 	ifree_ptr(Ptr);
100 	return;
101 }
102 
icalloc(const ILsizei Size,const ILsizei Num)103 void* ILAPIENTRY icalloc(const ILsizei Size, const ILsizei Num)
104 {
105     void *Ptr = ialloc(Size * Num);
106     if (Ptr == NULL)
107     	return Ptr;
108     imemclear(Ptr, Size * Num);
109     return Ptr;
110 }
111 
112 /*** Default Allocation/Deallocation Function ***/
DefaultAllocFunc(const ILsizei Size)113 static void* ILAPIENTRY DefaultAllocFunc(const ILsizei Size)
114 {
115 #ifdef VECTORMEM
116 	return (void*)vec_malloc(Size);
117 #else
118 	return malloc(Size);
119 #endif //VECTORMEM
120 }
121 
DefaultFreeFunc(const void * CONST_RESTRICT ptr)122 static void ILAPIENTRY DefaultFreeFunc(const void * CONST_RESTRICT ptr)
123 {
124 	if (ptr)
125 	{
126 #if defined(VECTORMEM) && defined(MM_MALLOC)
127 	    _mm_free((void*)ptr);
128 #else
129 #if defined(VECTORMEM) & !defined(POSIX_MEMALIGN) & !defined(VALLOC) & !defined(MEMALIGN) & !defined(MM_MALLOC)
130 	    free(((char*)Ptr) - ((char*)Ptr)[-1]);
131 #else
132 	    free((void*)ptr);
133 #endif //OTHERS...
134 #endif //MM_MALLOC
135 	}
136 }
137 
138 /*** Manipulate Allocation/Deallocation Function ***/
ilResetMemory()139 void ILAPIENTRY ilResetMemory()  // Deprecated
140 {
141 	ialloc_ptr = DefaultAllocFunc;
142 	ifree_ptr = DefaultFreeFunc;
143 }
144 
ilSetMemory(mAlloc AllocFunc,mFree FreeFunc)145 void ILAPIENTRY ilSetMemory(mAlloc AllocFunc, mFree FreeFunc)
146 {
147 	ialloc_ptr = AllocFunc == NULL ? DefaultAllocFunc : AllocFunc;
148 	ifree_ptr = FreeFunc == NULL ? DefaultFreeFunc : FreeFunc;
149 }
150 
151 
152 /*#if defined(_WIN32) && defined(_MEM_DEBUG)
153 #include <windows.h>
154 
155 int bAtexit = 0;
156 
157 
158 typedef struct ALLOC_INFO
159 {
160 	unsigned long	address;
161 	unsigned long	size;
162 	char			file[64];
163 	unsigned long	line;
164 	struct ALLOC_INFO *Next;
165 } ALLOC_INFO;
166 ALLOC_INFO *AllocList;
167 
168 
169 void AddTrack(unsigned long addr, unsigned long size, const char *file, unsigned long line)
170 {
171 	ALLOC_INFO *Temp;
172 
173 	if (AllocList == NULL) {
174 		AllocList = (ALLOC_INFO*)malloc(sizeof(ALLOC_INFO));  // Just assume it succeeds.
175 		AllocList->address = addr;
176 		AllocList->size = size;
177 		AllocList->line = line;
178 		strncpy(AllocList->file, file, 63);
179 		AllocList->Next = NULL;
180 	}
181 	else {
182 		Temp = AllocList;
183 		AllocList = (ALLOC_INFO*)malloc(sizeof(ALLOC_INFO));  // Just assume it succeeds.
184 		AllocList->address = addr;
185 		AllocList->size = size;
186 		AllocList->line = line;
187 		strncpy(AllocList->file, file, 63);
188 		AllocList->Next = Temp;
189 	}
190 
191 	return;
192 }
193 
194 
195 void RemoveTrack(unsigned long addr)
196 {
197 	ALLOC_INFO *Temp, *Prev;
198 
199 	Temp = AllocList;
200 	Prev = NULL;
201 
202 	if (Temp == NULL)
203 		return;
204 
205 	while (Temp != NULL) {
206 		if (Temp->address == addr) {
207 			if (Prev == NULL) {
208 				AllocList = Temp->Next;
209 				free(Temp);
210 			}
211 			else {
212 				Prev->Next = Temp->Next;
213 				free(Temp);
214 			}
215 			break;
216 		}
217 		Prev = Temp;
218 		Temp = Temp->Next;
219 	}
220 
221 	return;
222 }
223 
224 
225 void DumpUnfreed(void)
226 {
227 	unsigned long TotalSize = 0;
228 	char buf[1024];
229 	ALLOC_INFO *i = AllocList;
230 
231 	OutputDebugString("DevIL Unfreed Information:\n");
232 	while (i != NULL) {
233 		sprintf(buf, "%s(%d) : %d bytes unfreed at %d\n", i->file, i->line, i->size, i->address);
234 		OutputDebugString(buf);
235 		TotalSize += i->size;
236 
237 		AllocList = i->Next;
238 		free(i);
239 		i = AllocList;
240 	}
241 
242 	sprintf(buf, "-----------------------------------------------------------\n");
243 	OutputDebugString(buf);
244 	sprintf(buf, "Total Unfreed: %d bytes\n\n\n", TotalSize);
245 	OutputDebugString(buf);
246 }
247 
248 void AddToAtexit()
249 {
250 	if (bAtexit)
251 		return;
252 	atexit(DumpUnfreed);
253 	bAtexit = 1;
254 }
255 
256 void *c_alloc(unsigned long size, unsigned long num, const char *file, unsigned long line)
257 {
258 	void *ptr;
259 	ptr = calloc(size, num);
260 	if (!ptr)
261 		return NULL;
262 	AddToAtexit();
263 	AddTrack((unsigned long)ptr, size * num, file, line);
264 	return ptr;
265 }
266 
267 
268 void *m_alloc(unsigned long size, const char *file, unsigned long line)
269 {
270 	void *ptr;
271 	ptr = malloc(size);
272 	if (!ptr)
273 		return NULL;
274 	AddToAtexit();
275 	AddTrack((unsigned long)ptr, size, file, line);
276 	return ptr;
277 }
278 
279 
280 void f_ree(void *ptr)
281 {
282 	RemoveTrack((unsigned long)ptr);
283 	free(ptr);
284 	return;
285 }
286 
287 #endif//defined(_WIN32) && defined(_MEM_DEBUG)*/
288