11 #include <dispatch/dispatch.h>
13 #include <sys/errno.h>
31 fprintf(stderr,
"%s\n", message);
43 void *compositionState = NULL;
53 #ifdef VUOHEAP_TRACEALL
57 static bool VuoHeap_isComposition(
void)
59 static bool isComposition =
false;
60 static dispatch_once_t once = 0;
61 dispatch_once(&once, ^{
62 isComposition = dlsym(RTLD_DEFAULT,
"vuoCompositionStateKey");
96 for (
int i = 0; i < 10000; ++i)
109 __sync_synchronize();
123 int pageSize = getpagesize();
124 long heapPageMask = ~((long)pageSize-1);
125 long heapPage = (long)pointer & heapPageMask;
128 mlock((
void *)heapPage, pageSize);
129 munlock((
void *)heapPage, pageSize);
133 if (mincore((
void *)heapPage, pageSize, pageStatus) == 0)
134 return pageStatus[0] & MINCORE_INCORE;
149 char *pointerAsChar = (
char *)pointer;
150 for (
int i = 0; i < 16; ++i)
151 if (isprint(pointerAsChar[i]))
152 summary[i] = pointerAsChar[i];
158 strlcpy(summary,
"(not allocated)", 17);
170 const char *format =
"%s:%d :: %s() :: %s";
171 int size = snprintf(NULL, 0, format, e.file, e.line, e.function, e.variable);
172 char *description = (
char *)malloc(size+1);
173 snprintf(description, size+1, format, e.file, e.line, e.function, e.variable);
196 const double dumpInterval = 5.0;
197 dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, DISPATCH_TIMER_STRICT, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
198 dispatch_source_set_timer(timer, dispatch_walltime(NULL,0), NSEC_PER_SEC*dumpInterval, NSEC_PER_SEC*dumpInterval);
199 dispatch_source_set_event_handler(timer, ^{
200 fprintf(stderr,
"\n\n\n\n\nreferenceCounts:\n");
204 const void *heapPointer = i->first;
205 char pointerSummary[17];
208 fprintf(stderr,
"\t% 3d refs to %p \"%s\", registered at %s\n", i->second.referenceCount, heapPointer, pointerSummary, description);
213 dispatch_resume(timer);
229 ostringstream errorMessage;
231 <<
", VuoRelease was not called enough times for:" << endl;
234 const void *heapPointer = i->first;
235 char pointerSummary[17];
238 errorMessage <<
"\t" << setw(3) << i->second.referenceCount <<
" refs to " << heapPointer <<
" \"" << pointerSummary <<
"\", registered at " << description << endl;
268 bool isAlreadyReferenceCounted;
277 #ifdef VUOHEAP_TRACEALL
278 if (VuoHeap_isComposition())
283 fprintf(stderr,
"table=%p VuoRegister(%p) %s\n",
referenceCounts, heapPointer, pointerName);
288 map<const void *, VuoHeapEntry>::iterator i =
referenceCounts->find(heapPointer);
290 if (! isAlreadyReferenceCounted)
293 (*referenceCounts)[heapPointer] = (
VuoHeapEntry){updatedCount, deallocate, file, linenumber, func, pointerName};
296 updatedCount = i->second.referenceCount;
301 if (isAlreadyReferenceCounted)
303 ostringstream errorMessage;
306 <<
", VuoRegister was called more than once for " << heapPointer
307 <<
" " << description;
319 int VuoRegisterSingletonF(
const void *heapPointer,
const char *file,
unsigned int linenumber,
const char *func,
const char *pointerName)
324 bool isAlreadyReferenceCounted;
332 #ifdef VUOHEAP_TRACEALL
333 if (VuoHeap_isComposition())
338 fprintf(stderr,
"table=%p VuoRegisterSingleton(%p) %s\n",
referenceCounts, heapPointer, pointerName);
349 if (! isAlreadyReferenceCounted)
354 if (isAlreadyReferenceCounted)
356 ostringstream errorMessage;
359 <<
", VuoRegisterSingleton was called more than once for " << heapPointer
360 <<
" " << description;
365 return isAlreadyReferenceCounted ? 1 : 0;
376 extern "C" int VuoRetainF(
const void *heapPointer,
const char *file,
unsigned int linenumber,
const char *func)
393 int updatedCount = -1;
394 bool foundSingleton =
false;
401 map<const void *, VuoHeapEntry>::iterator i =
referenceCounts->find(heapPointer);
404 #ifdef VUOHEAP_TRACEALL
405 if (VuoHeap_isComposition())
416 updatedCount = ++(i->second.referenceCount);
424 if (updatedCount == -1 && !foundSingleton)
426 char pointerSummary[17];
428 ostringstream errorMessage;
430 <<
", VuoRetain was called for unregistered pointer " << heapPointer
431 <<
" \"" << pointerSummary <<
"\"";
446 extern "C" int VuoReleaseF(
const void *heapPointer,
const char *file,
unsigned int linenumber,
const char *func)
464 int updatedCount = -1;
465 bool foundSingleton =
false;
466 bool isRegisteredWithoutRetain =
false;
473 map<const void *, VuoHeapEntry>::iterator i =
referenceCounts->find(heapPointer);
476 #ifdef VUOHEAP_TRACEALL
477 if (VuoHeap_isComposition())
489 if (i->second.referenceCount == 0)
491 isRegisteredWithoutRetain =
true;
495 updatedCount = --(i->second.referenceCount);
497 if (updatedCount == 0)
499 deallocate = i->second.deallocateFunction;
510 if (updatedCount == 0)
513 #ifdef VUOHEAP_TRACEALL
514 if (VuoHeap_isComposition())
527 fprintf(stderr,
"table=%p VuoDeallocate(%p)\n",
referenceCounts, heapPointer);
532 deallocate((
void *)heapPointer);
534 else if (updatedCount == -1 && !foundSingleton)
536 char pointerSummary[17];
538 ostringstream errorMessage;
540 <<
", VuoRelease was called for "
541 << (isRegisteredWithoutRetain ?
"unretained" :
"unregistered")
542 <<
" pointer " << heapPointer
543 <<
" \"" << pointerSummary <<
"\"";
559 map<const void *, VuoHeapEntry>::iterator i =
referenceCounts->find(heapPointer);
563 return strdup(
"(pointer was not VuoRegister()ed)");