Exemple #1
0
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;
}
Exemple #2
0
/**
 * 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;
}
Exemple #3
0
/*
 * 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;
    }
}
Exemple #4
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);
    }
}
Exemple #5
0
size_t __wrap_malloc_usable_size(void *p)
{
	if(((u32)p & 0x10000000) != 0)
		return CMEM2Alloc::usableSize(p);
	return __real_malloc_usable_size(p);
}
Exemple #6
0
	size_t __wrap_malloc_usable_size(void *p)
	{
		return ((u32)p & 0x10000000) != 0 ? MEM2_usableSize(p) : __real_malloc_usable_size(p);
	}
Exemple #7
0
/**
 * 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
    }
}