📄 memory.c
字号:
int i; pthread_mutexattr_t mutex_attr; pthread_mutexattr_init(&mutex_attr); // initialize mutex configuration for (i = 0; i < NBR_BLOCKTYPES; i++) { blocklists[i].first = 0; blocklists[i].element_size = 0; blocklists[i].first_phys_area = 0; blocklists[i].phys_area_size = 0; blocklists[i].blocks_avail = 0; pthread_mutex_init(&blocklists[i].mutex, &mutex_attr); // initialize mutex } pthread_mutexattr_destroy(&mutex_attr); // destroy mutex configuration}/** * Check the parameter array for consistency. If blocks of a size * smaller than MIN_BLOCK_PWR_2 are specified, their number will be * added to the number of blocks of size MIN_BLOCK_PWR_2 and the * parameter is set to 0. Parameters for blocks with a size bigger * than MAX_BLOCK_PWR_2 are set to 0. * * After this function, the blocks parameter array is in a consistent * state. */int check_parameters(void) { int i; for (i = 0; i < NBR_BLOCKTYPES; i++) { if (blocks[i] < 0) { PR_DBG(0, "Parameters inconsistent for blocksize %i\n", 1 << i); return 1; } if (i < MIN_BLOCK_PWR_2) { if (blocks[i] > 0) { blocks[MIN_BLOCK_PWR_2] += blocks[i]; PR_DBG(2, "Blocksize 0x%X too small, creating blocks of size 0x%X\n", 1 << i, 1 << MIN_BLOCK_PWR_2); } } if (i > MAX_BLOCK_PWR_2) { if (blocks[i] > 0) PR_DBG(2, "Blocksize 0x%X too big, ignoring request.\n", 1 << i); blocks[i] = 0; } } PR_DBG(1, "Parameters ok\n"); return 0;}/** * Calculate for each blocksize the size of the physical area which * will be allocated. The assumption is that the header and the data * are equally aligned. */void calculate_area_sizes(void) { int i; int align = ALIGNED - 1; int header_size = sizeof(mem_header_t); int data_size, aligned_data_size; aligned_header_size_ = ( header_size | align ) + 1; for (i = 0; i < NBR_BLOCKTYPES; i++) { data_size = 1 << i; // round up to next higher multiple of align // The +4 is for integrity-checking at the end of the memory-segment aligned_data_size = ( ( data_size + 4 ) | align ) + 1; // calculate the sizes of one element and of the physical area blocklists[i].element_size = aligned_header_size_ + aligned_data_size; blocklists[i].phys_area_size = blocks[i] * blocklists[i].element_size; }}/** * Allocate just one block, if some block already exists, appends a new one. */int allocate_one_block( int block ) { int size; phys_area_t *next; block_entry_t *b = blocklists + block; unsigned int p; size = b->phys_area_size; if (size) { size += sizeof( phys_area_t ); PR_DBG(4, "Allocate %i bytes with bigphys for pwr2 %i\n", size, block); next = b->first_phys_area; if (!(b->first_phys_area = phys_malloc(size+ALIGNED))) { return 1; } // Append the old physical area to the new one b->first_phys_area->next = next; // Find the next aligned address p = (unsigned int)b->first_phys_area; p += sizeof( phys_area_t ) - 1; p |= ( ALIGNED - 1 ); p++; b->first_phys_area->phys_area = (void*)p; b->blocks_avail += blocks[block]; b->first = format_segment(b->first_phys_area->phys_area, b->element_size, blocks[block], block); } return 0;}/** * Allocate for each blocklist its chunk of physical memory. */int allocate_physical_mem(void) { int i; // initialize all pointers to 0: for (i = 0; i < NBR_BLOCKTYPES; i++) { blocklists[i].first_phys_area = 0; } // allocate space if needed: for (i = 0; i < NBR_BLOCKTYPES; i++) { if ( allocate_one_block( i ) ) { PR_DBG( 0, "Couldn't allocate block %i - continuing anyway\n", i ); } } PR_DBG(1, "Physical memory allocated for all blocklists\n"); return 0;}/** * Free the physical memory for all blocklists. No errors are reported * as the bigphysarea interface doesn't report errors for the free * function. */int free_physical_mem(void) { int i; phys_area_t *next; for (i = 0; i < NBR_BLOCKTYPES; i++) { while ( blocklists[i].first_phys_area ) { next = blocklists[i].first_phys_area->next; phys_free(blocklists[i].first_phys_area); blocklists[i].first_phys_area = next; } } PR_DBG(1, "Physical memory freed\n"); return 0;}//-------------------------------------------------------------------// PUBLIC FUNCTIONS//-------------------------------------------------------------------/** * This function is exported and allows to allocate memory from our * memory manager. A pointer to the data block is returned. * * @param size : The size of the returned memory block * * @return The *address of the memory block, 0 if the allocation * failed. */void *swr_malloc_func(int size, char *file, char *func, int show_error) { mem_header_t *memory; void *pointer; int index; if (size == 0) { PR_DBG(1, "swr_malloc in (%s:%s): Requested block of size 0, returning NULL\n", file, func ); return NULL; } // get the index for the right list if ((index = get_blocklists_index(size)) == -1) { if ( show_error ){ PR_DBG(0, "swr_malloc in (%s:%s): size %i out of possible range\n", file, func, size ); } return NULL; } // get a block of this index if (!(memory = get_block(index))) { if ( show_error ){ PR_DBG(0, "swr_malloc in (%s:%s): No more block of size %i available, " "please allocate!\n", file, func, 1 << index); } return NULL; } memory->size = size; pointer = (void *)memory; pointer += aligned_header_size_; PR_DBG(4, "swr_malloc in (%s:%s): Returning block of size %i, index %i\n", file, func, size, index); // Insert the id at the end *(int*)(pointer + memory->size) = BLOCK_USED; return pointer;}/** * Free a memory block. * * @param address The address of the memory block */int swr_free_func(void *address, char *file, char *func) { mem_header_t *block = 0; if (!address) { PR_DBG(2, "swr_free in (%s:%s): Warning: Pointer to NULL freed, " "hope y'know what you're doing...\n", file, func ); return 0; } block = (mem_header_t *)(address - aligned_header_size_); if (block->index < 0 || block->index >= NBR_BLOCKTYPES) { PR_DBG(0, "swr_free in (%s:%s): index %i not valid: %p!!!\n", file, func, block->index, address); return 1; } if (block->id != BLOCK_USED) { if ( block->id == BLOCK_FREE ) { PR_DBG(0, "swr_free in (%s:%s): This block has already been freed\n", file, func ); } else { PR_DBG(0, "swr_free in (%s:%s): id not valid: %x with pointer %p\n", file, func, block->id, address); } return 1; } if (*(int*)(address + block->size) != BLOCK_USED ) { PR_DBG(0, "swr_free in (%s:%s): overwriting of the block at %p occured!\n", file, func, address ); // BREAKPOINT(); return 1; } *(int*)(address + block->size) = BLOCK_FREE; pthread_mutex_lock(&blocklists[block->index].mutex); block->next = blocklists[block->index].first; block->id = BLOCK_FREE; blocklists[block->index].first = block; blocklists[block->index].blocks_avail++; pthread_mutex_unlock(&blocklists[block->index].mutex); PR_DBG( 4, "swr_free in (%s:%s): Freed block with index %i\n", file, func, block->index ); return 0;}/** * @dumps the memory-blocks */void swr_memory_show(void) { int i; PR_DBG( 2, "swr_memory: available blocks: \n"); for (i = 0; i <= MAX_BLOCK_PWR_2; i++) { if (i > 0 && (i % 4 == 0)) PR_DBG_CL( 2, " / "); PR_DBG_CL( 2, "%i ", blocklists[i].blocks_avail); } PR_DBG_CL( 2, "\n" );}/** * This function is called when the module is loaded */int swr_memory_init(void) { int error; PR_DBG(2, "Software radio memory module (swr_memory.o) loaded\n"); error = check_parameters(); if (error) goto check_parameters_failed; initialize_blocklists_array(); calculate_area_sizes(); error = allocate_physical_mem(); swr_memory_show(); if (error) goto allocate_physical_mem_failed; return 0;allocate_physical_mem_failed: free_physical_mem();check_parameters_failed: PR_DBG(0, "Module unloaded, initialization failed\n"); return 1;}/** * This function is called when the module is unloaded. */void swr_memory_cleanup(void) { free_physical_mem(); PR_DBG(2, "Software radio memory module unloaded\n");}/** * Kernel macros which define the initialization and finalization * function. */module_init(swr_memory_init);module_exit(swr_memory_cleanup);/** * The following symbols are exported: */EXPORT_SYMBOL(swr_malloc_func);EXPORT_SYMBOL(swr_free_func);EXPORT_SYMBOL(swr_memory_show);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -