Logo Search packages:      
Sourcecode: pymol version File versions  Download package

OVHeap.c

#include"OVHeap.h"

#ifndef OV_JENARIX
#ifdef OVHeap_TRACKING

/* all of the code in this module is only used when OVHeap_TRACKING is
 * active otherwise, OVHeap is simply a Macro-wrapper around stdlib's
 * memory management routines */

#define OVHeap_SORT

#define OVHeap_ERROR_LOG stderr

static void HandleOutOfMemory(void) 
{
  fprintf(OVHeap_ERROR_LOG,"OVHeap-Error: *************************************************\n");
  fprintf(OVHeap_ERROR_LOG,"OVHeap-Error: *** EEK! This program just ran out of memory! ***\n"); 
  fprintf(OVHeap_ERROR_LOG,"OVHeap-Error: *************************************************\n");
  fflush(OVHeap_ERROR_LOG);
#ifdef OVHeap_ABORT_ON_ERROR
  OVHeap_Dump(false);
  abort();
#endif

}

static void HandleError(void) 
{
  fprintf(OVHeap_ERROR_LOG,"OVHeap-Error: *************************************************\n");
  fprintf(OVHeap_ERROR_LOG,"OVHeap-Error: *** EEK! Memory corruption may have occurred! ***\n");
  fprintf(OVHeap_ERROR_LOG,"OVHeap-Error: *************************************************\n");
  fflush(OVHeap_ERROR_LOG);

#ifdef OVHeap_ABORT_ON_ERROR
  OVHeap_Dump(false);
  abort();
#endif
}


typedef struct DebugRec {
  struct DebugRec *next;
  char file[32], note[64];
  int line;
  ov_size size;
  int type;
} DebugRec;

#define HASH(x) ((x>>11)&0x3FF)

struct _OVHeap {
  DebugRec *HashTable[1024];
  int Count;
  int MaxCount;
};


OVHeap *_OVHeap_New(void)
{
  OVHeap *I = ov_os_calloc(1,sizeof(OVHeap));
  return I;
}

void _OVHeap_Del(OVHeap *I)
{
#ifndef OV_JENARIX
#ifdef OVHeap_TRACKING
  OVHeap_Dump(I,0);
#endif
#endif
  ov_os_free((void*)I);
}

int OVHeap_Usage(OVHeap *I)
{
  int a;
  unsigned int tot  = 0;
  DebugRec *rec;
  for(a=0;a<1024;a++)
    {
      rec=I->HashTable[a];
      while(rec)
        {
          tot+=rec->size;
          rec=rec->next;
        }
    }
  return(tot);
}

typedef char OutputLine[1280];

typedef struct {
  void *p;
  char text[1280];
} DebugOutput;

static int OutputInOrder(DebugOutput *output,int line1,int line2)
{
  return(output[line1].p <= output[line2].p);
}

static void OVHeap_SortOutput(int n,DebugOutput *array,int *x)
{
  int l,a,r,t,i;

  if(n<1) return;
  else if(n==1) { x[0]=0; return; }
  x--;
  for(a=1;a<=n;a++) x[a]=a;
  l=(n>>1)+1;
  r=n;
  while(1) {
    if(l>1)
      t = x[--l];
    else {
      t = x[r];
      x[r] = x[1];
      if( --r == 1) {
        x[1] = t;
        break;
      }
    }
    i=l;
    a=l << 1;
    while (a <= r) {
      if (a < r && (!OutputInOrder(array,x[a+1]-1,x[a]-1))) a++;
      if (!OutputInOrder(array,x[a]-1,t-1)) {
        x[i] = x[a];
        a += (i=a);
      } else
        a = r + 1;
    }
    x[i] = t;
  }
  x++;
  for(a=0;a<n;a++) x[a]--;
}

