unsigned VMShrink() { int i; int j; unsigned kill_time; unsigned kill_i; unsigned kill_j; virt_page *pg; imp_image_handle *ii; kill_time = UINT_MAX; kill_i = 0; kill_j = 0; for( ii = ImageList; ii != NULL; ii = ii->next_image ) { if( ii->virt != NULL ) { for( i = ii->vm_dir_num-1; i >= 0; --i ) { if( ii->virt[i] != NULL ) { for( j = DIR_SIZE-1; j >= 0; --j ) { pg = ii->virt[i][j]; if( pg != NULL && pg->offset == 0 ) { if( kill_time > pg->block->time_stamp ) { kill_time = pg->block->time_stamp; kill_i = i; kill_j = j; } } } } } } } if( kill_time == UINT_MAX ) return( 0 ); return( KillPages( ii, kill_i, kill_j ) ); }
unsigned VMShrink( void ) { int i; int j; unsigned kill_time; unsigned kill_i; unsigned kill_j; virt_page *pg; imp_image_handle *iih; imp_image_handle *kill_iih; kill_time = UINT_MAX; kill_i = 0; kill_j = 0; kill_iih = NULL; /* search oldest page by time_stamp */ for( iih = ImageList; iih != NULL; iih = iih->next_image ) { if( iih->virt != NULL ) { for( i = iih->vm_dir_num-1; i >= 0; --i ) { if( iih->virt[i] != NULL ) { for( j = DIR_SIZE-1; j >= 0; --j ) { pg = iih->virt[i][j]; if( pg != NULL && pg->offset == 0 ) { if( kill_time > pg->block->time_stamp ) { kill_time = pg->block->time_stamp; kill_i = i; kill_j = j; kill_iih = iih; } } } } } } } if( kill_iih == NULL ) return( 0 ); return( KillPages( kill_iih, kill_i, kill_j ) ); }
void *VMBlock( imp_image_handle *iih, virt_mem start, size_t len ) { unsigned dir_idx; unsigned pg_idx; unsigned tmp_idx; unsigned i; unsigned j; unsigned num_pages; virt_mem pg_start; virt_page *pg; virt_page *zero; loaded_block *block; dir_idx = GET_DIR( start ); if( iih->virt[dir_idx] == NULL ) { if( !InitPageDir( iih, dir_idx ) ) { return( NULL ); } } pg_idx = GET_PAGE( start ); len += start % VM_PAGE_SIZE; pg_start = start & ~(virt_mem)(VM_PAGE_SIZE - 1); pg = iih->virt[dir_idx][pg_idx]; if( pg == NULL || ( pg->block->len - pg->offset ) < len ) { /* unloaded previously loaded block */ if( pg != NULL ) { tmp_idx = dir_idx; /* find first page of the block */ i = pg_idx; for( ;; ) { iih->virt[tmp_idx][i] = NULL; if( pg->offset == 0 ) break; if( i == 0 ) { --tmp_idx; i = DIR_SIZE; } --i; --pg; } DCFree( pg ); } num_pages = BLOCK_FACTOR( len, VM_PAGE_SIZE ); pg = DCAlloc( num_pages * ( sizeof( *pg ) + VM_PAGE_SIZE ) + sizeof( loaded_block ) - 1 ); if( pg == NULL ) { DCStatus( DS_ERR | DS_NO_MEM ); return( NULL ); } /* set up new page table entries */ block = (loaded_block *)&pg[num_pages]; tmp_idx = dir_idx; for( j = pg_idx, i = 0; i < num_pages; ++j, ++i ) { pg[i].block = block; pg[i].offset = i * VM_PAGE_SIZE; if( j >= DIR_SIZE ) { ++tmp_idx; j = 0; } if( iih->virt[tmp_idx] == NULL ) { if( !InitPageDir( iih, tmp_idx ) ) { /* unwind the setup already done */ num_pages = i; for( i = 0; i < num_pages; ++i, ++pg_idx ) { if( pg_idx >= DIR_SIZE ) { ++dir_idx; pg_idx = 0; } iih->virt[dir_idx][pg_idx] = NULL; } DCFree( pg ); return( NULL ); } } if( iih->virt[tmp_idx][j] != NULL ) { /* We just ran into another allocated block, so we have to kill all the pages mapped in by it. We know that if the page pointer is non-NULL, it will be offset==0 since KillPages will clean out the others. */ KillPages( iih, tmp_idx, j ); } iih->virt[tmp_idx][j] = &pg[i]; } /* read in new block */ len = num_pages * VM_PAGE_SIZE; block->len = len; pg_start += iih->bias; if( DCSeek( iih->sym_fp, pg_start, DIG_ORG ) ) { DCStatus( DS_ERR | DS_FSEEK_FAILED ); return( NULL ); } /* last block might be a short read */ if( DCRead( iih->sym_fp, pg->block->data, len ) == DIG_RW_ERROR ) { DCStatus( DS_ERR | DS_FREAD_FAILED ); return( NULL ); } pg = iih->virt[dir_idx][pg_idx]; } ++TimeStamp; if( TimeStamp == 0 ) { /* deal with wrap-around */ for( iih = ImageList; iih != NULL; iih = iih->next_image ) { if( iih->virt != NULL ) { for( i = iih->vm_dir_num; i-- > 0; ) { if( iih->virt[i] != NULL ) { for( j = DIR_SIZE; j-- > 0; ) { zero = iih->virt[i][j]; if( zero != NULL ) { zero->block->time_stamp = 0; } } } } } } ++TimeStamp; } pg->block->time_stamp = TimeStamp; return( &pg->block->data[(start & (VM_PAGE_SIZE - 1)) + pg->offset] ); }