void HeapManager::printStatus() { int free_blocks = 0, used_blocks = 0; int free_memory = 0, used_memory = 0; unsigned char block_size; char type, color; bool free; int p = 0; while(p < HEAP_SIZE - HEAP_HEAD_SIZE) { read_block_size(heap+p, block_size); read_block_flags(heap+p, type, color, free); if (block_size == 0) { // reached free space at the and of the heap printf("Free: %.3f kB (%i blocks), used: %.3f kB (%i blocks)\n", free_memory/1024., free_blocks, used_memory/1024., used_blocks); double left = (HEAP_SIZE - p)/1024.; printf("%.3f kB (%.3f MB) left\n\n", left, left/1024.); break; } if (free) { free_blocks++; free_memory += block_size; } else { used_blocks++; used_memory += block_size; } p += HEAP_HEAD_SIZE + block_size; } }
char* HeapManager::getAddress(unsigned char alloc_size, unsigned char& block_size) { char type,color; bool free; int p = (int)(next_free_block - heap); while (p < HEAP_SIZE - HEAP_HEAD_SIZE - alloc_size) { read_block_size(heap+p, block_size); read_block_flags(heap+p, type, color, free); if (free && (block_size == 0 || alloc_size <= block_size)) { return heap+p; } p += FULL_BLOCK_SIZE(block_size); } return NULL; }
int main(int argc, char *argv[]) { int fd_in, fd_out; unsigned long n; if (argc != 4) { fprintf(stderr, "Usage: %s <file input> <file output> <block size>\n", argv[0]); exit(EXIT_FAILURE); } open_files(argv[1], argv[2], &fd_in, &fd_out); n = read_block_size(argv[3]); copy_invert(fd_in, fd_out, n); exit(EXIT_SUCCESS); }
void HeapManager::print() { unsigned char block_size; char type; char color; bool free; int p = 0; printf("Skipping protected\n"); while(p < HEAP_SIZE - HEAP_HEAD_SIZE) { read_block_size(heap+p, block_size); read_block_flags(heap+p, type, color, free); if (color != GC_PROTECTED) { if (block_size == 0) { // reached free space at the and of the heap double left = (HEAP_SIZE - p)/1024.; printf("%.3f kB (%.3f MB) left\n\n", left, left/1024.); break; } switch(color) { case GC_WHITE: printf("W"); break; case GC_BLACK: printf("B"); break; case GC_GRAY: printf("G"); break; case GC_PROTECTED: printf("*"); break; default: break; } printf(" Block [%i] @%i: %iB", free, p, block_size); if (!free) { switch(type) { case GC_TABLE: printf(", table"); break; case GC_UPVAL: printf(", upval"); break; case GC_CLOSURE: printf(", closure"); break; case GC_STRING: printf(", string"); break; case GC_NATIVE: printf(", native"); break; case GC_FILE: printf(", file"); break; default: printf("unknown"); break; } } printf("\n"); } p += HEAP_HEAD_SIZE + block_size; } }
void HeapManager::purgeHeap(bool force) { unsigned char block_size; char type, color; bool free; next_free_block = NULL; char* prev_block = NULL; unsigned char prev_size = 0; int p = 0; while (p < HEAP_SIZE - HEAP_HEAD_SIZE - HEAP_MIN_BLOCK_SIZE) { char* block = heap+p; read_block_size(block, block_size); if (block_size == 0) { // reached the end of used space if (next_free_block == NULL) { next_free_block = block; } if (prev_block != NULL) { write_block_size(prev_block, 0); } break; } read_block_flags(block, type, color, free); // free white blocks if (!free && (color == GC_WHITE || force)) { #if DEBUG_HEAP_ALLOC printf("DEALLOC %i\n", (int)(block - heap)); #endif switch(type) { case GC_TABLE: ((Table*) (block + HEAP_HEAD_SIZE))->~Table(); break; case GC_UPVAL: ((UpvalueRef*) (block + HEAP_HEAD_SIZE))->~UpvalueRef(); break; case GC_CLOSURE: ((Closure*) (block + HEAP_HEAD_SIZE))->~Closure(); break; case GC_STRING: ((StringObject*)(block + HEAP_HEAD_SIZE))->~StringObject(); break; case GC_NATIVE: ((Native*) (block + HEAP_HEAD_SIZE))->~Native(); break; case GC_FILE: ((File*) (block + HEAP_HEAD_SIZE))->~File(); break; default: break; } free = true; } if (!free) { write_block_flags(block, type, (char)(color == GC_PROTECTED ? GC_PROTECTED : GC_WHITE), free); prev_block = NULL; } else { if (next_free_block == NULL) { next_free_block = block; } // if possible, merge with previous free block if (prev_block != NULL && prev_size + block_size + HEAP_HEAD_SIZE <= HEAP_MAX_BLOCK_SIZE) { write_block_size(prev_block, (unsigned char)(prev_size + block_size + HEAP_HEAD_SIZE)); prev_size = (unsigned char)(prev_size + block_size + HEAP_HEAD_SIZE); // otherwise just mark block as free } else { write_block_flags(block, type, GC_WHITE, free); prev_block = block; prev_size = block_size; } } p += FULL_BLOCK_SIZE(block_size); } }