home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d181 / tracker.lha / Tracker / tracker.c < prev    next >
C/C++ Source or Header  |  1989-02-25  |  9KB  |  359 lines

  1. /* tracking memory allocator */
  2.  
  3. #include <exec/types.h>
  4. #include <exec/memory.h>
  5. #include <functions.h>
  6. #include <stdio.h>
  7.  
  8. /* comment out the following line if you want locks freed twice reported
  9.  * at the cost of getting spurious resource error messages when
  10.  * reusing the lock */
  11. /* #define FORGET_LOCKS_WHEN_UNLOCKED */
  12.  
  13. /* comment out the following line if you want memory freed twice reported
  14.  * at the cost of getting spurious resource error messages when
  15.  * freeing and reallocating memory */
  16. /* #define FORGET_MEMORY_WHEN_FREED */
  17.  
  18. /* make sure our invocations of the real routines on behalf of the user
  19.    don't cause us to recurse */
  20.  
  21. #ifdef AllocMem
  22. #undef AllocMem
  23. #undef FreeMem
  24. #undef AllocSignal
  25. #undef FreeSignal
  26. #undef Lock
  27. #undef UnLock
  28. #undef DupLock
  29. #endif
  30.  
  31. /* my flags */
  32. #define FREED_IT 1
  33.  
  34. struct TrackingAllocMemData
  35. {
  36.     UBYTE *where;            /* address returned by allocator */
  37.     long amount;            /* number of bytes allocated */
  38.     long alloc_flags;        /* flags passed to allocator */
  39.     char *file;                /* filename of caller from the macro */
  40.     int line;                /* line number of caller from macro */
  41.     long my_flags;            /* flags internal to tracker */
  42.     struct TrackingAllocMemData *next;    /* pointer to next entry */
  43. };
  44.  
  45. struct TrackingAllocMemData *TrackingAllocMemList = NULL;
  46. long MemAllocCount = 0, MemFreeCount = 0;
  47.  
  48. void *TrackingAllocMem(amount,flags,file,line)
  49. long amount;
  50. long flags;
  51. char *file;
  52. int line;
  53. {
  54.     register struct TrackingAllocMemData *rp;
  55.     UBYTE *users_memory;
  56.  
  57.     /* perform the actual alloc */
  58.     users_memory = AllocMem(amount,flags);
  59.  
  60.     /* if it succeeded, record tracking info */
  61.     if (users_memory)
  62.     {
  63.         MemAllocCount++;
  64.  
  65.         if ((rp = AllocMem((long)sizeof(struct TrackingAllocMemData),0L)) == NULL)
  66.             panic("tracker: can't alloc memory to record AllocMem data");
  67.  
  68.         /* add new alloc data entry to linked list */
  69.         rp->next = TrackingAllocMemList;
  70.         TrackingAllocMemList = rp;
  71.  
  72.         /* shove in save values */
  73.         rp->amount = amount;
  74.         rp->alloc_flags = flags;
  75.         rp->where = users_memory;
  76.         rp->file = file;
  77.         rp->line = line;
  78.         rp->my_flags = 0;
  79.     }
  80.     /* return pointer to the space allocated */
  81.     return(users_memory);
  82. }
  83.  
  84. void TrackingFreeMem(where,amount,file,line)
  85. UBYTE *where;
  86. long amount;
  87. char *file;
  88. int line;
  89. {
  90.     register struct TrackingAllocMemData *rp, *op, *freep;
  91.  
  92.     MemFreeCount++;
  93.     /* scan the memory tracking list for a match */
  94.     for (rp = TrackingAllocMemList, op = NULL; rp != NULL; op = rp, rp = rp->next)
  95.     {
  96.         /* if we matched the address */
  97.         if (rp->where == where)
  98.         {
  99.             /* if they got the amount wrong, tell them */
  100.             if (rp->amount != amount)
  101.             {
  102.                 fprintf(stderr,"freed addr %lx OK but length differs, talloc'ed %ld, freed %ld,\n\tallocated at file %s line %d, freed at file %s line %d\n",
  103.                 where,rp->amount,amount,rp->file,rp->line,file,line);
  104.             }
  105. #ifndef FORGET_MEMORY_WHEN_FREED
  106.             /* if it's already free, tell them they freed twice */
  107.             if (rp->my_flags & FREED_IT)
  108.             {
  109.                 fprintf(stderr,"freed memory twice at %lx, amount %ld,\n\tallocated in file %s at line %d, freed in file %s at line %d\n",where,amount,rp->file,rp->line,file,line);
  110.                 return;
  111.             }
  112.             else
  113.             {
  114.                 /* mark this entry as free */
  115.                 rp->my_flags |= FREED_IT;
  116.             }
  117. #else
  118.             /* remove entry from linked list and free it */
  119.             if (op != NULL) op->next = rp->next;
  120.             else
  121.                 TrackingAllocMemList = rp->next;
  122.             freep = rp;
  123.             rp = rp->next;
  124.             FreeMem(freep,(long)sizeof(struct TrackingAllocMemData));
  125. #endif
  126.             FreeMem(where,amount);
  127.  
  128.             return;
  129.         }
  130.     }
  131.     fprintf(stderr,"Freed memory at %lx of amount %ld that wasn't allocated,\n\tfreed at file %s line %d\n",where,amount,file,line);
  132.     FreeMem(where,amount);
  133. }
  134.  
  135. void ReportUnfreedMemory()
  136. {
  137.     struct TrackingAllocMemData *rp = TrackingAllocMemList, *freep;
  138.  
  139.     while (rp != NULL)
  140.     {
  141.         if (!(rp->my_flags & FREED_IT))
  142.         {
  143.             fprintf(stderr,"FreeMem was never called for memory at %lx, amount %ld,\n\tthe alloc was performed at file %s line %d\n",rp->where,rp->amount,rp->file,rp->line);
  144.         }
  145.         freep = rp;
  146.         rp = rp->next;
  147.         FreeMem(freep,(long)sizeof(struct TrackingAllocMemData));
  148.     }
  149.     printf("Total tracked AllocMem calls %ld, FreeMem calls %ld\n",MemAllocCount,MemFreeCount);
  150. }
  151.  
  152.  
  153. /* track signals */
  154. /* tracking AllocSignal doesn't currently track where it was called from */
  155.  
  156. long TrackingSignalMask = 0;
  157. long SignalAllocCount = 0, SignalFreeCount = 0;
  158.  
  159. long TrackingAllocSignal(signal_num,file,line)
  160. long signal_num;
  161. char *file;
  162. int line;
  163. {
  164.     SignalAllocCount++;
  165.  
  166.     signal_num = AllocSignal(signal_num);
  167.  
  168.     if (signal_num != -1)
  169.         TrackingSignalMask |= (1 << signal_num);
  170.  
  171.     return(signal_num);
  172. }
  173.  
  174. void TrackingFreeSignal(signal_num,file,line)
  175. long signal_num;
  176. char *file;
  177. int line;
  178. {
  179.     SignalFreeCount++;
  180.  
  181.     if (!(TrackingSignalMask & (1 << signal_num)))
  182.     {
  183.         fprintf("freed a signal (%ld) that was never allocated, at file %s line %d\n",
  184.             signal_num,file,line);
  185.         TrackingSignalMask &= ~(1 << signal_num);
  186.     }
  187. }
  188.  
  189. void ReportUnfreedSignals()
  190. {
  191.     if (TrackingSignalMask)
  192.         fprintf("failed to free signals indicated by this mask: %8lx\n",
  193.             TrackingSignalMask);
  194.     printf("Total tracked AllocSignal calls %ld, FreeSignal calls %ld\n",SignalAllocCount,SignalFreeCount);
  195. }
  196.  
  197. /* tracking lock and unlock */
  198.  
  199. struct TrackingLockData
  200. {
  201.     struct FileLock *lock;    /* lock returned by Lock */
  202.     char *name;                /* name of file that was locked */
  203.     long accessMode;        /* access mode of the file that was locked */
  204.     char *file;                /* ptr to file name of line of caller */
  205.     int line;                /* ptr to line number text of locker */
  206.     long my_flags;            /* flags internal to tracker */
  207.     struct TrackingLockData *next;    /* pointer to next entry */
  208. };
  209.  
  210. /* flags */
  211. #define CREATED_BY_DUPLOCK 1
  212.  
  213. struct TrackingLockData *TrackingLockList = NULL;
  214. long TrackerLockCount = 0, TrackerUnLockCount = 0;
  215.  
  216. struct FileLock *TrackingLock(name, accessMode, file, line)
  217. char *name;
  218. long accessMode;
  219. char *file;
  220. int line;
  221. {
  222.     register struct TrackingLockData *lp;
  223.     struct FileLock *users_lock;
  224.  
  225.     users_lock = Lock(name, (long)accessMode);
  226.  
  227.     if (users_lock)
  228.     {
  229.         TrackerLockCount++;
  230.  
  231.         if ((lp = AllocMem((long)sizeof(struct TrackingLockData),0L)) == NULL)
  232.             panic("tracker: can't alloc memory to record lock data");
  233.  
  234.         /* add new alloc data entry to linked list */
  235.         lp->next = TrackingLockList;
  236.         TrackingLockList = lp;
  237.  
  238.         /* shove in save values */
  239.         lp->accessMode = accessMode;
  240.         lp->file = file;
  241.         lp->line = line;
  242.         lp->my_flags = 0;
  243.         lp->lock = users_lock;
  244.  
  245.         /* alloc space for filename and save */
  246.         if ((lp->name = AllocMem((long)(strlen(name)+1),0L)) == NULL)
  247.             panic("tracker: can't alloc memory to record lock filename");
  248.         strcpy(lp->name,name);
  249.     }
  250.     return(users_lock);
  251. }
  252.  
  253. struct FileLock *TrackingDupLock(lock, file, line)
  254. struct FileLock *lock;
  255. char *file;
  256. int line;
  257. {
  258.     register struct TrackingLockData *lp;
  259.     struct FileLock *users_lock;
  260.  
  261.     users_lock = DupLock(lock);
  262.  
  263.     if (users_lock)
  264.     {
  265.         TrackerLockCount++;
  266.  
  267.         if ((lp = AllocMem((long)sizeof(struct TrackingLockData),0L)) == NULL)
  268.             panic("tracker: can't alloc memory to record lock data");
  269.  
  270.         /* add new alloc data entry to linked list */
  271.         lp->next = TrackingLockList;
  272.         TrackingLockList = lp;
  273.  
  274.         lp->file = file;
  275.         lp->line = line;
  276.         lp->name = NULL;
  277.         lp->lock = users_lock;
  278.         lp->my_flags = CREATED_BY_DUPLOCK;            
  279.     }
  280.     return(users_lock);
  281. }
  282.  
  283. void TrackingUnLock(lock,file,line)
  284. struct FileLock *lock;
  285. char *file;
  286. int line;
  287. {
  288.     register struct TrackingLockData *lp, *op, *freep;
  289.  
  290.     TrackerUnLockCount++;
  291.  
  292.     /* scan the lock tracking list for a match */
  293.     for (lp = TrackingLockList, op = NULL; lp != NULL; op = lp, lp = lp->next)
  294.     {
  295.         /* if we matched the lock */
  296.         if (lp->lock == lock)
  297.         {
  298. #ifndef FORGET_LOCKS_WHEN_UNLOCKED
  299.             /* if it's already free, tell them they freed twice */
  300.             if (lp->my_flags & FREED_IT)
  301.             {
  302.                 fprintf(stderr,"freed lock twice, lock %lx, filename %s\n\tlocked at file %s line %d, freed at file %s line %d\n",lock,lp->name,lp->file,lp->line,file,line);
  303.                 return;
  304.             }
  305.             else
  306.             {
  307.                 /* mark this entry as free */
  308.                 lp->my_flags |= FREED_IT;
  309.             }
  310. #else
  311.             if (op != NULL) op->next = lp->next;
  312.             else TrackingLockList = lp->next;
  313.             freep = lp;
  314.             lp = lp->next;
  315.             if (lp->name != NULL)
  316.                 FreeMem(lp->name,(long)(strlen(lp->name)+1));
  317.             FreeMem(freep,(long)(sizeof(struct TrackingLockData)));
  318. #endif
  319.             UnLock(lock);
  320.             return;
  321.         }
  322.     }
  323.     fprintf(stderr,"Freed lock %lx that hadn't been allocated at file %s line %d\n",lock,file,line);
  324. }
  325.  
  326. ReportUnfreedLocks()
  327. {
  328.     struct TrackingLockData *lp = TrackingLockList, *freep;
  329.  
  330.     while (lp != NULL)
  331.     {
  332.         if (!(lp->my_flags & FREED_IT))
  333.         {
  334.             if (lp->my_flags & CREATED_BY_DUPLOCK)
  335.             {
  336.                 fprintf(stderr,"UnLock was never called for lock %lx,\n\It was created by DupLock at file %s line %d\n",lp->lock,lp->file,lp->line);
  337.             }
  338.             else
  339.             {
  340.                 fprintf(stderr,"UnLock was never called for lock %lx,\n\It was created by a Lock of %s\nat file %s line %d\n",lp->lock,lp->name,lp->file,lp->line);
  341.             }
  342.         }
  343.         if (lp->name != NULL)
  344.             FreeMem(lp->name,(long)(strlen(lp->name)+1));
  345.         freep = lp;
  346.         lp = lp->next;
  347.         FreeMem(freep,(long)sizeof(struct TrackingLockData));
  348.     }
  349.     printf("Total tracked Lock and DupLock calls %ld, UnLock calls %ld\n",TrackerLockCount,TrackerUnLockCount);
  350. }
  351.  
  352. TrackerExitReport()
  353. {
  354.     ReportUnfreedMemory();
  355.     ReportUnfreedLocks();
  356.     ReportUnfreedSignals();
  357. }
  358.  
  359.