📄 memblk.cpp
字号:
* Gets a new big block of memory from malloc for use by alloc_mem. **********************************************************************/MEMBLOCK *MEM_ALLOCATOR::new_block( //get new big block INT32 minsize //minimum size ) { MEMBLOCK *newblock; //new block if (blockcount >= MAXBLOCKS) { //can't have another NOMOREBLOCKS.error ("mem_new_block", LOG, NULL); return NULL; } if (mem_checkfreq != 0) { tprintf ("\nGetting new block due to request size of %d", minsize * sizeof (MEMUNION)); tprintf (" from %d from %d from %d from %d from %d\n", trace_caller (3), trace_caller (4), trace_caller (5), trace_caller (6), trace_caller (7)); check_mem ("Getting new block", MEMCHECKS); } //get a new one newblock = &memblocks[blockcount++]; while (memsize < minsize) memsize *= 4; //go up in sizes //get a big block newblock->blockstart = (MEMUNION *) malloc (memsize * sizeof (MEMUNION)); if (newblock->blockstart == NULL) { NOMOREMEM.error ("mem_new_block", LOG, NULL); #ifdef __UNIX__ raise(SIGTTOU); //hangup for js #endif return NULL; } //end of block newblock->blockend = newblock->blockstart + memsize; //first free chunk newblock->freechunk = newblock->blockstart; newblock->topchunk = newblock->blockstart; newblock->lowerspace = 0; newblock->upperspace = memsize;//amount available //set pointer newblock->freechunk->size = memsize; newblock->freechunk->owner = 0; newblock->freechunk->age = 0; totalmem += memsize; //total assigned mem if (memsize < maxsize) memsize *= 4; //successively bigger if (currblock == NULL) { newblock->next = newblock; //first block } else { //insert in list newblock->next = currblock->next; currblock->next = newblock; } return newblock; //new block}/********************************************************************** * MEMBLOCK::find_chunk * * Find a chunk within the block which is big enough for the given request **********************************************************************/MEMUNION *MEMBLOCK::find_chunk( //find free chunk INT32 count //size required ) { MEMUNION *chunk; //current chunk INT32 chunksize; //size of free chunk MEMUNION *chunkstart; //start of free chunk INT32 spaceshift; //shift in lowerspace if (upperspace <= lowerspace) { freechunk = blockstart; //restart chunklist upperspace += lowerspace; lowerspace = 0; //correct space counts } chunk = freechunk; //current free chunk if (chunk->size < count) { //big enough? spaceshift = 0; do { while (chunk->size < 0) { //find free chunk chunk -= chunk->size; //skip forward if (chunk == blockend) { chunk = blockstart; //restart block //gone back to start spaceshift = -lowerspace; } if (chunk == freechunk) return chunk; //gone all round & failed } chunkstart = chunk; //start of chunk chunksize = chunk->size;; chunk += chunk->size; while (chunk != blockend //until end && chunk->size > 0) { //or used chunksize += chunk->size;//coalesce free blocks //gone all round if (chunk == freechunk) { //ensure it is at end freechunk += chunk->size; upperspace -= chunk->size; lowerspace += chunk->size; spaceshift -= chunk->size; } if (chunk == topchunk) //got back to end one topchunk = chunkstart; //end one bigger chunk += chunk->size; //get next block } //new big block chunkstart->size = chunksize; if (chunksize < count) spaceshift += chunksize; //skipping free block if (chunk == blockend) { chunk = blockstart; //back to start if (freechunk == blockend) { freechunk = blockstart;//so is freechunk upperspace += lowerspace; lowerspace = 0; spaceshift = 0; } else //so is shift spaceshift = -lowerspace; } } while (chunksize < count && chunk != freechunk); if (chunksize < count) return chunk; //failed lowerspace += spaceshift; //get space counts right upperspace -= spaceshift; freechunk = chunkstart; return chunkstart; //success } return chunk; //easy}#ifdef __UNIX__/********************************************************************** * trace_caller * * Return the return address of the caller at a given depth back. * 0 gives the return address of the caller to trace_caller. * S300 ONLY!! **********************************************************************///#pragma OPTIMIZE OFF /*force link*/void *trace_caller( //trace stack INT32 depth //depth to trace ) { #ifdef hp9000s800 unsigned sp, pc, rp; //registers UWREC rec1; //for unwinder UWREC rec2; sp = (unsigned) (&depth + 9); pc = *(int *) (sp - 20); rp = 0; get_pcspace(&rec1, pc); rec1.cur_frsize = 0xc0; rec1.currlo = pc & ~3; rec1.curdp = 0; rec1.toprp = rp; while (depth > 0) { if (U_get_previous_frame (&rec1, &rec2)) return NULL; rec1.currlo = rec2.currlo; rec1.cur_frsize = rec2.cur_frsize; rec1.cursp = rec2.cursp; rec1.currls = rec2.currls; rec1.curdp = rec2.curdp; depth--; } return (void *) rec1.currlo; #else void *a6; //address register a6 = &depth - 2; while (depth > 0) { a6 = *(void **) a6; //follow chain depth--; } return *((void **) a6 + 1); #endif}//#pragma OPTIMIZE ON#else// Fake procedure for non-UNIXvoid *trace_caller( //trace stack INT32 depth //depth to trace ) { return NULL;}#endif/********************************************************************** * identify_struct_owner * * Get an index into the table of owners of structures. * Implemented very inefficiently, but only a debug tool! **********************************************************************/INT32 identify_struct_owner( //get table index INT32 struct_count, //cell size const char *name //name of type ) { INT32 index; //index to structure for (index = 0; index < name_counts[struct_count] && strcmp (name, owner_names[struct_count][index]); index++); if (index < MAX_CLASSES) { if (index == name_counts[struct_count]) { name_counts[struct_count]++; owner_names[struct_count][index] = name; owner_counts[struct_count][index] = 0; } } return index;}/********************************************************************** * check_struct * * Check a particular structure size for consistency. **********************************************************************/void check_struct( //check a structure INT8 level, //print control INT32 count //no of bytes ) { MEMUNION *element; //current element MEMUNION *block; //current block INT32 struct_count; //no of required structs INT32 block_count; //no of structure blocks INT32 free_count; //size of freelist*/ INT32 name_index; //named holder INT32 named_total; //total held by names //no of MEMUNIONS-1 struct_count = (count - 1) / sizeof (MEMUNION); if (struct_count < 0 || struct_count >= MAX_STRUCTS) //request too big MEMTOOBIG.error ("check_struct", ABORT, "%d", (int) count); free_count = 0; //size of freelist //count blocks for (block_count = 0, block = struct_blocks[struct_count]; block != NULL; block = block->ptr, block_count++); if (block_count > 0) { //scan freelist for (element = free_structs[struct_count]; element != NULL; element = element->ptr) free_count++; if (level >= MEMCHECKS) { tprintf ("No of structs of size %d in use=%d,", (int) count, (int) structs_in_use[struct_count]); tprintf (" %d free", free_count); tprintf (" in %d blocks, total space=%d\n", (int) block_count, block_count * STRUCT_BLOCK_SIZE * sizeof (MEMUNION)); for (named_total = 0, name_index = 0; name_index < name_counts[struct_count]; name_index++) { tprintf ("No held by %s=%d\n", owner_names[struct_count][name_index], owner_counts[struct_count][name_index]); named_total += owner_counts[struct_count][name_index]; } tprintf ("Total held by names=%d\n", named_total); } } if (structs_in_use[struct_count] + free_count != block_count * (STRUCT_BLOCK_SIZE / (struct_count + 1) - 1)) BADSTRUCTCOUNT.error ("check_struct", ABORT, "%d+%d=%d", structs_in_use[struct_count], free_count, block_count * (STRUCT_BLOCK_SIZE / (struct_count + 1) - 1));}/********************************************************************** * check_structs * * Reports statistics on each maintained structure type by calling * free_struct(NULL) on each. Only active structure types are reported. **********************************************************************/void check_structs( //count in use on structs INT8 level //print control ) { INT8 index; //index to structs for (index = 1; index <= MAX_STRUCTS; index++) //check number allocated check_struct (level, index * sizeof (MEMUNION));}/********************************************************************** * new_struct_block * * Allocate space for a new block of structures. The space is obtained * from alloc_mem, and a freelist of such blocks is maintained for when * the individual structure types get completely freed. **********************************************************************/void *new_struct_block() { //allocate memory MEMUNION *element; //current element MEMUNION *returnelement; //return value returnelement = free_block; if (returnelement == NULL) { //need a new block element = (MEMUNION *) alloc_mem_p (STRUCT_BLOCK_SIZE * sizeof (MEMUNION)); if (element == NULL) return NULL; //can't get more returnelement = element; //going to return 1st } else { //new free one free_block = returnelement->ptr; } return returnelement; //free cell}/********************************************************************** * old_struct_block * * Free memory allocated by new_struct_block. The block is returned * to a freelist ready for a new call to new_struct_block. * This saves confusion over freeing "permanent" blocks, yet * allows them to be recycled for different structures. **********************************************************************/void old_struct_block( //free a structure block MEMUNION *deadblock //block to free ) { if (deadblock != NULL) { deadblock->ptr = free_block; //add to freelist free_block = deadblock; free_struct_blocks++; } if (free_struct_blocks > MAX_FREE_S_BLOCKS) { MEMUNION *next_block; //next in list deadblock = free_block; do { next_block = deadblock->ptr; free_mem(deadblock); //really free it deadblock = next_block; } while (deadblock != NULL); free_struct_blocks = 0; free_block = NULL; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -