/** * Allocate memory block * * Allocates a block of size bytes of memory, returning a pointer to the * beginning of the block. The content of the newly allocated block of * memory is not initialized, remaining with indeterminate values. * * @param size * Size of the memory block, in bytes. * * @return * On success, a pointer to the memory block allocated by the function. * * The type of this pointer is always void*, which can be cast to the * desired type of data pointer in order to be dereferenceable. * * If the function failed to allocate the requested block of memory, * a null pointer is returned. * * @see http://www.cplusplus.com/reference/clibrary/cstdlib/malloc/ */ void *malloc(size_t size) { if(size<=0) return NULL; if(free_list_ptr == NULL) free_list_ptr = free_list_init(); L( actual_size += size); size_t size_plus_dic = find_new_alloc_size(size); void *block_ptr = block_available(size_plus_dic); if (block_ptr == NULL) { /* Allocate new space from sbrk() */ block_ptr = allocate_new_space(size_plus_dic); D(printf("malloc(): find new space at loc %zu with length %zu, occupy:%d\n", (size_t)(block_ptr - heap_ptr),MDIC(block_ptr)->size, MDIC(block_ptr)->occupy )); // store the size_plus_dic into the block MDIC(block_ptr) -> occupy = true; free_list_delete(block_ptr , size2order( MDIC(block_ptr)->size )); // delete from free list. L( printf("size actual_size total_size: %zu %zu %zu\n",size,actual_size,total_size) ); return block_ptr + sizeof(mem_dic); } else { if (MDIC(block_ptr)->size > size_plus_dic) block_ptr = split_block(block_ptr,size_plus_dic); if ( !block_ptr || MDIC(block_ptr)->size != size_plus_dic){ D( printf("Error in malloc(): size after split cannot match\n") ); return NULL; } /* Assign the size to the block, split the block if necessary */ D( printf("malloc(): find old space at loc %zu with length %zu, occupy:%d\n", (size_t)(block_ptr - heap_ptr),MDIC(block_ptr)->size, MDIC(block_ptr)->occupy ) ); MDIC(block_ptr) -> occupy = true; free_list_delete(block_ptr,size2order( MDIC(block_ptr)->size )); L( printf("size actual_size total_size: %zu %zu %zu\n",size,actual_size,total_size) ); return block_ptr + sizeof(mem_dic); } return NULL; }
/* * bcm_mpm_init() - initialize the whole memory pool system. * * Parameters: * osh: INPUT Operating system handle. Needed for heap memory allocation. * max_pools: INPUT Maximum number of mempools supported. * mgr: OUTPUT The handle is written with the new pools manager object/handle. * * Returns: * BCME_OK Object initialized successfully. May be used. * BCME_NOMEM Initialization failed due to no memory. Object must not be used. */ int BCMATTACHFN(bcm_mpm_init)(osl_t *osh, int max_pools, bcm_mpm_mgr_h *mgrp) { bcm_mpm_mgr_h mgr = NULL; bcm_mp_pool_t *pool_objs; /* Check parameters */ if ((mgrp == NULL) || (osh == NULL) || (max_pools <= 0)) { return (BCME_BADARG); } /* Allocate memory pool manager object. */ mgr = (bcm_mpm_mgr_h) MALLOC(osh, (sizeof(*mgr))); if (mgr == NULL) { return (BCME_NOMEM); } /* Init memory pool manager object. */ memset(mgr, 0, sizeof(*mgr)); mgr->osh = osh; mgr->max_pools = (uint16) max_pools; /* Pre-allocate pool meta-data (array of bcm_mp_pool structs). */ pool_objs = (bcm_mp_pool_t *) MALLOC(osh, max_pools * sizeof(bcm_mp_pool_t)); if (pool_objs == NULL) { MFREE(osh, mgr, sizeof(*mgr)); return (BCME_NOMEM); } memset(pool_objs, 0, max_pools * sizeof(bcm_mp_pool_t)); mgr->pool_objs = pool_objs; /* Chain all the memory pools onto the manager's free list. */ STATIC_ASSERT(sizeof(bcm_mp_pool_t) > sizeof(bcm_mp_free_list_t)); free_list_init(&mgr->free_pools, pool_objs, sizeof(bcm_mp_pool_t), max_pools); *mgrp = mgr; return (BCME_OK); }
/* * create_pool() - Create a new pool for fixed size objects. Helper function * common to all memory pool types. * * Parameters: * mgr: INPUT The handle to the pool manager * obj_sz: INPUT Size of objects that will be allocated by the new pool. * This is the size requested by the user. The actual size * of the memory object may be padded. * Must be > 0 for heap pools. Must be >= sizeof(void *) for * Prealloc pools. * padded_obj_sz: INPUT Size of objects that will be allocated by the new pool. * This is the actual size of memory objects. It is 'obj_sz' * plus optional padding required for alignment. * Must be > 0 for heap pools. Must be >= sizeof(void *) for * Prealloc pools. * nobj: INPUT Maximum number of concurrently existing objects to support. * Must be specified for Prealloc pool. Ignored for heap pools. * memstart INPUT Pointer to the memory to use, or NULL to malloc(). * Ignored for heap pools. * memsize INPUT Number of bytes referenced from memstart (for error checking). * Must be 0 if 'memstart' is NULL. Ignored for heap pools. * poolname INPUT For instrumentation, the name of the pool * type INPUT Pool type - BCM_MP_TYPE_xxx. * newp: OUTPUT The handle for the new pool, if creation is successful * * Returns: * BCME_OK Pool created ok. * other Pool not created due to indicated error. newpoolp set to NULL. * * */ static int BCMATTACHFN(create_pool)(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int padded_obj_sz, int nobj, void *memstart, char poolname[BCM_MP_NAMELEN], uint16 type, bcm_mp_pool_h *newp) { bcm_mp_pool_t *mem_pool = NULL; void *malloc_memstart = NULL; /* Check parameters */ if ((mgr == NULL) || (newp == NULL) || (obj_sz == 0) || (padded_obj_sz == 0) || (poolname == NULL) || (poolname[0] == '\0')) { return (BCME_BADARG); } /* Allocate memory object from pool. */ mem_pool = (bcm_mp_pool_t *) free_list_remove(&mgr->free_pools); if (mem_pool == NULL) { return (BCME_NOMEM); } /* For pool manager allocated memory, malloc the contiguous memory * block of objects. */ if ((type == BCM_MP_TYPE_PREALLOC) && (memstart == NULL)) { memstart = MALLOC(mgr->osh, padded_obj_sz * nobj); if (memstart == NULL) { free_list_add(&mgr->free_pools, (bcm_mp_free_list_t *) mem_pool); return (BCME_NOMEM); } malloc_memstart = memstart; } /* Init memory pool object (common). */ memset(mem_pool, 0, sizeof(*mem_pool)); mem_pool->objsz = obj_sz; BCM_MP_SET_POOL_TYPE(mem_pool, type); BCM_MP_SET_IN_USE(mem_pool); strncpy(mem_pool->name, poolname, sizeof(mem_pool->name)); mem_pool->name[sizeof(mem_pool->name)-1] = '\0'; if (type == BCM_MP_TYPE_PREALLOC) { /* Init memory pool object (Prealloc specific). */ mem_pool->u.p.nobj = (uint16) nobj; mem_pool->u.p.malloc_memstart = malloc_memstart; mem_pool->u.p.padded_objsz = padded_obj_sz; /* Chain all the memory objects onto the pool's free list. */ free_list_init(&mem_pool->u.p.free_objp, memstart, padded_obj_sz, nobj); } else { /* Init memory pool object (Heap specific). */ mem_pool->u.h.osh = mgr->osh; } mgr->npools++; *newp = mem_pool; return (BCME_OK); }
int main(int argc, char** argv) { if(argc != 2 && argc != 3) { c_print_format("Usage: %s FILE [cartridge/folder]\n", argv[0]); return 0; } Arena arena = arena_create(MB(512)); String cartridge_folder_path_name = (argc > 2) ? string_from_c_string(argv[2]) : L("SuperMarioWorld.sfc"); Path cartridge_folder_path; path_init(&cartridge_folder_path, cartridge_folder_path_name); Path manifest_path; path_init_from_c(&manifest_path, &cartridge_folder_path, "manifest.bml"); Buffer manifest_buffer = path_read_file(&manifest_path, &arena); Wdc65816MapperBuilder rom_builder = { }; char name[256]; Buffer name_buffer = buffer(name, 256); Buffer rom_buffer; for(Wdc65816RomLoader loader = wdc65816_rom_loader_begin(&rom_builder, string_from_buffer(manifest_buffer)); wdc65816_rom_loader_end(&loader); wdc65816_rom_loader_next(&loader)) { Wdc65816MemoryBufferRequest request = wdc65816_rom_loader_get_buffer_request(&loader, name_buffer); Buffer file_buffer = buffer(arena_alloc_array(&arena, request.size, u8), request.size); if(string_equal(request.name, L("program.rom")) && request.type == WDC65816_MEMORY_ROM) { rom_buffer = file_buffer; } wdc65816_rom_loader_set_buffer(&loader, file_buffer); } uint mapper_buffer_size = wdc65816_mapper_get_buffer_size(); u8* work_buffer = arena_alloc_array(&arena, mapper_buffer_size, u8); Wdc65816Mapper rom; wdc65816_mapper_init(&rom, &rom_builder, (u8**)work_buffer); nuts_global_init(); Path working_dir; path_init_working_directory(&working_dir); FreeList sentinel; free_list_init(&sentinel); ErrorList error_list; error_list_init(&error_list, arena_subarena(&arena, MB(10))); AST ast; ast_init(&ast, &arena); String file_name = string_from_c_string(argv[1]); /* struct timespec lex_start, lex_end, lex_time = { 0 }; */ /* struct timespec parse_start, parse_end, parse_time = { 0 }; */ /* struct timespec assemble_start, assemble_end, assemble_time = { 0 }; */ /* struct timespec all_start, all_end, all_time; */ /* clock_gettime(CLOCK_REALTIME, &all_start); */ Parser parser; parser_init(&parser, &arena, &sentinel, &error_list, &ast); int error_num = 0; while(1) { Path file; path_init(&file, file_name); Buffer file_buffer = path_read_file(&file, &arena); TokenList token_list; //c_print_format("read %.*s\n", file_name.length, file_name.data); Text file_text = { .buffer = file_buffer, .name = file_name }; /* clock_gettime(CLOCK_REALTIME, &lex_start); */ Result result = lex(file_text, &token_list, &arena, &error_list, &ast.identifier_map); if(result == RESULT_ERROR) { for(;error_num < error_list.length; error_num++) { describe_error(error_list.errors[error_num]); } } /* clock_gettime(CLOCK_REALTIME, &lex_end); */ /* lex_time = timespec_add(lex_time, timespec_sub(lex_start, lex_end)); */ /* clock_gettime(CLOCK_REALTIME, &parse_start); */ /* result = parse(&parser, token_list); */ /* clock_gettime(CLOCK_REALTIME, &parse_end); */ /* parse_time = timespec_add(parse_time, timespec_sub(parse_start, parse_end)); */ if(result == RESULT_NEED_TOKEN_STREAM) { file_name = parser.needed_token_stream_file_name; continue; } else if(result == RESULT_OK) { break; } else if(result == RESULT_ERROR) { for(;error_num < error_list.length; error_num++) { describe_error(error_list.errors[error_num]); } return 1; } else { invalid_code_path; } } /* clock_gettime(CLOCK_REALTIME, &assemble_start); */ Assembler assembler; assembler_init(&assembler, &error_list, &ast, &rom); Result result = RESULT_ERROR; while(result != RESULT_OK) { result = assemble(&assembler); if(result == RESULT_NEED_FILE) { String file_name = assembler_get_file_name(&assembler); Path file; path_init(&file, file_name); Buffer file_buffer = path_read_file(&file, &arena); assembler_give_buffer(&assembler, file_buffer); } else if(result == RESULT_ERROR) { break; } } /* clock_gettime(CLOCK_REALTIME, &assemble_end); */ /* assemble_time = timespec_add(assemble_time, timespec_sub(assemble_start, assemble_end)); */ for(int i = 0; i < error_list.length; i++) { describe_error(error_list.errors[i]); } /* parser_deinit(&parser); */ /* clock_gettime(CLOCK_REALTIME, &all_end); */ /* all_time = timespec_sub(all_start, all_end); */ /* c_print_format("Lex: %li.%06lims\n", lex_time.tv_sec * 1000 + lex_time.tv_nsec / 1000000, lex_time.tv_nsec % 1000000); */ /* c_print_format("Parse: %li.%06lims\n", parse_time.tv_sec * 1000 + parse_time.tv_nsec / 1000000, parse_time.tv_nsec % 1000000); */ /* c_print_format("Assemble: %li.%06lims\n", assemble_time.tv_sec * 1000 + assemble_time.tv_nsec / 1000000, assemble_time.tv_nsec % 1000000); */ /* c_print_format("All: %li.%06lims\n", all_time.tv_sec * 1000 + all_time.tv_nsec / 1000000, all_time.tv_nsec % 1000000); */ Path rom_path; path_create_from(&rom_path, &cartridge_folder_path, L("program.rom")); path_write_file(&rom_path, rom_buffer); return 0; }