//Add a <key,value> pair to the cache //If key already exists, overwrite the old value //If maxmem capacity is exceeded, values will be removed void cache_set(cache_t cache, _key_t key, val_t val, uint32_t val_size) { cache_real_obj *c = cache->cache; //Delete the value if it's already in the cache. meta_t old = get_key_loc(cache,key); if (old != NULL) cache_delete(cache, key); uint64_t available_memory = cache->cache->size - cache_space_used(cache); printf("Trying to add a value of size %"PRIu32", with available memory %"PRIu64"\n",val_size,available_memory); if (available_memory < val_size) { printf(" Increasing size.\n"); defrag(cache, 1); //This doubles the cache size (defragmenting at the same time). } bucket_timer_up(cache); //Create a new meta object and pair it to a slab address, and copy the value over meta_t next_meta = create_meta(cache,key,val_size); next_meta->address = get_address(c->slab_manager,val_size); //enact eviction policy if we need space if (next_meta->address == NULL){ uint32_t val_slab_class = get_slab_class(c->slab_manager, val_size); cache_evict(cache, val_slab_class); next_meta->address = get_address(c->slab_manager,val_size); if (next_meta->address == NULL){ uint32_t slab_class = get_slab_class(c->slab_manager, val_size); printf("Couldn't add a %u-%u byte value because there are no slabs of that range, and no free slabs to be allocated\n",slab_class>>1, slab_class); free(next_meta); return; }
bool SlottedPage::tryUpdateSlotWithIndirection(uint16_t slotID, char const *dataptr, uint16_t lenInBytes) { Slot* s = &slots[slotID]; if(getFreeSpaceInBytes() >= lenInBytes){ header.dataStart -= lenInBytes; memcpy( &data[header.dataStart], dataptr, lenInBytes); s->offset = header.dataStart; s->length = lenInBytes; setControlbitsToDefault(slotID); //here we have completely removed the TID, which was previously stored in this slot return true; } //4. (length is greater than before && space after defrag) -> defrag and insert anywhere on page -> update length & offset else if(getFreeSpaceInBytesAfterDefrag() >= lenInBytes){ defrag(); header.dataStart -= lenInBytes; memcpy( &data[header.dataStart], dataptr, lenInBytes); s->offset = header.dataStart; s->length = lenInBytes; setControlbitsToDefault(slotID); //here we have completely removed the TID, which was previously stored in this slot return true; } return false; }
void deleteFile(const char *path){ filereference *ref = getReferenceByPath((char *)path); if(ref == NULL){ printf("Warning: Trying to delete unexistent file: $%s\n", path); return; } drive->filecount--; drive->freespace += ref->size; // if the file to be deleted is already the last file in the list if(strcmp(drive->files[drive->filecount].name,path) == 0){ // there is nothing else to be done, decrementing the filecount is enough return; } // the file is somewhere in the middle or begining of the filelist int cnt; bool copyahead = false; for(cnt = 0; cnt < drive->filecount; cnt++){ ref = drive->files + cnt; if(strcmp(path,ref->name) == 0){// found match copyahead = true; } if(copyahead){ *ref = drive->files[cnt+1]; } } defrag(); }
void free(void *ptr) { t_block *block; t_zone *zone; if (!ptr) return ; pthread_mutex_lock(&g_mutex); block = (t_block *)(ptr - HEADER_SIZE); if (!block->parent) { pthread_mutex_unlock(&g_mutex); return ; } block->flag = FREE; zone = block->parent; zone->blocks_used--; zone->size_free += block->size + HEADER_SIZE; if (zone->blocks_used <= 0 || zone->type == LARGE_INDEX) free_zone(zone); else defrag(block); ptr = NULL; pthread_mutex_unlock(&g_mutex); }
int spm_alloc(int bytes) { assert(spm_used_size + bytes <= spm_size); int blocks = bytes/spm_block_size + (bytes%spm_block_size?1:0); /* first try */ int loc = first_fit(blocks); if (loc == -1) { defrag(); spm_need_defragment = 1; } else { spm_need_defragment = 0; } /* set the bits of the used blocks */ loc = first_fit(blocks); assert(loc != -1); for (int k = 0; k < blocks; k++) { set(loc + k); } spm_used_size += blocks * spm_block_size; spm_internal_fragment += spm_block_size - bytes%spm_block_size; return loc; }
void *malloc(size_t size) { Header *curr = freelist, *prev = NULL, *first = NULL; int desiredSize = size; // 16-divisiblity while (size % 16) size++; // defrag contiguous free blocks then iterate over the freelist defrag(); while (curr) { if (curr->free && curr->size >= size) { // carve out block if free block is big enough if (curr->size > size) { curr->next = carveHeader(size, curr); curr->size = size; } // if curr->size is equal to desired alloc size only do this curr->free = 0; #if DEBUG_MALLOC snprintf(buffer, BUFSIZE, "MALLOC: malloc(%d) => (ptr=%p, size=%d)\n", desiredSize, curr + 1, curr->size); fputs(buffer, stderr); #endif return curr + 1; } curr = curr->next; } // extend section break if no blocks are available Header *header = sbrk(sizeof(Header) + size); if (header < 0) return NULL; header->free = 0; header->size = size; push_back(header); #if DEBUG_MALLOC snprintf(buffer, BUFSIZE, "MALLOC: malloc(%d) => (ptr=%p, size=%d)\n", desiredSize, header + 1, header->size); fputs(buffer, stderr); #endif return header + 1; }
int deallocate(void* mem_ptr) { size_t i, j; size_t heap_pos; bool find_flag = false; printf("\n --- deallocate ---"); if (mem_ptr == NULL) { printf("\nNULL pointer free().\n"); return DEALLOC_FAILURE; } for (i = 0; i < memory->heaps_count; i++) { if (mem_ptr == memory->heaps[i].mem_ptr) { heap_pos = i; find_flag = true; for (j = memory->heaps[i].mem_begin; j < memory->heaps[i].mem_end; j++) { memory->mem_block[j] = 0; } } if (find_flag == true) { break; } } if (find_flag == false) { printf("\nNot initialized pointer or double free().\n"); return DEALLOC_FAILURE; } memory->allocated_bytes -= memory->heaps[heap_pos].mem_size; memory->free_bytes += memory->heaps[heap_pos].mem_size; memory->mem_usage.total_free_calls++; mem_ptr = NULL; zero_heap_data(&(memory->heaps[heap_pos])); move_heaps(); find_free_mem(); defrag(); return 0; }
/* * Only call on a regular slot (no indirection, not removed!) */ bool SlottedPage::tryUpdate(uint16_t slotID, char const *dataptr, uint16_t lenInBytes) { Slot* s = &slots[slotID]; //1. (length is the same) -> insert at the same position //& 2. (length is smaller than before) -> insert at the same position -> update length & fragmented if(s->length >= lenInBytes){ memcpy(&data[s->offset], dataptr, lenInBytes); header.fragmentedSpace += s->length - lenInBytes; s->length = lenInBytes; return true; } else if( s->length < lenInBytes){ //3. (length is greater than before && space on page) -> insert anywhere on page -> update length, offset, fragmented if(getFreeSpaceInBytes() >= lenInBytes){ header.fragmentedSpace += s->length; header.dataStart -= lenInBytes; memcpy( &data[header.dataStart], dataptr, lenInBytes); s->offset = header.dataStart; s->length = lenInBytes; setControlbitsToDefault(slotID); return true; } //4. (length is greater than before && space after defrag) -> defrag and insert anywhere on page -> update length & offset else if(getFreeSpaceInBytesAfterDefrag() + s->length >= lenInBytes){ setControlbitsToRemoved(slotID); defrag(); header.dataStart -= lenInBytes; memcpy( &data[header.dataStart], dataptr, lenInBytes); s->offset = header.dataStart; s->length = lenInBytes; setControlbitsToDefault(slotID); return true; } } return false; }
void *malloc(int size) { int *p, *end; int k, n, tries; size = (size + sizeof(int) - 1) / sizeof(int); if (NULL == _arena) { if (size >= THRESHOLD) _asize = size + 1; else _asize = size * OVERALLOC; _arena = _sbrk(_asize * sizeof(int)); if ((int *) -1 == _arena) { errno = ENOMEM; return NULL; } _arena[0] = _asize; freep = _arena; } for (tries = 0; tries < 3; tries++) { end = _arena + _asize; p = freep; do { if (*p > size) { if (size + 1 == *p) { *p = -*p; } else { k = *p; *p = -(size+1); p[size+1] = k - size - 1; } freep = p; return p+1; } p += abs(*p); if (p == end) p = _arena; if (p < _arena || p >= end || 0 == *p) { _write(2, "malloc(): corrupt arena\n", 24); abort(); } } while (p != freep); if (0 == tries) { defrag(); } else { if (size >= THRESHOLD) n = size + 1; else n = size * OVERALLOC; if (_sbrk(n * sizeof(int)) == (void *)-1) { errno = ENOMEM; return NULL; } k = _asize; _asize += n; *end = _asize - k; } } errno = ENOMEM; return NULL; }
int FileSystem::changeSize(fs_pageno newPageCount) { bool mustReleaseLock = getLock(); int result = FILESYSTEM_ERROR; // if "newPageCount" is too small, an error is returned if ((newPageCount < MIN_PAGE_COUNT) || (newPageCount < getUsedPageCount()) || (newPageCount > MAX_PAGE_COUNT)) goto endOfChangeSize; if (newPageCount < pageCount) { // First, defragment the filesystem in order to be able to reduce the size. if (defrag() == FILESYSTEM_ERROR) goto endOfChangeSize; // Then, decrease the size of the filesystem. int newPageLayoutSize = (newPageCount + (intsPerPage - 1)) / intsPerPage; byte *pageBuffer = (byte*)malloc(pageSize); // copy page layout data to new position for (int i = 0; i < newPageLayoutSize; i++) { readPage(pageCount + i, pageBuffer); writePage(newPageCount + i, pageBuffer); } // copy file->page mappings to new position for (int i = 0; i < fileMappingSize; i++) { readPage(pageCount + pageLayoutSize + i, pageBuffer); writePage(newPageCount + newPageLayoutSize + i, pageBuffer); } free(pageBuffer); pageCount = newPageCount; pageLayoutSize = newPageLayoutSize; // write changed preamble to disk int32_t pageCountOnDisk = (int32_t)pageCount; int32_t pageLayoutSizeOnDisk = (int32_t)pageLayoutSize; lseek(dataFile, 2 * INT_SIZE, SEEK_SET); forced_write(dataFile, &pageCountOnDisk, INT_SIZE); forced_write(dataFile, &pageLayoutSizeOnDisk, INT_SIZE); // change the size of the data file off_t fileSize = pageSize; fileSize *= (newPageCount + newPageLayoutSize + fileMappingSize); forced_ftruncate(dataFile, fileSize); } // end if (newPageCount < pageCount) if (newPageCount > pageCount) { // change the size of the data file int newPageLayoutSize = (newPageCount + (intsPerPage - 1)) / intsPerPage; off_t fileSize = pageSize; fileSize *= (newPageCount + newPageLayoutSize + fileMappingSize); if (ftruncate(dataFile, fileSize) < 0) { fprintf(stderr, "Filesystem size could not be changed.\n"); perror(NULL); goto endOfChangeSize; } if (getSize() != fileSize) { fprintf(stderr, "Filesystem size could not be changed.\n"); perror(NULL); goto endOfChangeSize; } int oldPageCount = pageCount; pageCount = newPageCount; int oldPageLayoutSize = pageLayoutSize; pageLayoutSize = newPageLayoutSize; // write changed preamble to disk int32_t pageCountOnDisk = (int32_t)pageCount; int32_t pageLayoutSizeOnDisk = (int32_t)pageLayoutSize; lseek(dataFile, 2 * INT_SIZE, SEEK_SET); forced_write(dataFile, &pageCountOnDisk, INT_SIZE); forced_write(dataFile, &pageLayoutSizeOnDisk, INT_SIZE); byte *pageBuffer = (byte*)malloc(pageSize); // copy file->page mappings to new position for (int i = fileMappingSize - 1; i >= 0; i--) { readPage(oldPageCount + oldPageLayoutSize + i, pageBuffer); writePage(newPageCount + newPageLayoutSize + i, pageBuffer); } // copy page layout data to new position for (int i = oldPageLayoutSize - 1; i >= 0; i--) { readPage(oldPageCount + i, pageBuffer); writePage(newPageCount + i, pageBuffer); } // initialize layout data for the new pages int32_t unusedValue = UNUSED_PAGE; for (int i = 0; i < intsPerPage; i++) memcpy(&pageBuffer[i * INT_SIZE], &unusedValue, INT_SIZE); for (int i = oldPageLayoutSize; i < newPageLayoutSize; i++) writePage(newPageCount + i, pageBuffer); free(pageBuffer); // update the freePages and freeFileNumbers arrays free(freePages); freePages = NULL; free(freeFileNumbers); freeFileNumbers = NULL; initializeFreeSpaceArrays(); } // end if (newPageCount > pageCount) enableCaching(); result = FILESYSTEM_SUCCESS; endOfChangeSize: if (mustReleaseLock) releaseLock(); return result; } // end of changeSize(fs_pageno)
void *realloc(void *ptr, size_t size) { int desiredSize = size; // if first argument is NULL, do malloc if (!ptr) { void *block = malloc(size); #if DEBUG_MALLOC snprintf(buffer, BUFSIZE, "MALLOC: realloc(%p, %d) => (ptr=%p, " "size=%d)\n", ptr, desiredSize, block, ((Header *)block)[-1].size); fputs(buffer, stderr); #endif return block; } defrag(); Header *curr = (Header *)ptr - 1; int sum = curr->size; // track how much free continguous space we have to do an in-place // expansion curr = curr->next; while (curr && curr->free) { sum += curr->size; curr = curr->next; } // 16 divisibility while (size % 16) size++; curr = (Header *)ptr - 1; if (sum > size && curr->next) { // in-place expansion w/o moving sbrk Header *oldHeader = curr->next; Header *newHeader = (char *)curr + sizeof(Header) + size; newHeader->next = oldHeader->next; newHeader->size = sum - size; newHeader->free = 1; curr->next = newHeader; curr->size = size; } else if (sum < size) { if (!curr->next) { // in-place expansion w/ moving sbrk sbrk(size - curr->size); curr->size = size; } else { // malloc new location, copy data curr->free = 1; char *oldLocation = ++curr; char *newLocation = malloc(size); if (!newLocation) { curr->free = 0; return NULL; } memmove(newLocation, oldLocation, curr->size); curr = (Header *)newLocation - 1; } } #if DEBUG_MALLOC snprintf(buffer, BUFSIZE, "MALLOC: realloc(%p, %d) => (ptr=%p, size=%d)\n", ptr, desiredSize, curr + 1, curr->size); fputs(buffer, stderr); #endif return curr + 1; }