home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 348.lha / chatterbox_v1.0 / sources / tracker.c < prev    next >
C/C++ Source or Header  |  1990-02-14  |  9KB  |  362 lines

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