/* DFT++ is a density functional package developed by the research group of Professor Tomas Arias Copyright 1996-2003 Sohrab Ismail-Beigi This file is part of DFT++. DFT++ is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. DFT++ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with DFT++; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Please see the file CREDITS for a list of authors. For academic users, we request that publications using results obtained with this software reference "New algebraic formulation of density functional calculation," by Sohrab Ismail-Beigi and T.A. Arias, Computer Physics Communications 128:1-2, 1-45 (June 2000). and, if using the wavelet basis, further reference "Multiresolution analysis of electronic structure: semicardinal and wavelet bases," T.A. Arias, Reviews of Modern Physics 71:1, 267-311 (January 1999). and "Robust ab initio calculation of condensed matter: transparent convergence through semicardinal multiresolution analysis,'' I.P. Daykov, T.A. Arias, and Torkel D. Engeness, Physical Review Letters, 90:21, 216402 (May 2003). For your convenience, preprints of the above articles may be obtained from http://arXiv.org/abs/cond-mat/9909130, 9805262, and 0204411, respectively. */ /* * Sohrab Ismail-Beigi Jan. 6, 1997 * * mem.c: Routines that dynamically allocate/free memory. * * void *mymalloc() is just a fancy calloc() that exits with * provided error messages if it can't allocate memory. * */ /* $Id: mem.cpp,v 1.12.2.3 2003/05/29 18:54:29 ivan Exp $ */ #include "header.h" #ifndef DFT_TRACE_MEM /* Allocate size bytes of memory; if it fails, die with some * information. If it suceeds, it zeroes out the memory before * returning the pointer. */ void * mymalloc(int size,const char *what,const char *where) { #ifdef DFT_PROFILING timerOn(8); // Turn on memory allocation timer. #endif // DFT_PROFILING void *p; if (size <= 0) { #ifdef DFT_PROFILING timerOff(8); // Turn off memory allocation timer. #endif // DFT_PROFILING return ((void *) 0); } #ifdef DFT_MEMALIGN // not all platforms have memalign in standard lib p = (void *)memalign(32,size); #else p = (void *)malloc(size); #endif if (p == (void *)0) die("Can't malloc %d for %s in %s.\n", size, what, where); else { int i; char *c = (char *)p; for (i=0; i < size; i++) c[i] = 0; #ifdef DFT_PROFILING timerOff(8); // Turn off memory allocation timer. #endif // DFT_PROFILING } return p; } /* Reallocate size bytes of memory; if it fails, die with some * information. If it suceeds, returns the new block pointer */ void * myrealloc(void *pold,int size,const char *what,const char *where) { #ifdef DFT_PROFILING timerOn(8); // Turn on memory allocation timer. #endif // DFT_PROFILING void *p; if (size <= 0) { #ifdef DFT_PROFILING timerOff(8); // Turn off memory allocation timer. #endif // DFT_PROFILING return ((void *) 0); } p = (void *)realloc(pold,size); if (p == 0) die("Can't realloc %d for %s in %s.\n", size, what, where); #ifdef DFT_PROFILING timerOff(8); // Turn off memory allocation timer. #endif // DFT_PROFILING return p; } void myfree(void* ptr) { if (ptr != NULL) free(ptr); } #else // DFT_TRACE_MEM : trace memory usage /************************************************* * * * For debugging purpose, use the following * * memory access routines to trace usage. * * * *************************************************/ int num_blocks = 0; int max_block = 0; long int accum_alloc = 0L; long int current_alloc = 0L; long int max_alloc = 0L; #define PREFIX 16 #define POSTFIX 16 #define MAGIC1 1234 #define MAGIC2 -9876 #define MAGIC3 "little-dogs" #define POSTCHECK 10 void mem_trace_report() { int i; dft_log("\n>Memory Trace Report:\n"); dft_log(">Memory\ttotal allocations\t%d\n",num_blocks); dft_log(">Memory\tmaximum block allocated\t%d\n",max_block); dft_log(">Memory\taccumulative memory\t%ld\n", accum_alloc); dft_log(">Memory\tcurrent memory\t%ld\n", current_alloc); dft_log(">Memory\tmaximum memory\t%ld\n", max_alloc); dft_log("\n\n"); dft_log_flush(); } void * mymalloc(int size,const char *what,const char *where) { #ifdef DFT_PROFILING timerOn(8); // Turn on memory allocation timer. #endif // DFT_PROFILING void *p; int * pint; int dieflag = 0; if (size <= 0) { #ifdef DFT_PROFILING timerOff(8); // Turn off memory allocation timer. #endif // DFT_PROFILING return((void*) 0); } // Allocating the memory #ifdef DFT_MEMALIGN // not all platforms have memalign in standard lib p = (void *) memalign(32, size + PREFIX*sizeof(int) + POSTFIX*sizeof(char) ); #else p = (void *) malloc(size + PREFIX*sizeof(int) + POSTFIX*sizeof(char) ); #endif if (p == (void*) 0) { mem_trace_report(); die("Can't malloc %d for %s in %s.\n", size, what, where); } // Post-allocation work. // The prefix memory is // [MAGIC1, SIZE, NUM_BLOCKS, SIZE, MAGIC2, ... content ... ] // pint = (int*) p; pint[0] = MAGIC1; pint[1] = size; pint[2] = num_blocks; pint[3] = size; pint[4] = MAGIC2; pint += PREFIX; // PREFIX >= 5 p = (void*) pint; num_blocks++; accum_alloc += size; current_alloc += size; if (current_alloc > max_alloc) max_alloc = current_alloc; if (size > max_block) max_block = size; { int i; char *c = (char *)p; for (i=0; i < size; i++) c[i] = 0; } // The postfix memory is // [ ... content ... , MAGIC3 ] // strncpy((char*)p+size, MAGIC3, POSTCHECK); #ifdef DFT_PROFILING timerOff(8); // Turn off memory allocation timer. #endif // DFT_PROFILING return p; } void myfree(void *ptr) { int size, * pint; char errstr[100]; int error_flag = 0; // check for prefix MAGICs. pint = (int*) ptr; pint -= PREFIX; if (pint[0] != MAGIC1) { // MAGIC string 1 corrupted. dft_log(DFT_SILENCE, "MAGIC 1 corrupted in memory trace, block %d, %d != %d\n", pint[2], pint[0], MAGIC1); dft_log_flush(); error_flag = 1; } if (pint[4] != MAGIC2) { // MAGIC string 2 corrupted. dft_log(DFT_SILENCE, "MAGIC 2 corrupted in memory trace, block %d, %d != %d\n", pint[2], pint[4], MAGIC2); dft_log_flush(); error_flag = 1; } size = pint[1]; if (pint[1] != pint[3]) { // size of blocks mismatch. dft_log(DFT_SILENCE, "Size of blocks mismatch, block %d, %d != %d\n", pint[2], pint[1], pint[3]); dft_log_flush(); error_flag = 1; } // check for postfix MAGICs. if (error_flag == 0) { char * pchar = (char*) ptr + size; if (strncmp(pchar,MAGIC3,POSTCHECK)!=0) { // MAGIC string 3 corrupted. dft_log(DFT_SILENCE, "MAGIC 3 corrupted in memory trace\n"); dft_log_flush(); error_flag = 1; } } if (error_flag == 0) { size = pint[1]; current_alloc += -size; free(pint); } else { mem_trace_report(); dft_log_flush(); die("Die in mem trace."); } } #endif // DFT_TRACE_MEM