00001 /* 00002 * *************************************************************************** 00003 * MALOC = < Minimal Abstraction Layer for Object-oriented C > 00004 * Copyright (C) 1994--2008 Michael Holst 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 * 00020 * rcsid="$Id: vmem.c,v 1.15 2008/03/12 05:13:59 fetk Exp $" 00021 * *************************************************************************** 00022 */ 00023 00024 /* 00025 * *************************************************************************** 00026 * File: vmem.c 00027 * 00028 * Purpose: Class Vmem: methods. 00029 * 00030 * Author: Michael Holst 00031 * *************************************************************************** 00032 */ 00033 00034 #include "vmem_p.h" 00035 00036 VEMBED(rcsid="$Id: vmem.c,v 1.15 2008/03/12 05:13:59 fetk Exp $") 00037 00038 /* total and misc (default) malloc/free tracking */ 00039 VPRIVATE Vmem vmemTotal, vmemMisc; 00040 VPRIVATE size_t vmemInit=0; 00041 00042 /* 00043 * *************************************************************************** 00044 * Class Vmem: Inlineable methods 00045 * *************************************************************************** 00046 */ 00047 #if !defined(VINLINE_MALOC) 00048 00049 #endif /* if !defined(VINLINE_MALOC) */ 00050 /* 00051 * *************************************************************************** 00052 * Class Vmem: Non-inlineable methods 00053 * *************************************************************************** 00054 */ 00055 00056 /* 00057 * *************************************************************************** 00058 * Routine: Vmem_init 00059 * 00060 * Purpose: Initialize the total log and the catch-all misc log. 00061 * 00062 * Author: Michael Holst 00063 * *************************************************************************** 00064 */ 00065 VPRIVATE void Vmem_init(void) 00066 { 00067 if (!vmemInit) { 00068 00069 strncpy(vmemTotal.name, "TOTAL", VMAX_ARGLEN); 00070 vmemTotal.mallocBytes = 0; 00071 vmemTotal.freeBytes = 0; 00072 vmemTotal.highWater = 0; 00073 vmemTotal.mallocAreas = 0; 00074 00075 strncpy(vmemMisc.name, "MISC", VMAX_ARGLEN); 00076 vmemMisc.mallocBytes = 0; 00077 vmemMisc.freeBytes = 0; 00078 vmemMisc.highWater = 0; 00079 vmemMisc.mallocAreas = 0; 00080 00081 vmemInit = 1; 00082 } 00083 } 00084 00085 /* 00086 * *************************************************************************** 00087 * Routine: Vmem_bytesTotal 00088 * 00089 * Purpose: Return total size of ALL currently ACTIVE malloc areas that 00090 * went through Vmem_malloc. This is the current memory footprint. 00091 * 00092 * Author: Michael Holst 00093 * *************************************************************************** 00094 */ 00095 VPUBLIC size_t Vmem_bytesTotal(void) 00096 { 00097 Vmem_init(); 00098 return (vmemTotal.mallocBytes - vmemTotal.freeBytes); 00099 } 00100 00101 /* 00102 * *************************************************************************** 00103 * Routine: Vmem_mallocBytesTotal 00104 * 00105 * Purpose: Return total size of ALL malloc areas that went through 00106 * Vmem_malloc (even if they have been subsequently freed). 00107 * 00108 * Author: Michael Holst 00109 * *************************************************************************** 00110 */ 00111 VPUBLIC size_t Vmem_mallocBytesTotal(void) 00112 { 00113 Vmem_init(); 00114 return vmemTotal.mallocBytes; 00115 } 00116 00117 /* 00118 * *************************************************************************** 00119 * Routine: Vmem_freeBytesTotal 00120 * 00121 * Purpose: Return total size of ALL freed malloc areas that 00122 * went through Vmem_free. 00123 * 00124 * Author: Michael Holst 00125 * *************************************************************************** 00126 */ 00127 VPUBLIC size_t Vmem_freeBytesTotal(void) 00128 { 00129 Vmem_init(); 00130 return vmemTotal.freeBytes; 00131 } 00132 00133 /* 00134 * *************************************************************************** 00135 * Routine: Vmem_highWaterTotal 00136 * 00137 * Purpose: Return the high-water malloc bytemark hit by ALL active 00138 * malloc areas; this is the largest active malloc total hit at 00139 * one time by areas obtained through Vmem_malloc. 00140 * 00141 * Author: Michael Holst 00142 * *************************************************************************** 00143 */ 00144 VPUBLIC size_t Vmem_highWaterTotal(void) 00145 { 00146 Vmem_init(); 00147 return vmemTotal.highWater; 00148 } 00149 00150 /* 00151 * *************************************************************************** 00152 * Routine: Vmem_mallocAreasTotal 00153 * 00154 * Purpose: Return the total number of ALL individual active malloc areas. 00155 * 00156 * Author: Michael Holst 00157 * *************************************************************************** 00158 */ 00159 VPUBLIC size_t Vmem_mallocAreasTotal(void) 00160 { 00161 Vmem_init(); 00162 return vmemTotal.mallocAreas; 00163 } 00164 00165 /* 00166 * *************************************************************************** 00167 * Routine: Vmem_printTotal 00168 * 00169 * Purpose: Print current memory statistics for all malloc areas that have 00170 * gone through Vmem_malloc and Vmem_free. 00171 * 00172 * Author: Michael Holst 00173 * *************************************************************************** 00174 */ 00175 VPUBLIC void Vmem_printTotal(void) 00176 { 00177 Vmem_init(); 00178 fprintf(stderr,"%12ld %12ld %12ld %12ld %12ld %% %s\n", 00179 (vmemTotal.mallocBytes-vmemTotal.freeBytes), 00180 vmemTotal.mallocAreas, vmemTotal.mallocBytes, 00181 vmemTotal.freeBytes, vmemTotal.highWater, 00182 vmemTotal.name); 00183 } 00184 00185 /* 00186 * *************************************************************************** 00187 * Routine: Vmem_ctor 00188 * 00189 * Purpose: Construct the dynamic memory allocation logging object. 00190 * 00191 * Author: Michael Holst 00192 * *************************************************************************** 00193 */ 00194 VPUBLIC Vmem *Vmem_ctor(char *name) 00195 { 00196 Vmem *thee; 00197 00198 thee = Vmem_malloc( VNULL, 1, sizeof(Vmem) ); 00199 VASSERT( thee != VNULL ); 00200 00201 strncpy( thee->name, name, VMAX_ARGLEN ); 00202 thee->mallocBytes = 0; 00203 thee->freeBytes = 0; 00204 thee->highWater = 0; 00205 thee->mallocAreas = 0; 00206 00207 return thee; 00208 } 00209 00210 /* 00211 * *************************************************************************** 00212 * Routine: Vmem_dtor 00213 * 00214 * Purpose: Destruct the dynamic memory allocation logging object. 00215 * 00216 * Author: Michael Holst 00217 * *************************************************************************** 00218 */ 00219 VPUBLIC void Vmem_dtor(Vmem **thee) 00220 { 00221 Vmem_free( VNULL, 1, sizeof(Vmem), (void**)thee ); 00222 } 00223 00224 /* 00225 * *************************************************************************** 00226 * Routine: Vmem_malloc 00227 * 00228 * Purpose: A logged version of malloc. 00229 * 00230 * Author: Michael Holst 00231 * *************************************************************************** 00232 */ 00233 VPUBLIC void *Vmem_malloc(Vmem *thee, size_t num, size_t size) 00234 { 00235 size_t btmp; 00236 void *ram = VNULL; 00237 00238 Vmem_init(); 00239 00240 /* VWARN( (num > 0) && (size > 0) ); */ 00241 VASSERT( (num > 0) && (size > 0) ); 00242 if ( (num > 0) && (size > 0) ) { 00243 00244 ram = (void*)calloc((size_t)num, (size_t)size); 00245 if (ram == VNULL) { 00246 fprintf(stderr, "Unable to allocate memory!\n"); 00247 fprintf(stderr, "(This often means you don't have enough memory available for this calculation.)\n"); 00248 printf("FATAL ERROR: Unable to allocate enough memory for problem size.\n"); 00249 printf("FATAL ERROR: You requested %u bytes of RAM.\n",(size_t)num * (size_t)size); 00250 printf("FATAL ERROR: Check that your system has that much memory.\n"); 00251 } 00252 VASSERT( ram != VNULL ); 00253 00254 vmemTotal.mallocBytes += (num * size); 00255 btmp = (vmemTotal.mallocBytes - vmemTotal.freeBytes); 00256 if ( vmemTotal.highWater < btmp ) vmemTotal.highWater = btmp; 00257 vmemTotal.mallocAreas++; 00258 00259 if (thee != VNULL) { 00260 thee->mallocBytes += (num * size); 00261 btmp = (thee->mallocBytes - thee->freeBytes); 00262 if ( thee->highWater < btmp ) thee->highWater = btmp; 00263 thee->mallocAreas++; 00264 } else { 00265 vmemMisc.mallocBytes += (num * size); 00266 btmp = (vmemMisc.mallocBytes - vmemMisc.freeBytes); 00267 if ( vmemMisc.highWater < btmp ) vmemMisc.highWater = btmp; 00268 vmemMisc.mallocAreas++; 00269 } 00270 00271 } 00272 00273 return ram; 00274 } 00275 00276 /* 00277 * *************************************************************************** 00278 * Routine: Vmem_free 00279 * 00280 * Purpose: A logged version of free. 00281 * 00282 * Author: Michael Holst 00283 * *************************************************************************** 00284 */ 00285 VPUBLIC void Vmem_free(Vmem *thee, size_t num, size_t size, void **ram) 00286 { 00287 Vmem_init(); 00288 00289 /* VWARN( (*ram) != VNULL ); */ 00290 VASSERT( (*ram) != VNULL ); 00291 if ((*ram) != VNULL) { 00292 00293 free(*ram); 00294 (*ram) = VNULL; 00295 00296 vmemTotal.freeBytes += (num * size); 00297 vmemTotal.mallocAreas--; 00298 00299 if (thee != VNULL) { 00300 thee->freeBytes += (num * size); 00301 thee->mallocAreas--; 00302 } else { 00303 vmemMisc.freeBytes += (num * size); 00304 vmemMisc.mallocAreas--; 00305 } 00306 } 00307 } 00308 00309 /* 00310 * *************************************************************************** 00311 * Routine: Vmem_realloc 00312 * 00313 * Purpose: A logged version of realloc (using this is usually a bad idea). 00314 * 00315 * Author: Michael Holst 00316 * *************************************************************************** 00317 */ 00318 VPUBLIC void *Vmem_realloc(Vmem *thee, size_t num, size_t size, void **ram, 00319 size_t newNum) 00320 { 00321 void *tee = Vmem_malloc(thee, newNum, size); 00322 memcpy(tee, (*ram), size*VMIN2(num,newNum)); 00323 Vmem_free(thee, num, size, ram); 00324 return tee; 00325 } 00326 00327 /* 00328 * *************************************************************************** 00329 * Routine: Vmem_bytes 00330 * 00331 * Purpose: Return total of ACTIVE malloc areas used by the Vmem object. 00332 * (If Vmem is VNULL, return the misc catch-all malloc total). 00333 * 00334 * Author: Michael Holst 00335 * *************************************************************************** 00336 */ 00337 VPUBLIC size_t Vmem_bytes(Vmem *thee) 00338 { 00339 Vmem_init(); 00340 00341 if (thee != VNULL) { 00342 return (thee->mallocBytes - thee->freeBytes); 00343 } else { 00344 return (vmemMisc.mallocBytes - vmemMisc.freeBytes); 00345 } 00346 } 00347 00348 /* 00349 * *************************************************************************** 00350 * Routine: Vmem_mallocBytes 00351 * 00352 * Purpose: Return total of all mallocs performed by the Vmem object. 00353 * (If Vmem is VNULL, return the misc catch-all malloc total). 00354 * 00355 * Author: Michael Holst 00356 * *************************************************************************** 00357 */ 00358 VPUBLIC size_t Vmem_mallocBytes(Vmem *thee) 00359 { 00360 Vmem_init(); 00361 00362 if (thee != VNULL) { 00363 return thee->mallocBytes; 00364 } else { 00365 return vmemMisc.mallocBytes; 00366 } 00367 } 00368 00369 /* 00370 * *************************************************************************** 00371 * Routine: Vmem_freeBytes 00372 * 00373 * Purpose: Return total of the frees performed by the Vmem object. 00374 * (If Vmem is VNULL, return misc catch-all free total). 00375 * 00376 * Author: Michael Holst 00377 * *************************************************************************** 00378 */ 00379 VPUBLIC size_t Vmem_freeBytes(Vmem *thee) 00380 { 00381 Vmem_init(); 00382 00383 if (thee != VNULL) { 00384 return thee->freeBytes; 00385 } else { 00386 return vmemMisc.freeBytes; 00387 } 00388 } 00389 00390 /* 00391 * *************************************************************************** 00392 * Routine: Vmem_highWater 00393 * 00394 * Purpose: Return the high-water malloc bytemark hit by the Vmem object. 00395 * (If Vmem is VNULL, return misc catch-all malloc highwater). 00396 * 00397 * Author: Michael Holst 00398 * *************************************************************************** 00399 */ 00400 VPUBLIC size_t Vmem_highWater(Vmem *thee) 00401 { 00402 Vmem_init(); 00403 00404 if (thee != VNULL) { 00405 return thee->highWater; 00406 } else { 00407 return vmemMisc.highWater; 00408 } 00409 } 00410 00411 /* 00412 * *************************************************************************** 00413 * Routine: Vmem_mallocAreas 00414 * 00415 * Purpose: Return the total number of individual active malloc areas. 00416 * (If Vmem is VNULL, return misc catch-all malloc areas). 00417 * 00418 * Author: Michael Holst 00419 * *************************************************************************** 00420 */ 00421 VPUBLIC size_t Vmem_mallocAreas(Vmem *thee) 00422 { 00423 Vmem_init(); 00424 00425 if (thee != VNULL) { 00426 return thee->mallocAreas; 00427 } else { 00428 return vmemMisc.mallocAreas; 00429 } 00430 } 00431 00432 /* 00433 * *************************************************************************** 00434 * Routine: Vmem_print 00435 * 00436 * Purpose: Print current memory statistics associated with this Vmem object. 00437 * (If Vmem is VNULL, print info for the catch-all ovject). 00438 * 00439 * Author: Michael Holst 00440 * *************************************************************************** 00441 */ 00442 VPUBLIC void Vmem_print(Vmem *thee) 00443 { 00444 Vmem_init(); 00445 00446 if (thee != VNULL) { 00447 fprintf(stderr,"%12ld %12ld %12ld %12ld %12ld %% %s\n", 00448 (thee->mallocBytes-thee->freeBytes), 00449 thee->mallocAreas, thee->mallocBytes, 00450 thee->freeBytes, thee->highWater, 00451 thee->name); 00452 } else { 00453 fprintf(stderr,"%12ld %12ld %12ld %12ld %12ld %% %s\n", 00454 (vmemMisc.mallocBytes-vmemMisc.freeBytes), 00455 vmemMisc.mallocAreas, vmemMisc.mallocBytes, 00456 vmemMisc.freeBytes, vmemMisc.highWater, 00457 vmemMisc.name); 00458 } 00459 } 00460