/** * @internal * * FUNCTION: pcsl_end_memory() * TYPE: private operation * OVERVIEW: Finalize the PCSL memory pool * INTERFACE: * parameters: count address to store memory leak count * size address to store totol bytes of memory leaked * returns: the number of memory leaks detected * */ static int pcsl_end_memory(int* count, int* size) { _PcslMemHdrPtr pcslMemoryHdr; char* pcslMemoryPtr; *count = 0; *size = 0; for (pcslMemoryPtr = PcslMemoryStart; pcslMemoryPtr < PcslMemoryEnd; pcslMemoryPtr += pcslMemoryHdr->size + sizeof(_PcslMemHdr)) { pcslMemoryHdr = (_PcslMemHdrPtr)pcslMemoryPtr; if (pcslMemoryHdr->magic != MAGIC) { REPORT1("ERROR: Corrupted start of memory header: 0x%p\n", pcslMemoryPtr); return -1; } #ifdef PCSL_DEBUG if (pcslMemoryHdr->guard != GUARD_WORD) { report("ERROR: Corrupted end of memory header: 0x%p\n", pcslMemoryPtr); return -1; } /* The memory block header is valid, now check the guard data */ if (verify_tail_guard_data(pcslMemoryHdr)) { report("ERROR: Memory overrun: 0x%p\n", pcslMemoryPtr); print_alloc("allocated", pcslMemoryHdr->filename, pcslMemoryHdr->lineno); } #endif if (pcslMemoryHdr->free != 1) { #ifdef PCSL_DEBUG report("WARNING: memory leak: size= %d address= 0x%p\n", pcslMemoryHdr->size, (void*)((char*)pcslMemoryHdr + sizeof(_PcslMemHdr))); print_alloc("allocated", pcslMemoryHdr->filename, pcslMemoryHdr->lineno); #endif pcsl_mem_free((void*)((char*)pcslMemoryHdr + sizeof(_PcslMemHdr))); *count += 1; *size += pcslMemoryHdr->size; } } return *count; }
void pcsl_mem_free_impl0(void *ptr, char *filename, int lineno) { _PcslMemHdrPtr pcslMemoryHdr; if (ptr == NULL) { report("WARNING: Attempt to free NULL pointer\n"); print_alloc("freed", filename, lineno); } else if (((char*)ptr > PcslMemoryEnd) || ((char*)ptr < PcslMemoryStart)) { report("ERROR: Attempt to free memory out of scope: 0x%p\n", ptr); print_alloc("freed", filename, lineno); } else { pcslMemoryHdr = (_PcslMemHdrPtr)((char*)ptr -sizeof(_PcslMemHdr)); if (pcslMemoryHdr->magic != MAGIC) { report("ERROR: Attempt to free corrupted memory: 0x%p\n", ptr); print_alloc("freed", filename, lineno); } else if (pcslMemoryHdr->free != 0) { report("ERROR: Attempt to free memory twice: 0x%p\n", ptr); print_alloc("freed", filename, lineno); } else { PcslMemoryAllocated -= pcslMemoryHdr->size; /* The memory block header is valid, now check the guard data */ if (pcslMemoryHdr->guard != GUARD_WORD) { report("ERROR: Possible memory underrun: 0x%p\n", ptr); print_alloc("allocated", pcslMemoryHdr->filename, pcslMemoryHdr->lineno); print_alloc("freed", filename, lineno); } else if (verify_tail_guard_data(pcslMemoryHdr)) { report("ERROR: Possible memory overrun: 0x%p\n", ptr); print_alloc("allocated", pcslMemoryHdr->filename, pcslMemoryHdr->lineno); print_alloc("freed", filename, lineno); } report("DEBUG: free %d bytes: 0x%p\n", pcslMemoryHdr->size, ptr); print_alloc("allocated", pcslMemoryHdr->filename, pcslMemoryHdr->lineno); print_alloc("freed", filename, lineno); pcslMemoryHdr->free = 1; } } /* end of else */ }
/* Set countMemoryLeaksOnly = 0 in order to get more verbose information */ int pcsl_mem_malloc_dump_impl0(int countMemoryLeaksOnly) { char *localpcslMallocMemPtr = NULL; char *localpcslMallocMemStart = PcslMemoryStart; char *localpcslMallocMemEnd = PcslMemoryEnd; _PcslMemHdrPtr localpcslMallocMemHdr = NULL; int numberOfAllocatedBlocks = 0; REPORT3("PcslMemory=0x%p PcslMemoryStart=0x%p PcslMemoryEnd=0x%p\n", PcslMemory, PcslMemoryStart, PcslMemoryEnd); for (localpcslMallocMemPtr = localpcslMallocMemStart; localpcslMallocMemPtr < localpcslMallocMemEnd; localpcslMallocMemPtr += localpcslMallocMemHdr->size + sizeof(_PcslMemHdr)) { localpcslMallocMemHdr = (_PcslMemHdrPtr) localpcslMallocMemPtr; if (localpcslMallocMemHdr->magic != MAGIC) { REPORT1("ERROR: memory corruption at 0x%p\n", localpcslMallocMemPtr); return -1; } else { if (countMemoryLeaksOnly == 0) { REPORT4("hdr 0x%p free=%d size=%d address=0x%p\n", localpcslMallocMemHdr, localpcslMallocMemHdr->free, localpcslMallocMemHdr->size, (void *)(((char *)localpcslMallocMemHdr) + sizeof(_PcslMemHdr))); } if (localpcslMallocMemHdr->free != 1) { numberOfAllocatedBlocks += 1; #ifdef PCSL_DEBUG report("WARNING: memory leak: size=%d address=0x%p\n", localpcslMallocMemHdr->size, (void*)((char*)localpcslMallocMemHdr + sizeof(_PcslMemHdr))); print_alloc("allocated", localpcslMallocMemHdr->filename, localpcslMallocMemHdr->lineno); #endif } } } return numberOfAllocatedBlocks; }
/** * FUNCTION: pcsl_mem_get_free_heap_impl0() * TYPE: public operation * OVERVIEW: Get the current amount of unused heap * INTERFACE: * parameters: <none> * returns: The current amount of unused heap * */ int pcsl_mem_get_free_heap_impl0() { _PcslMemHdrPtr pcslMemoryHdr; char* pcslMemoryPtr; int size = 0; for (pcslMemoryPtr = PcslMemoryStart; pcslMemoryPtr < PcslMemoryEnd; pcslMemoryPtr += pcslMemoryHdr->size + sizeof(_PcslMemHdr)) { pcslMemoryHdr = (_PcslMemHdrPtr)pcslMemoryPtr; #ifdef PCSL_DEBUG if (pcslMemoryHdr->magic != MAGIC) { report("ERROR: Corrupted start of memory header: 0x%p\n", pcslMemoryPtr); return -1; } if (pcslMemoryHdr->guard != GUARD_WORD) { report("ERROR: Corrupted end of memory header: 0x%p\n", pcslMemoryPtr); return -1; } /* The memory block header is valid, now check the guard data */ if (verify_tail_guard_data(pcslMemoryHdr)) { report("ERROR: Memory overrun: 0x%p\n", pcslMemoryPtr); print_alloc("allocated", pcslMemoryHdr->filename, pcslMemoryHdr->lineno); } #endif if (pcslMemoryHdr->free != 1) { size += pcslMemoryHdr->size; } } return (pcsl_mem_get_total_heap_impl0() - size); }
void* pcsl_mem_malloc_impl0(unsigned int size, char* filename, int lineno) { #else void* pcsl_mem_malloc_impl0(unsigned int size) { #endif unsigned int numBytesToAllocate = size; void* loc = NULL; _PcslMemHdrPtr tempHdr = NULL; char* temp = NULL; char* pcslMemoryPtr; _PcslMemHdrPtr pcslMemoryHdr; #ifdef PCSL_DEBUG int guardSize = 0; void* guardPos = NULL; int i = 0; numBytesToAllocate += GUARD_SIZE; #endif while ( (numBytesToAllocate & ALIGNMENT) != 0 ) { numBytesToAllocate++; } /* find a free slot */ for (pcslMemoryPtr = PcslMemoryStart; pcslMemoryPtr < PcslMemoryEnd; pcslMemoryPtr += pcslMemoryHdr->size + sizeof(_PcslMemHdr)) { pcslMemoryHdr = (_PcslMemHdrPtr)pcslMemoryPtr; if (pcslMemoryHdr->magic != MAGIC) { REPORT1("ERROR: Memory corruption at 0x%p\n", pcslMemoryPtr); return((void *) 0); } else { while ( 1 ) { /* coalescing */ if (pcslMemoryHdr->free == 1) { /* if current block is free */ temp = (char*)pcslMemoryHdr; temp += pcslMemoryHdr->size + sizeof(_PcslMemHdr); tempHdr = (_PcslMemHdrPtr)temp; if ((temp < PcslMemoryEnd) && (tempHdr->free == 1) && (tempHdr->magic == MAGIC)) { /* and the next block is free too */ /* then coalesce */ pcslMemoryHdr->size += tempHdr->size + sizeof(_PcslMemHdr); #ifdef PCSL_DEBUG pcslMemoryHdr->guardSize = 0; #endif REPORT2("DEBUG: Coalescing blocks 0x%p and 0x%p\n", pcslMemoryHdr, tempHdr); } else { break; } } else { break; } } /* while */ /* allocating */ if ((pcslMemoryHdr->free == 1) && (pcslMemoryHdr->size >= numBytesToAllocate)) { if (pcslMemoryHdr->size > (numBytesToAllocate + sizeof(_PcslMemHdr) + 4)) { /* split block */ _PcslMemHdrPtr nextHdr; nextHdr = (_PcslMemHdrPtr)((char *)pcslMemoryPtr + numBytesToAllocate + sizeof(_PcslMemHdr)); nextHdr->magic = MAGIC; nextHdr->free = 1; nextHdr->size = pcslMemoryHdr->size - numBytesToAllocate - sizeof(_PcslMemHdr); #ifdef PCSL_DEBUG nextHdr->guard = GUARD_WORD; nextHdr->guardSize = 0; #endif pcslMemoryHdr->size = numBytesToAllocate; } pcslMemoryHdr->free = 0; loc = (void*)((char*)pcslMemoryHdr + sizeof(_PcslMemHdr)); #ifdef PCSL_DEBUG pcslMemoryHdr->guard = GUARD_WORD; /* Add head guard */ pcslMemoryHdr->filename = filename; pcslMemoryHdr->lineno = lineno; /* Add tail guard */ guardSize = pcslMemoryHdr->size - size; pcslMemoryHdr->guardSize = guardSize; guardPos = (void*)((char*)loc + pcslMemoryHdr->size - guardSize); for(i=0; i<guardSize; i++) { ((unsigned char*)guardPos)[i] = GUARD_BYTE; } PcslMemoryAllocated += numBytesToAllocate; if (PcslMemoryAllocated > PcslMemoryHighWaterMark) { PcslMemoryHighWaterMark = PcslMemoryAllocated; } report("DEBUG: Requested %d provided %d at 0x%p\n", numBytesToAllocate, pcslMemoryHdr->size, loc); print_alloc("allocated", filename, lineno); #endif return(loc); } /* end of allocating */ } /* end of else */ } /* end of for */ REPORT1("DEBUG: Unable to allocate %d bytes\n", numBytesToAllocate); return((void *)0); }
/* Register allocation */ static int _x86_allocate_registers( EventSetInfo_t * ESI ) { int i, j, natNum; hwd_reg_alloc_t event_list[MAX_COUNTERS]; hwd_register_t *ptr; /* Initialize the local structure needed for counter allocation and optimization. */ natNum = ESI->NativeCount; if ( is_pentium4() ) SUBDBG( "native event count: %d\n", natNum ); for ( i = 0; i < natNum; i++ ) { /* retrieve the mapping information about this native event */ _papi_libpfm_ntv_code_to_bits( ( unsigned int ) ESI->NativeInfoArray[i]. ni_event, &event_list[i].ra_bits ); if ( is_pentium4() ) { /* combine counter bit masks for both esc registers into selector */ event_list[i].ra_selector = event_list[i].ra_bits.counter[0] | event_list[i].ra_bits. counter[1]; } else { /* make sure register allocator only looks at legal registers */ event_list[i].ra_selector = event_list[i].ra_bits.selector & ALLCNTRS; #ifdef PERFCTR_X86_INTEL_CORE2 if ( _papi_hwi_system_info.hw_info.model == PERFCTR_X86_INTEL_CORE2 ) event_list[i].ra_selector |= ( ( event_list[i].ra_bits. selector >> 16 ) << 2 ) & ALLCNTRS; #endif } /* calculate native event rank, which is no. of counters it can live on */ event_list[i].ra_rank = 0; for ( j = 0; j < MAX_COUNTERS; j++ ) { if ( event_list[i].ra_selector & ( 1 << j ) ) { event_list[i].ra_rank++; } } if ( is_pentium4() ) { event_list[i].ra_escr[0] = event_list[i].ra_bits.escr[0]; event_list[i].ra_escr[1] = event_list[i].ra_bits.escr[1]; #ifdef DEBUG SUBDBG( "i: %d\n", i ); print_alloc( &event_list[i] ); #endif } } if ( _papi_hwi_bipartite_alloc( event_list, natNum, ESI->CmpIdx ) ) { /* successfully mapped */ for ( i = 0; i < natNum; i++ ) { #ifdef PERFCTR_X86_INTEL_CORE2 if ( _papi_hwi_system_info.hw_info.model == PERFCTR_X86_INTEL_CORE2 ) event_list[i].ra_bits.selector = event_list[i].ra_selector; #endif #ifdef DEBUG if ( is_pentium4() ) { SUBDBG( "i: %d\n", i ); print_alloc( &event_list[i] ); } #endif /* Copy all info about this native event to the NativeInfo struct */ ptr = ESI->NativeInfoArray[i].ni_bits; *ptr = event_list[i].ra_bits; if ( is_pentium4() ) { /* The selector contains the counter bit position. Turn it into a number and store it in the first counter value, zeroing the second. */ ptr->counter[0] = ffs( event_list[i].ra_selector ) - 1; ptr->counter[1] = 0; } /* Array order on perfctr is event ADD order, not counter #... */ ESI->NativeInfoArray[i].ni_position = i; } return 1; } else return 0; }
/* This function removes shared resources available to the src event from the resources available to the dst event, and reduces the rank of the dst event accordingly. Typically, the src event will be exclusive, but the code shouldn't assume it. Returns nothing. */ static void _x86_bpt_map_preempt( hwd_reg_alloc_t * dst, hwd_reg_alloc_t * src ) { int i; unsigned shared; if ( is_pentium4() ) { #ifdef DEBUG SUBDBG( "src, dst\n" ); print_alloc( src ); print_alloc( dst ); #endif /* check for a pebs conflict */ /* pebs enables must both be non-zero */ i = ( ( ( dst->ra_bits.pebs_enable && src->ra_bits.pebs_enable ) && /* and not equal to each other */ ( dst->ra_bits.pebs_enable != src->ra_bits.pebs_enable ) ) || /* same for pebs_matrix_vert */ ( ( dst->ra_bits.pebs_matrix_vert && src->ra_bits.pebs_matrix_vert ) && ( dst->ra_bits.pebs_matrix_vert != src->ra_bits.pebs_matrix_vert ) ) ); if ( i ) { SUBDBG( "pebs conflict! clearing selector\n" ); dst->ra_selector = 0; return; } else { /* remove counters referenced by any shared escrs */ if ( ( dst->ra_escr[0] == src->ra_escr[0] ) && ( ( int ) dst->ra_escr[0] != -1 ) ) { dst->ra_selector &= ~dst->ra_bits.counter[0]; dst->ra_escr[0] = -1; } if ( ( dst->ra_escr[1] == src->ra_escr[1] ) && ( ( int ) dst->ra_escr[1] != -1 ) ) { dst->ra_selector &= ~dst->ra_bits.counter[1]; dst->ra_escr[1] = -1; } /* remove any remaining shared counters */ shared = ( dst->ra_selector & src->ra_selector ); if ( shared ) dst->ra_selector ^= shared; } /* recompute rank */ for ( i = 0, dst->ra_rank = 0; i < MAX_COUNTERS; i++ ) if ( dst->ra_selector & ( 1 << i ) ) dst->ra_rank++; #ifdef DEBUG SUBDBG( "new dst\n" ); print_alloc( dst ); #endif } else { shared = dst->ra_selector & src->ra_selector; if ( shared ) dst->ra_selector ^= shared; for ( i = 0, dst->ra_rank = 0; i < MAX_COUNTERS; i++ ) if ( dst->ra_selector & ( 1 << i ) ) dst->ra_rank++; } }
int main( int argc, char **argv) { dm_sessid_t sid = DM_NO_SESSION; dm_off_t startoff = 0; /* starting offset */ u_int nelem = 100; char *pathname; void *hanp; size_t hlen; dm_stat_t sbuf; char *name; int opt; if (Progname = strrchr(argv[0], '/')) { Progname++; } else { Progname = argv[0]; } /* Crack and validate the command line options. */ while ((opt = getopt(argc, argv, "Dn:o:s:")) != EOF) { switch(opt) { case 'D': Dflag++; break; case 'n': nelem = atol(optarg); break; case 'o': startoff = atoll(optarg); break; case 's': sid = atol(optarg); break; case '?': usage(); } } if (optind + 1 != argc) usage(); pathname = argv[optind]; if (dm_init_service(&name)) { fprintf(stderr, "dm_init_service failed, %s\n", strerror(errno)); exit(1); } if (sid == DM_NO_SESSION) find_test_session(&sid); /* Get the file's handle and verify that it is a regular file. */ if (dm_path_to_handle(pathname, &hanp, &hlen)) { fprintf(stderr, "can't get handle for %s\n", pathname); exit(1); } if (dm_get_fileattr(sid, hanp, hlen, DM_NO_TOKEN, DM_AT_STAT, &sbuf)) { fprintf(stderr, "dm_get_fileattr failed\n"); exit(1); } if (!S_ISREG(sbuf.dt_mode)) { fprintf(stderr, "%s is not a regular file\n", pathname); exit(1); } /* Print the allocation. */ if (print_alloc(sid, hanp, hlen, pathname, startoff, nelem)) exit(1); dm_handle_free(hanp, hlen); exit(0); }