void *__wrap_realloc(void *p, size_t size) { void *n; // ptr from mem2 if(((u32)p & 0x10000000) != 0 || (p == 0 && size > MEM2_PRIORITY_SIZE)) { n = g_mem2gp.reallocate(p, size); if(n != 0) return n; n = __real_malloc(size); if(n == 0) return 0; if(p != 0) { memcpy(n, p, MEM2_usableSize(p) < size ? MEM2_usableSize(p) : size); g_mem2gp.release(p); } return n; } // ptr from malloc n = __real_realloc(p, size); if(n != 0) return n; n = g_mem2gp.allocate(size); if(n == 0) return 0; if(p != 0) { memcpy(n, p, __real_malloc_usable_size(p) < size ? __real_malloc_usable_size(p) : size); __real_free(p); } return n; }
/** * Returns a descriptor page from the descriptor page * pool or allocates a new descriptor page if the * descriptor page pool is empty. */ static descriptor_page_t *new_descriptor_page() { descriptor_page_t *new_page = NULL; if (descriptor_root->number_of_pooled_descriptor_pages > 0) { descriptor_root->number_of_pooled_descriptor_pages--; new_page = descriptor_root->descriptor_page_pool [descriptor_root->number_of_pooled_descriptor_pages]; #ifdef SCM_RECORD_MEMORY_USAGE dec_pooled_mem(sizeof(descriptor_page_t)); #endif } else { new_page = __real_malloc(SCM_DESCRIPTOR_PAGE_SIZE); if (!new_page) { #ifdef SCM_DEBUG printf("Allocation of new descriptor page failed.\n"); #endif return NULL; } #ifdef SCM_RECORD_MEMORY_USAGE inc_overhead(__real_malloc_usable_size(new_page)); #endif } #ifdef SCM_RECORD_MEMORY_USAGE inc_allocated_mem(__real_malloc_usable_size(new_page)); #endif new_page->number_of_descriptors = 0; new_page->next = NULL; return new_page; }
/* * Expires an object descriptor and decrements the object's descriptor counter. * If the descriptor counter is 0, the object to which the descriptor points * is deallocated. Returns 0 iff no more expired object descriptors exist. */ int expire_object_descriptor_if_exists(expired_descriptor_page_list_t *list) { // check pre-conditions #ifdef SCM_CHECK_CONDITIONS if (list == NULL) { printf("Expired descriptor page list is NULL but was expected to exist.\n"); return 0; } #endif object_header_t *expired_object = (object_header_t*) get_expired_memory(list); if (expired_object != NULL) { //decrement the descriptor counter of the expired object if (atomic_int_dec_and_test((int*) &expired_object->dc_or_region_id)) { //with the descriptor counter now zero run finalizer and free it int finalizer_result = run_finalizer(expired_object); if (finalizer_result != 0) { #ifdef SCM_DEBUG printf("WARNING: finalizer returned %d.\n", finalizer_result); printf("WARNING: %lx is a leak.\n", (unsigned long) PAYLOAD_OFFSET(expired_object)); #endif return 1; //do not free the object } #ifdef SCM_DEBUG printf("Object FREE(%lx).\n", (unsigned long) PAYLOAD_OFFSET(expired_object)); #endif #ifdef SCM_RECORD_MEMORY_USAGE dec_overhead(sizeof(object_header_t)); inc_freed_mem(__real_malloc_usable_size(expired_object)); #endif __real_free(expired_object); return 1; } else { #ifdef SCM_DEBUG printf("Decrementing DC==%d.\n", expired_object->dc_or_region_id); #endif return 1; } } else { #ifdef SCM_DEBUG printf("No expired object found.\n"); #endif return 0; } }
static inline void recycle_descriptor_page(descriptor_page_t *page) { if (descriptor_root->number_of_pooled_descriptor_pages < SCM_DESCRIPTOR_PAGE_FREELIST_SIZE) { descriptor_root->descriptor_page_pool[descriptor_root->number_of_pooled_descriptor_pages] = page; descriptor_root->number_of_pooled_descriptor_pages++; #ifdef SCM_RECORD_MEMORY_USAGE inc_pooled_mem(sizeof(descriptor_page_t)); #endif } else { #ifdef SCM_RECORD_MEMORY_USAGE dec_overhead(__real_malloc_usable_size(page)); inc_freed_mem(__real_malloc_usable_size(page)); #endif __real_free(page); } }
size_t __wrap_malloc_usable_size(void *p) { if(((u32)p & 0x10000000) != 0) return CMEM2Alloc::usableSize(p); return __real_malloc_usable_size(p); }
size_t __wrap_malloc_usable_size(void *p) { return ((u32)p & 0x10000000) != 0 ? MEM2_usableSize(p) : __real_malloc_usable_size(p); }
/** * Recycles a region in O(1) by pooling * the list of free region_pages except the * first region page iff the region_page_pool * limit is not exceeded, otherwise the region_pages * except the first one are deallocated and * the memory is handed back to the OS in O(n), * n = amount of region pages - 1. * * The remaining first region page indicates that the region * once existed, which is necessary to differentiate * it from regions which have not yet been used. * This indicates how many not-yet-used regions * are available. * * If the region was unregistered, all region pages * are recycled or deallocated. * * Returns if no or just one region_page * has been allocated in the region. */ static void recycle_region(region_t* region) { #ifdef SCM_DEBUG printf("Recycle region: %p.\n", region); #endif // check pre-conditions #ifdef SCM_CHECK_CONDITIONS if (region == NULL) { printf("Region recycling failed: NULL region should not appear in the descriptor buffers.\n"); exit(-1); } else if (region->firstPage == NULL || region->lastPage == NULL) { printf("Region recycling failed: Descriptor points to a region which was not correctly initialized.\n"); exit(-1); } if (region->dc != 0) { printf("Region recycling failed: Region seems to be still alive.\n"); exit(-1); } region_t* invar_region = region; #endif region_page_t* legacy_pages; unsigned long number_of_recycle_region_pages; // if the region has been used in the current thread... if (region->age == descriptor_root->current_time) { //.. recycle everything except the first page region_page_t* firstPage = region->firstPage; legacy_pages = firstPage->nextPage; memset(firstPage, '\0', SCM_REGION_PAGE_SIZE); region->last_address_in_last_page = firstPage->memory + SCM_REGION_PAGE_PAYLOAD_SIZE; // nothing to put into the pool if (legacy_pages == NULL) { // check post-conditions #ifdef SCM_CHECK_CONDITIONS if (region->number_of_region_pages != 1) { printf("Region recycling failed: Number of region pages is %u but only one region page exists.\n", region->number_of_region_pages); exit(-1); } else { if (region->firstPage != region->lastPage) { printf("Region recycling failed: Last region page is not equal to first region page but only one region page exists.\n"); exit(-1); } if (region != invar_region) { printf("Region recycling failed: The region changed during recycling.\n"); exit(-1); } if(region->firstPage->nextPage != NULL) { printf("Region recycling failed: Next page pointer is corrupt: %p.\n", region->firstPage->nextPage); exit(-1); } } #endif region->dc = 0; return; } // check post-conditions #ifdef SCM_CHECK_CONDITIONS if (region->number_of_region_pages <= 1) { printf("Region recycling failed: Number of region pages is %u but more than 1 region pages were expected.\n", region->number_of_region_pages); exit(-1); } #endif number_of_recycle_region_pages = region->number_of_region_pages - 1; } // if the region was a zombie in the current thread... else { #ifdef SCM_DEBUG printf("Region expired.\n"); #endif //.. recycle everything, also the first page legacy_pages = region->firstPage; // nothing to put into the pool if (legacy_pages == NULL) { // check post-conditions #ifdef SCM_CHECK_CONDITIONS if (region->number_of_region_pages != 0) { printf("Region recycling failed: Number of region pages is not zero but no region pages exist.\n"); exit(-1); } else { if (region->firstPage != region->lastPage) { printf("Region recycling failed: Last region page is not equal to first region page but only one region page exists.\n"); exit(-1); } if (region != invar_region) { printf("Region recycling failed: The region changed during recycling.\n"); exit(-1); } } #endif region->dc = 0; return; } // check post-conditions #ifdef SCM_CHECK_CONDITIONS if (region->number_of_region_pages == 0) { printf("Region recycling failed: Number of region pages is %u but legacy pages could be obtained.\n", region->number_of_region_pages); exit(-1); } #endif // a zombie region recycles all region pages number_of_recycle_region_pages = region->number_of_region_pages; } unsigned long number_of_pooled_region_pages = descriptor_root->number_of_pooled_region_pages; // is there space in the region page pool? if ((number_of_pooled_region_pages + number_of_recycle_region_pages) <= SCM_REGION_PAGE_FREELIST_SIZE) { //..yes, there is space in the region page pool #ifdef SCM_RECORD_MEMORY_USAGE region_page_t* p = legacy_pages; while(p != NULL) { inc_pooled_mem(SCM_REGION_PAGE_SIZE); inc_overhead(__real_malloc_usable_size(p)); p = p->nextPage; } #endif region_page_t* first_in_pool = descriptor_root->region_page_pool; region_page_t* last_page = region->lastPage; last_page->nextPage = first_in_pool; descriptor_root->region_page_pool = legacy_pages; descriptor_root->number_of_pooled_region_pages = number_of_pooled_region_pages + number_of_recycle_region_pages; } else { //..no, there is no space in the region page pool // If the first region page is not NULL, // deallocate all region pages region_page_t* page2free = legacy_pages; while (page2free != NULL && (number_of_pooled_region_pages + number_of_recycle_region_pages) > SCM_REGION_PAGE_FREELIST_SIZE) { region_page_t* next = page2free->nextPage; __real_free(page2free); #ifdef SCM_RECORD_MEMORY_USAGE inc_freed_mem(SCM_REGION_PAGE_SIZE); #endif page2free = next; number_of_recycle_region_pages--; } // check again if we can recycle now if (page2free != NULL && (number_of_pooled_region_pages + number_of_recycle_region_pages) <= SCM_REGION_PAGE_FREELIST_SIZE) { region_page_t* first_in_pool = descriptor_root->region_page_pool; region_page_t* last_page = region->lastPage; if(last_page != NULL) { last_page->nextPage = first_in_pool; descriptor_root->region_page_pool = page2free; descriptor_root->number_of_pooled_region_pages = number_of_recycle_region_pages - 1; #ifdef SCM_RECORD_MEMORY_USAGE inc_pooled_mem(number_of_recycle_region_pages * SCM_REGION_PAGE_SIZE); #endif } } descriptor_root->number_of_pooled_region_pages = number_of_pooled_region_pages + number_of_recycle_region_pages; } region->number_of_region_pages = 1; region->lastPage = region->firstPage; region->last_address_in_last_page = region->lastPage->memory + SCM_REGION_PAGE_PAYLOAD_SIZE; region->next_free_address = region->lastPage->memory; // check post-conditions #ifdef SCM_CHECK_CONDITIONS if (region->number_of_region_pages != 1) { printf("Region recycling failed: Number of region pages is %u but only one region page exists.\n", region->number_of_region_pages); exit(-1); } else { if (region->firstPage != region->lastPage) { printf("Region recycling failed: Last region page is not equal to first region page but only one region page should exist.\n"); exit(-1); } if (region != invar_region) { printf("Region recycling failed: The region changed during recycling.\n"); exit(-1); } } #endif if (region->age != descriptor_root->current_time) { region->number_of_region_pages = 0; region->lastPage = region->firstPage = NULL; // check post-conditions #ifdef SCM_CHECK_CONDITIONS if (region->number_of_region_pages != 0) { printf("Region recycling failed: Number of region pages is %u but no region pages should exist.\n", region->number_of_region_pages); exit(-1); } else { if (region->firstPage != NULL) { printf("Region recycling failed: First page is not null as expected.\n"); exit(-1); } if (region != invar_region) { printf("Region recycling failed: The region changed during recycling.\n"); exit(-1); } } #endif } }