void OVHeap_Dump(OVHeap *I,ov_uint32 flags)
{
  int a;
  int cnt=0;
  unsigned int tot  = 0;
  DebugRec *rec;
  char type[]="FV";
#ifdef OVHeap_SORT
  DebugOutput *output;
  int *index;
#endif


#ifdef OVHeap_SORT
  for(a=0;a<1024;a++)
    {
      rec=I->HashTable[a];
      while(rec)
        {
          rec=rec->next;
          cnt++;
        }
    }
  output = (DebugOutput*)malloc(cnt*sizeof(DebugOutput));
  index = (int*)malloc(cnt*sizeof(int));
  cnt = 0;
#endif
  fprintf(OVHeap_ERROR_LOG,"================================= HEAP =================================\n");
  fflush(OVHeap_ERROR_LOG);
  for(a=0;a<1024;a++)
    {
      rec=I->HashTable[a];
      while(rec)
        {
          {
            tot+=rec->size;
            
            if(flags&OVHeap_DUMP_NO_ADDRESSES) {
#ifdef OVHeap_SORT
              output[cnt].p=rec;
              sprintf(output[cnt].text,
#else
              fprintf(OVHeap_ERROR_LOG,
#endif
                      "OVHeap: (%7x) %c %s",(unsigned int)
                      rec->size,type[rec->type],rec->file);
                      
                      } else {
                        
#ifdef OVHeap_SORT
                        output[cnt].p=rec;
                        sprintf(output[cnt].text,
#else
                        fprintf(OVHeap_ERROR_LOG,
#endif
                                "OVHeap:%8x -%8x (%7x) %c %s:%-4d",
                                (unsigned int)rec+1,
                                (unsigned int)((char*)(rec+1)+rec->size),
                                (unsigned int)
                                rec->size,type[rec->type],rec->file,rec->line);
                                }
                        
                        if(flags&OVHeap_DUMP_FILES_TOO) {
                          FILE *f;
                          int line = rec->line;
                          char buffer[1024],*c;
                          f=fopen(rec->file,"r");
                          while(line--)
                            fgets(buffer,2048,f);
                          c=buffer;
                          while(*c && *c<33)
                            c++;
#ifdef OVHeap_SORT
                          strcat(output[cnt].text,c);
#else
                          fprintf(OVHeap_ERROR_LOG,"%s",c);
#endif
                          fclose(f);
                        } else {
#ifdef OVHeap_SORT
                          strcat(output[cnt].text,"\n");
#else
                          fprintf(OVHeap_ERROR_LOG,"\n");
#endif
                        }
                      }
              rec=rec->next;
              cnt++;
            }
          }
#ifdef OVHeap_SORT
          OVHeap_SortOutput(cnt,output,index);
          for(a=0;a<cnt;a++)
            {
              fprintf(OVHeap_ERROR_LOG,"%s",output[index[a]].text);
            }
#endif
          
          fprintf(OVHeap_ERROR_LOG,"OVHeap: Summary: Blocks expected %d, found %d, peaked at %d.\n",
                  I->Count,cnt,I->MaxCount);
          fprintf(OVHeap_ERROR_LOG,"OVHeap: Summary: Total bytes allocated 0x%x (%0.3f MB).\n",tot,tot/(1024.0*1024));
          fprintf(OVHeap_ERROR_LOG,"========================================================================\n");
          fflush(OVHeap_ERROR_LOG);
}


static void OVHeap_HashAdd(OVHeap *I,DebugRec *rec)
{
  int hash;

  hash=(int)rec;
  hash=HASH(hash);
  rec->next=I->HashTable[hash];
  I->HashTable[hash]=rec;
}

static DebugRec *OVHeap_HashRemove(OVHeap *I,void *ptr)
{
  DebugRec *rec,*cur,*last;
  int hash;

  rec=(DebugRec*)ptr;
  rec--;
  hash=(int)rec;
  hash=HASH(hash);
  last=NULL;
  cur=I->HashTable[hash];
  while(cur)
    {
      if(cur==rec)
        {
          if(last)
            last->next=cur->next;
          else
            I->HashTable[hash]=cur->next;
          break;
        }
      last=cur;
      cur=cur->next;
    }  
  return(cur);
}

/* 
   Ustatus OVHeap_Wrap(Ustatus input,void **ptrptr,char *file, int line, int type)
   {
   DebugRec *rec,*cur;
   int hash;
  
   rec=(DebugRec*)(*ptrptr);
   rec--;
   hash=(int)rec;
   hash=HASH(hash);
   cur=I->HashTable[hash];
   while(cur)
   {
   if(cur==rec)
   {
   strcpy(rec->file,file);
   rec->line=line;
   rec->type=type;
   break;
   }
   cur=cur->next;
   }  
   return input;
   }
*/

void *_OVHeap_Malloc(OVHeap *I,ov_size size,const char *file,int line,int type)
{
  DebugRec *rec;

  rec=(DebugRec*)malloc(sizeof(DebugRec)+size);
  if(!rec) {
    if(size) {
      fprintf(OVHeap_ERROR_LOG,"OVHeap_Malloc-Error: malloc failed %lu.\n",(unsigned long)size);
      HandleOutOfMemory();
    }
  } else {
    strcpy(rec->file,file);
    rec->line=line;
    rec->size=size;
    rec->type=type;
    OVHeap_HashAdd(I,rec);
    rec++;
    I->Count++;
    if(I->MaxCount<I->Count) I->MaxCount=I->Count;
  }
  return((void *) rec);
}

void *_OVHeap_Calloc(OVHeap *I,ov_size num,ov_size size,
                     const char *file,int line,int type)
{
  DebugRec *rec;

  rec=(DebugRec*)calloc(1,sizeof(DebugRec)+size*num);
  if(!rec) {
    if(size) {
      fprintf(OVHeap_ERROR_LOG,"OVHeap_Malloc-Error: calloc failed %lu x %lu.\n",
              (unsigned long)size,(unsigned long)num);
      HandleOutOfMemory();
    }
  } else {
    strcpy(rec->file,file);
    rec->line=line;
    rec->size=size*num;
    rec->type=type;
    OVHeap_HashAdd(I,rec);
    rec++;
    I->Count++;
    if(I->MaxCount<I->Count) I->MaxCount=I->Count;
  }
  return((void *) rec);
}

void *_OVHeap_Realloc(OVHeap *I,void *ptr,ov_size size,
                      const char *file,int line,int type)
{
  DebugRec *rec,*new_rec;

  if(!ptr)
    return(_OVHeap_Malloc(I,size,file,line,type));
  else
    {
      rec=OVHeap_HashRemove(I,ptr);
      if(!rec) {
        fprintf(OVHeap_ERROR_LOG,
                   "OVHeap_Realloc-Error: realloc() corrupted heap or bad ptr! (%s:%i @%p)\n",
                                file,line,ptr);
#ifdef OVHeap_ABORT_ON_ERROR
          OVHeap_Dump(false);
          abort();
#endif
          HandleError();
      } else if(rec->type!=type) {
        fprintf(OVHeap_ERROR_LOG,"OVHeap_Realloc-Error: ptr %p of wrong type: %i!=%i (%s:%i)\n",
                ptr,rec->type,type,file,line);
#ifdef OVHeap_ABORT_ON_ERROR
        OVHeap_Dump(false);
        abort();
#endif
        HandleError();
      } else {
        new_rec=(DebugRec*)realloc(rec,size+sizeof(DebugRec));
        if(!new_rec) {
          fprintf(OVHeap_ERROR_LOG,"OVHeap_Realloc-Error: realloc() failed! (%s:%i)\n",
                  file,line);
          HandleOutOfMemory();
          OVHeap_HashAdd(I,rec); /* put it back */
          rec++;
        } else {
          rec=new_rec;
          OVHeap_HashAdd(I,rec);
          rec->size=size;
          rec++;
          return((void*)rec);
        }
      }
    }
  return(NULL);
}

void _OVHeap_Free(OVHeap *I,void *ptr,const char *file,int line,int type)
{
  DebugRec *rec;
  
  if(!ptr)
    {
      fprintf(OVHeap_ERROR_LOG,"OVHeap_Free-Error: free() called with NULL pointer (%s:%i)\n",
                         file,line);
#ifdef OVHeap_ABORT_ON_ERROR
      OVHeap_Dump(false);
      abort();
#endif
      HandleError();
    }
  rec=OVHeap_HashRemove(I,ptr);
  if(rec)
    {
      if(rec->type!=type)
              {
                   fprintf(OVHeap_ERROR_LOG,"OVHeap_Free-Error: ptr %p type mismatch: %i!=%i (%s:%i)\n",
                                ptr,rec->type,type,file,line);
#ifdef OVHeap_ABORT_ON_ERROR
          OVHeap_Dump(false);
          abort();
#endif
          HandleError();
              }
      free(rec);
    }
  else
    {
            
      fprintf(OVHeap_ERROR_LOG,
                         "OVHeap_Free-Error: free(): corrupted tree or bad ptr! (%s:%i @%p)\n",
                         file,line,ptr);
      HandleError();
    }
  I->Count--;
}


#endif
#endif

Generated by  Doxygen 1.6.0   Back to index