350 likes | 424 Views
Go’LegOS. Alternative Memory Management Schemes for LegOS Project. Hao Ji Yanhao Zhu Gowri Mereddy. Problem Statement.
E N D
Go’LegOS Alternative Memory Management Schemes for LegOS Project Hao Ji Yanhao Zhu Gowri Mereddy
Problem Statement • To introduces a new system call mm_algorithm_used() to allow the user to select the type of memory management required depending up to the type of user programs in order to have efficient memory management.
The Basic memory block The unit of the memory is 2 byte word 4 bytes Head Consisting of Process ID and Size Size indicating the length of Data Field
Current Mechanism • Straightforward continuous allocation scheme • No advanced memory schemes (which imply more overheads) • The kernel code and the kernel data starts at the location 0x8000 up to the global variable mm_start ( User memory space) • The user memory starts from mm_start to 0xFFFF.
The Technique that is currently implemented is First fit. (i.e the first enough free block for The alternative schemes to be implemented is the process) • The function mm_try_join takes the address of a free memory blocks as the parameters and merges with the following free memory blocks. • The merging requires locking of the mm_semophore to stop the other process requesting memory space in multitasking mode
Techniques • BEST FIT: The Memory is searched from the mm_start till the end to find a free memory which is of the nearest size to the required size. This type of technique leads to minimize external fragmention,but may lead to lot of internal fragmentations. • WORST FIT: The memory is searched to find the biggest whole available and the split into two parts so that the other process can use the space. May be a solution to internal fragmentation.
NEXT FIT: The alteration of the First fit is the next fit. Never it finds the hole it stores the location, and when requested for allocation starts allocating from that position
Files modified: • stdlib.h • declare function mm_algorithm_used as an extern function. • declare function mm_scan as extern function • mm.c • Added #define FIRST_FIT 0, #define NEXT_FIT 1, #define BEST_FIT 2, #define WORST_FIT 3 • Added kernel variable mm_policy, which remember which algorithm should be used. During kernel startup, it is initialized to FIRST_FIT. • Added kernel variable mm_next_free, which always points to the next free block during the search. It is initialized to &mm_start at the very beginning. • Add function mm_algorithm_used(int a) as following:
void mm_algorithm_used(unsigned short policy){ • if(policy < FIRST_FIT || policy > WORST_FIT) return ; • #ifdef CONF_TM • sem_wait(&mm_semaphore); • #endif • /* • if current policy is not NEXT_FIT and we want to change it to NEXT_FIT, • we need to change the pointer mm_next_free to point to mm_first_free • */ • if (policy == NEXT_FIT ) • if (mm_policy !=NEXT_FIT) mm_next_free = mm_first_free; • mm_policy = policy; • #ifdef CONF_TM • sem_post(&mm_semaphore); • #endif • }
-Modified malloc function • void *malloc(size_t size){ if (mm_policy == FIRST_FIT) return malloc_first_fit(size); If (mm_policy == NEXT_FIT) return malloc_next_fit(size); if (mm_policy == BEST_FIT) return malloc_best_fit(size); if (mm_policy == WORST_FIT) return malloc_worst_fit(size); } malloc() malloc_first_fit() malloc_next_fit() malloc_best_fit() malloc_worst_fit()
Add function malloc_next_fit() as following • This algorithm search the free memory block from mm_next_free, which is the pointer pointing to the next free block. If it found one suitable free block, it will put the new block there. If the free block size is bigger than request size plus MM_SPLIT_THRESH (MM_HEADER_SIZE+8), the block will be split. If memory block allocation is succeed, the pointer, mm_next_free, is updated to the addres of next free block if there is one. Otherwise, mm_next_free is reset to &mm_start
void *malloc_next_fit(size_t size) { • size_t *ptr,*next; • size=(size+1)>>1; // only multiples of 2 • #ifdef CONF_TM • sem_wait(&mm_semaphore); // tasksafe • #endif • ptr=mm_next_free; • next = mm_next_free; • while(ptr>=&mm_start) { • if(*(ptr++)==MM_FREE) { // free block? • #ifdef CONF_TM • mm_try_join(ptr); // unite with later blocks • #endif • if(*ptr>=size) { // big enough? • *(ptr-1)=(size_t)cpid; // set owner • // split this block? • if((*ptr-size)>=MM_SPLIT_THRESH) { • next=ptr+size+1; • *(next++)=MM_FREE; • *(next)=*ptr-size-MM_HEADER_SIZE; • mm_try_join(next); • *ptr=size;
next--; • }else • /* move mm_next_free pointer to next available free block*/ • { • next = ptr+MM_HEADER_SIZE+*(ptr)-1; • } • // was it the first free one? • if(ptr==mm_first_free+1) • mm_update_first_free(ptr+*ptr+1); • while(*(next)!=MM_FREE && next >= ptr) • next = next+MM_HEADER_SIZE+*(next+1); • if (next < ptr) next = mm_first_free; • mm_next_free = next; • #ifdef CONF_TM • sem_post(&mm_semaphore); • #endif • return (void*) (ptr+1); • } • } • ptr+=(*ptr)+1; // find next block.
/* in case we didn't find a usable block between mm_next_free and 0xFFFF, • we need to go back from the pointer of mm_first_free to search from the beginning */ • ptr = mm_first_free ; • while(ptr >= mm_first_free && ptr <mm_next_free ){ • if(*(ptr++)==MM_FREE) { // free block? • #ifdef CONF_TM • mm_try_join(ptr); // unite with later blocks • #endif • if(*ptr>=size) { // big enough? • *(ptr-1)=(size_t)cpid; // set owner • // split this block? • if((*ptr-size)>=MM_SPLIT_THRESH) { • next=ptr+size+1; • *(next++)=MM_FREE; • *(next)=*ptr-size-MM_HEADER_SIZE; • mm_try_join(next); • *ptr=size; • }else • /* move mm_next_free pointer to next available free block*/ • { • next = ptr+MM_HEADER_SIZE+*(ptr)-1;
// was it the first free one? • if(ptr==mm_first_free+1) • mm_update_first_free(ptr+*ptr+1); • while(*(next)!=MM_FREE && next >= ptr) • next = next+MM_HEADER_SIZE+*(next+1); • if (next < ptr) next = mm_first_free; • mm_next_free = next; • #ifdef CONF_TM • sem_post(&mm_semaphore); • #endif • return (void*) (ptr+1); • } • } • ptr+=(*ptr)+1; // find next block. • } • #ifdef CONF_TM • sem_post(&mm_semaphore); • #endif • return NULL; • } • //find
Add function malloc_best_fit() as following: • //! allocate a block of memory using Best _fit POLICY • /*! \param size requested block size • \return 0 on error, else pointer to block. • */ • void *malloc_best_fit(size_t size) { • size_t *ptr,*next,*bestptr; • size_t bestsize; • size=(size+1)>>1; // only multiples of 2 • #ifdef CONF_TM • sem_wait(&mm_semaphore); // tasksafe • #endif • ptr=mm_first_free; • bestptr=ptr; • bestsize=0xFFFF; • while(ptr>=&mm_start) { • if(*(ptr++)==MM_FREE) { // free block? • #ifdef CONF_TM
mm_try_join(ptr); // unite with later blocks • #endif • if(*ptr>=size) { // big enough? • if(*ptr<bestsize){ • bestsize=*ptr; • bestptr=ptr-1; • } • } • } • ptr+=(*ptr)+1; // find next block. • } • if (bestsize != 0xFFFF) { • ptr = bestptr +1; • *(ptr-1)=(size_t)cpid; // set owner • // split this block? • if((*ptr-size)>=MM_SPLIT_THRESH) { • next=ptr+size+1; • *(next++)=MM_FREE; • *(next)=*ptr-size-MM_HEADER_SIZE; • mm_try_join(next); • *ptr=size; • } • // was it the first free one?
if(ptr==mm_first_free+1) • mm_update_first_free(ptr+*ptr+1); • #ifdef CONF_TM • sem_post(&mm_semaphore); • #endif • return (void*) (bestptr); • } • #ifdef CONF_TM • sem_post(&mm_semaphore); • #endif • return NULL;
Add function malloc_worst_fit() as following: • //! allocate a block of memory using Worst _fit POLICY • /*! \param size requested block size • \return 0 on error, else pointer to block. • */ • void *malloc_worst_fit(size_t size) { • size_t *ptr,*next,*worstptr; • size_t worstsize; • size=(size+1)>>1; // only multiples of 2 • #ifdef CONF_TM • sem_wait(&mm_semaphore); // tasksafe • #endif • ptr=mm_first_free; • worstptr=ptr; • worstsize=0; • while(ptr>=&mm_start) { • if(*(ptr++)==MM_FREE) { // free block?
while(ptr>=&mm_start) { • if(*(ptr++)==MM_FREE) { // free block? • #ifdef CONF_TM • mm_try_join(ptr); // unite with later blocks • #endif • if(*ptr>=size) { // big enough? • if(*ptr>worstsize){ • worstsize=*ptr; • worstptr=ptr-1; • } • } • } • ptr+=(*ptr)+1; // find next block. • } • if (worstsize != 0) { • ptr = worstptr +1; • *(ptr-1)=(size_t)cpid; // set owner • // split this block? • if((*ptr-size)>=MM_SPLIT_THRESH) { • next=ptr+size+1; • *(next++)=MM_FREE; • *(next)=*ptr-size-MM_HEADER_SIZE; • mm_try_join(next); • *ptr=size; • }
if(ptr==mm_first_free+1) • mm_update_first_free(ptr+*ptr+1); • #ifdef CONF_TM • sem_post(&mm_semaphore); • #endif • return (void*) (worstptr); • } • #ifdef CONF_TM • sem_post(&mm_semaphore); • #endif • return NULL; • }
Testing • (1). First Fit • Testing Program: • mm_algorithm_used(FIRST_FIT); • cputs("malloc0"); • mm_scan(); • sleep(1); • n=(char*)malloc(sizeof(char)*15388); //15388 bytes = 0x1E0E words • m= (char*)malloc(sizeof(char)*160); //160 bytes = 0x50 words • o= (char*)malloc(sizeof(char)*16); //16 bytes = 0x08 words • mm_scan(); • free(n); • free(m); • free(o); • cputs("free0"); • sleep(1); • mm_scan();
(2). Next Fit • Testing program: • mm_algorithm_used(NEXT_FIT); • mm_scan(); • // sleep(1); • n=(char*)malloc(sizeof(char)*15394); //15394 bytes = 0x1E11 words • m= (char*)malloc(sizeof(char)*160);//160 bytes = 0x50 words// • o= (char*)malloc(sizeof(char)*16); //16 bytes = 0x08 words • mm_scan(); • free(n); • free(m); • free(o); • cputs("free1"); • sleep(1); • mm_scan();
(3) Best_FIT • mm_algorithm_used(BEST_FIT); • cputs("malloc2"); • mm_scan(); • sleep(1); • n=(char*)malloc(sizeof(char)*170); //170 bytes = 0x0055 words • m= (char*)malloc(sizeof(char)*8); //8 bytes = 0x0004 words • mm_scan(); • free(n); • cputs("free2"); • sleep(1); • mm_scan();
(4)worst_fit • mm_algorithm_used(3); • cputs("malloc3"); • mm_scan(); • sleep(1); • n=(char*)malloc(sizeof(char)*12878); //12878 bytes = 0x1927 words • m= (char*)malloc(sizeof(char)*1024); //1024 bytes = 0x0200 words • mm_scan(); • free(n); • cputs("free3"); • sleep(1); • mm_scan();
Test Conclusion • We keep the same interface to programmer so that they don’t need to modify any of their source codes .(Seamless hacking) • The new memory allocation mechanism we developed works fine. • LNP may save a lot of test time and be more straightforward. /* we got crazy when pressing the button for hundreds of times to keep record of our testing result. */