void KHeap::install(uint32_t start, const uint32_t &end, const uint32_t &max, const bool &supervisor, const bool &readonly) { index=new Ordered_array<header_t*>( (void*)(start), KHEAP_INDEX_SIZE ); //// index=(Ordered_array<header_t*>*)( kmalloc( sizeof(index) ) ); //// index->init( (void*)(start), KHEAP_INDEX_SIZE ); // heap_t *heap = (heap_t*)( kmalloc(sizeof(heap_t)) ); // All our assumptions are made on startAddress and endAddress being page-aligned. ASSERT(start%0x1000 == 0); ASSERT(end_address()%0x1000 == 0); // Initialise the index. // heap->index = place_ordered_array( (void*)start, HEAP_INDEX_SIZE, &header_t_less_than); // Shift the start address forward to resemble where we can start putting data. // start += sizeof(type_t)*HEAP_INDEX_SIZE; start += index->abs_size(); // Make sure the start address is page-aligned. if( (start&0xFFFFF000)!=0 ) { start &= 0xFFFFF000; start += 0x1000; } // Write the start, end and max addresses into the heap structure. start_address(start); end_address(end); max_address(max); this->supervisor(supervisor); this->readonly(readonly); // We start off with one large hole in the index. header_t *hole=(header_t *)(start); hole->size=end_address()-start_address(); hole->magic=KHEAP_MAGIC; hole->is_hole=true; /* kprintf("FREEEEEEEE!!! header->magic=%p\n",hole->magic); kprintf("FREEEEEEEE! header->size=%u\n",hole->size); kprintf("FREEEEEEEE! header=%p\n",hole); */ index->insert(hole); kheap_kfree_handler=this; kfree_set_handler(kheap_kfree); kheap_kmalloc_handler=this; kmalloc_set_handler(kheap_kmalloc); paging.current_directory=paging.clone_directory(paging.kernel_directory); paging.switch_page_directory(paging.current_directory); // kprintf("Sai!!!\n"); // halt_machine(); }
uint32_t KHeap::contract(uint32_t new_size) { // Sanity check. ASSERT( new_size<end_address()-start_address()); // Get the nearest following page boundary. if( new_size&0x1000 ) { new_size&=0x1000; new_size+=0x1000; } // Don't contract too far! if( new_size<KHEAP_MIN_SIZE ) { new_size = KHEAP_MIN_SIZE; } uint32_t old_size=end_address()-start_address(); uint32_t i=old_size-0x1000; while( new_size<i ) { paging.free_frame( paging.get_page(start_address()+i, false, paging.kernel_directory) ); i -= 0x1000; } end_address( start_address()+new_size ); return new_size; }
void KHeap::expand( uint32_t new_size ) { // Sanity check. ASSERT(new_size>end_address()-start_address()); // Get the nearest following page boundary. if( (new_size&0xFFFFF000)!=0 ) { new_size &= 0xFFFFF000; new_size += 0x1000; } // Make sure we are not overreaching ourselves. ASSERT( start_address()+new_size<=max_address()); // This should always be on a page boundary. uint32_t old_size=end_address()-start_address(); uint32_t i=old_size; while( i<new_size ) { paging.alloc_frame( paging.get_page(start_address()+i, true, paging.kernel_directory), supervisor(), !readonly() ); i += 0x1000 /* page size */; } end_address( start_address()+new_size ); }
//***************************************************************************** // Keep executing instructions until there are other tasks to do (i.e. gCPUState.GetStuffToDo() is set) // Process these tasks and loop //***************************************************************************** template < bool DynaRec, bool TraceEnabled > void CPU_Go() { DAEDALUS_PROFILE( __FUNCTION__ ); while (CPU_KeepRunning()) { // // Keep executing ops as long as there's nothing to do // u32 stuff_to_do( gCPUState.GetStuffToDo() ); while(stuff_to_do == 0) { CPU_EXECUTE_OP< TraceEnabled >(); stuff_to_do = gCPUState.GetStuffToDo(); } if( TraceEnabled && (stuff_to_do != CPU_CHANGE_CORE) ) { if(gTraceRecorder.IsTraceActive()) { #ifdef DAEDALUS_DEBUG_DYNAREC u32 start_address( gTraceRecorder.GetStartTraceAddress() ); //DBGConsole_Msg( 0, "Aborting tracing of [R%08x] - StuffToDo is %08x", start_address, stuff_to_do ); gAbortedTraceReasons[ start_address ] = stuff_to_do; #endif #ifdef ALLOW_TRACES_WHICH_EXCEPT if(stuff_to_do == CPU_CHECK_INTERRUPTS && gCPUState.Delay == NO_DELAY ) // Note checking for exactly equal, not just that it's set { //DBGConsole_Msg( 0, "Adding chunk at %08x after interrupt\n", gTraceRecorder.GetStartTraceAddress() ); gTraceRecorder.StopTrace( gCPUState.CurrentPC ); CPU_CreateAndAddFragment(); } #endif gTraceRecorder.AbortTrace(); // Abort any traces that were terminated through an interrupt etc } CPU_SelectCore(); } if (CPU_CheckStuffToDo()) break; } }
void *KHeap::alloc(uint32_t size, const bool &page_align) { // Make sure we take the size of header/footer into account. uint32_t new_size = size + sizeof(header_t) + sizeof(footer_t); // Find the smallest hole that will fit. uint32_t iterator = find_smallest_hole(new_size, page_align); if( iterator==(uint32_t)(-1) ) { // If we didn't find a suitable hole // Save some previous data. uint32_t old_length=end_address()-start_address(); uint32_t old_end_address=end_address(); // We need to allocate some more space. expand(old_length+new_size); uint32_t new_length=end_address()-start_address(); // Find the endmost header. (Not endmost in size, but in location). iterator=0; // Vars to hold the index of, and value of, the endmost header found so far. uint32_t idx=-1; uint32_t value = 0x0; while( iterator<index->size() ) { uint32_t tmp=(uint32_t)( (*index)[iterator] ); if( tmp>value ) { value=tmp; idx=iterator; } ++iterator; } // If we didn't find ANY headers, we need to add one. if( idx==(uint32_t)(-1) ) { header_t *header=(header_t*)(old_end_address); header->magic=KHEAP_MAGIC; header->size=new_length-old_length; header->is_hole=true; footer_t *footer=(footer_t *)(old_end_address+header->size-sizeof(footer_t)); footer->magic=KHEAP_MAGIC; footer->header=header; /* kprintf("FREEEEEEEE! header->magic=%p\n",header->magic); kprintf("FREEEEEEEE! header->size=%u\n",header->size); kprintf("FREEEEEEEE! header=%p\n",header);*/ index->insert( header ); } else { // The last header needs adjusting. header_t *header=(*index)[idx]; header->size+=new_length-old_length; // Rewrite the footer. footer_t *footer=(footer_t*)( (uint32_t)header+header->size-sizeof(footer_t) ); footer->header=header; footer->magic=KHEAP_MAGIC; } // We now have enough space. Recurse, and call the function again. return alloc(size, page_align); } header_t *orig_hole_header=(*index)[iterator]; uint32_t orig_hole_pos=(uint32_t)orig_hole_header; uint32_t orig_hole_size=orig_hole_header->size; // Here we work out if we should split the hole we found into two parts. // Is the original hole size - requested hole size less than the overhead for adding a new hole? if( orig_hole_size-new_size<sizeof(header_t)+sizeof(footer_t) ) { // Then just increase the requested size to the size of the hole we found. size += orig_hole_size-new_size; new_size = orig_hole_size; } // If we need to page-align the data, do it now and make a new hole in front of our block. if( page_align && orig_hole_pos&0xFFFFF000 ) { uint32_t new_location = orig_hole_pos+0x1000 /* page size */ - (orig_hole_pos&0xFFF) - sizeof(header_t); header_t *hole_header = (header_t *)orig_hole_pos; hole_header->size = 0x1000 /* page size */ - (orig_hole_pos&0xFFF) - sizeof(header_t); hole_header->magic = KHEAP_MAGIC; hole_header->is_hole = 1; footer_t *hole_footer = (footer_t *) ( (uint32_t)new_location - sizeof(footer_t) ); hole_footer->magic = KHEAP_MAGIC; hole_footer->header = hole_header; orig_hole_pos = new_location; orig_hole_size = orig_hole_size - hole_header->size; } else { // Else we don't need this hole any more, delete it from the index. index->remove(iterator); } // Overwrite the original header... header_t *block_header = (header_t*)orig_hole_pos; block_header->magic = KHEAP_MAGIC; block_header->is_hole = 0; block_header->size = new_size; // ...And the footer footer_t *block_footer = (footer_t *) (orig_hole_pos + sizeof(header_t) + size); block_footer->magic = KHEAP_MAGIC; block_footer->header = block_header; // We may need to write a new hole after the allocated block. // We do this only if the new hole would have positive size... if( orig_hole_size-new_size>0 ) { header_t *hole_header = (header_t *) (orig_hole_pos + sizeof(header_t) + size + sizeof(footer_t)); hole_header->magic = KHEAP_MAGIC; hole_header->is_hole = 1; hole_header->size = orig_hole_size - new_size; footer_t *hole_footer = (footer_t *) ( (uint32_t)hole_header + orig_hole_size - new_size - sizeof(footer_t) ); if( (uint32_t)hole_footer<end_address() ) { hole_footer->magic = KHEAP_MAGIC; hole_footer->header = hole_header; } // Put the new hole in the index; /* kprintf("FREEEEEEEE! header->magic=%p\n",hole_header->magic); kprintf("FREEEEEEEE! header->size=%u\n",hole_header->size); kprintf("FREEEEEEEE! header=%p\n",hole_header);*/ index->insert(hole_header); } // ...And we're done! return (void*)( (uint32_t)block_header+sizeof(header_t) ); }