⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 malloc.c

📁 嵌入式操作系统内核
💻 C
📖 第 1 页 / 共 2 页
字号:
#endif  old_owner =  blockptr->blockhdr.owner;  // Set the new block ID                                        blockptr->blockhdr.owner = id;          //ker_log( SOS_LOG_CHANGE_OWN, id, old_owner);    return SOS_OK;}void mem_start() {  // sched_register_kernel_module(&malloc_module, sos_get_header_address(mod_header), NULL);}int8_t mem_remove_all(sos_pid_t id){  HAS_CRITICAL_SECTION;  Block* block = (Block*)malloc_heap;  ENTER_CRITICAL_SECTION();  for (block = (Block*)malloc_heap;        block != mSentinel;        block += block->blockhdr.blocks & ~RESERVED)     {      if ((block->blockhdr.blocks & RESERVED) && 	  (block->blockhdr.owner == id)){	ker_free(block->userPart);      }		    }  //printMem("remove_all_end: ");  LEAVE_CRITICAL_SECTION();  return SOS_OK;}//-----------------------------------------------------------------------------// Re-allocate the buffer to a new area the requested size. If possible the// existing area is simply expanded. Otherwise a new area is allocated and// the current contents copied.// SFI Mode: 1. If call from untrusted domain, only owner is allowed to realloc//-----------------------------------------------------------------------------void* sos_blk_mem_realloc(void* pntr, uint16_t newSize, bool bCallFromModule){  HAS_CRITICAL_SECTION;  sos_pid_t id;#ifdef SOS_SFI  uint16_t block_num;  uint8_t perms;    uint16_t oldSize;  int8_t domid;#endif  // Check for errors.  //  if ( (pntr == NULL ) || (newSize == 0) ) return pntr;#ifdef SOS_SFI  ENTER_CRITICAL_SECTION();  // Get the permission of the first block  block_num = MEMMAP_GET_BLK_NUM(pntr);  MEMMAP_GET_PERMS(block_num, perms);#ifdef SFI_DOMS_8  if ((bCallFromModule) && ((perms & MEMMAP_DOM_MASK) != curr_dom_id))#endif#ifdef SFI_DOMS_2  if ((bCallFromModule) && ((perms & MEMMAP_DOM_MASK) == KER_DOM_ID))#endif    {      LEAVE_CRITICAL_SECTION();      sfi_exception(MALLOC_EXCEPTION);      // Error - Untrusted domain trying to realloc memory that it does not own or that is free.    }  domid = perms & MEMMAP_DOM_MASK;  LEAVE_CRITICAL_SECTION();#endif  Block* block = TO_BLOCK_PTR(pntr);   // convert user to block address  uint16_t reqBlocks = (newSize + BLOCKOVERHEAD + sizeof(Block) - 1) >> SHIFT_VALUE;  ENTER_CRITICAL_SECTION();  id = block->blockhdr.owner;  block->blockhdr.blocks &= ~RESERVED;         // expose the size#ifdef SOS_SFI  oldSize = BLOCKS_TO_BYTES(block->blockhdr.blocks);#endif  // The fastest option is to merge this block with any free blocks  // that are contiguous with this block.  //  block = MergeBlocks(block);  if (block->blockhdr.blocks > reqBlocks)    {      // The merge produced a larger block than required, so split it      // into two blocks. This also takes care of the case where the      // new size is less than the old.      //      SplitBlock(block, reqBlocks);#ifdef SOS_SFI      if (reqBlocks < oldSize){	memmap_set_perms((Block*)(block + reqBlocks), 			 (oldSize - reqBlocks)*(sizeof(Block)), 			 MEMMAP_SEG_START|BLOCK_FREE);      }      else{	memmap_set_perms((Block*)(block + oldSize),			   (reqBlocks - oldSize)*(sizeof(Block)), 			   DOM_SEG_LATER(domid));      }#endif          }  else if (block->blockhdr.blocks < reqBlocks)    {      // Could not expand this block. Must attempt to allocate      // a new one the correct size and copy the current contents.      //#ifndef SOS_SFI      uint16_t oldSize = BLOCKS_TO_BYTES(block->blockhdr.blocks);#endif      block = (Block*)ker_malloc(newSize, id);      if (NULL != block)        {	  // A new block large enough has been allocated. Copy the	  // existing data and then discard the old block.	  //	  block = TO_BLOCK_PTR(block);	  memcpy(block->userPart, (Block*)(TO_BLOCK_PTR(pntr))->userPart, oldSize);	  sos_blk_mem_free(pntr, bCallFromModule);        }      else        {	  // Cannot re-allocate this block. Note the old pointer	  // is still valid.	  //	  LEAVE_CRITICAL_SECTION();	  return NULL;        // no valid options        }    }#ifdef SOS_SFI  else if (block->blockhdr.blocks == reqBlocks)    {      memmap_set_perms((Block*)(block + oldSize), 		       (reqBlocks - oldSize)*(sizeof(Block)), 		       DOM_SEG_LATER(domid));    }#endif  block->blockhdr.blocks |= RESERVED;  block->blockhdr.owner = id;#ifndef SOS_SFI                                  BLOCK_GUARD_BYTE(block) = id; #endif  LEAVE_CRITICAL_SECTION();  return block->userPart;}//-----------------------------------------------------------------------------// Compute the number of blocks that will fit in the memory area defined.// Allocate the pool of blocks. Note this includes the sentinel area that is // attached to the end and is always only one block. The first entry in the // free list pool is set to include all available blocks. The sentinel is // initialised to point back to the start of the pool.//void mem_init(void){  Block* head;  char* heapStart = (char*)malloc_heap; //&__heap_start;  char* heapEnd = (char*)(((char*)malloc_heap) + MALLOC_HEAP_SIZE);//&__heap_end;  DEBUG("malloc init\n");  mPool = (Block*)heapStart;  mNumberOfBlocks = (uint16_t)(((heapEnd - (char*)mPool) >> SHIFT_VALUE) - 1L);  mSentinel = mPool + mNumberOfBlocks;  mSentinel->blockhdr.blocks = RESERVED;           // now cannot be used  mSentinel->prev = mSentinel;  mSentinel->next = mSentinel;  // Entire pool is initially a single unallocated area.  //  head = &mPool[0];  head->blockhdr.blocks = mNumberOfBlocks;         // initially all of free memeory  InsertAfter(head);                      // link the sentinel#ifdef SOS_SFI  memmap_init(); // Initialize all the memory to be owned by the kernel  memmap_set_perms((void*) mPool, mNumberOfBlocks * sizeof(Block), MEMMAP_SEG_START|BLOCK_FREE); // Init heap to unallocated#endif}//-----------------------------------------------------------------------------// As each area is examined for a fit, we also examine the following area. // If it is free then it must also be on the Free list. Being a doubly-linked // list, we can combine these two areas in constant time. If an area is // combined, the procedure then looks again at the following area, thus // repeatedly combining areas until a reserved area is found. In terminal // cases this will be the sentinel block.//static Block* MergeBlocks(Block* block){  while (TRUE)    {      Block* successor = block + block->blockhdr.blocks;   // point to next area      /*	DEBUG("block = %x, blocks = %d, successor = %x, alloc = %d\n",	(unsigned int)block,	block->blockhdr.blocks,	(unsigned int) successor,	successor->blockhdr.blocks);      */      if (successor->blockhdr.blocks & RESERVED)           // done if reserved        {	  return block;        }      Unlink(successor);      block->blockhdr.blocks += successor->blockhdr.blocks;         // add in its blocks    }}static Block* MergeBlocksQuick(Block *block, uint16_t req_blocks){  while (TRUE)    {      Block* successor = block + block->blockhdr.blocks;   // point to next area      if (successor->blockhdr.blocks & RESERVED)           // done if reserved	{	  return block;	}      Unlink(successor);      block->blockhdr.blocks += successor->blockhdr.blocks;         // add in its blocks      if( block->blockhdr.blocks >= req_blocks ) {	return block;      }    }}//-----------------------------------------------------------------------------//static void SplitBlock(Block* block, uint16_t reqBlocks)  {  Block* newBlock = block + reqBlocks;            // create a remainder area  newBlock->blockhdr.blocks = block->blockhdr.blocks - reqBlocks;   // set its size and mark as free  block->blockhdr.blocks = reqBlocks;                      // set us to requested size  InsertAfter(newBlock);                          // stitch remainder into free list}    //-----------------------------------------------------------------------------//static void InsertAfter(Block* block){  Block* p = mSentinel->next;  mSentinel->next = block;  block->prev = mSentinel;  block->next = p;  p->prev = block;}//-----------------------------------------------------------------------------//static void Unlink(Block* block){  block->prev->next = block->next;  block->next->prev = block->prev;}#if 0static inline void mem_defrag(){  HAS_CRITICAL_SECTION;  Block* block;  ENTER_CRITICAL_SECTION();  printMem("before defrag\n");  for (block = mSentinel->next; block != mSentinel; block = block->next)    {      block = MergeBlocks(block);    }  printMem("after defrag\n");  LEAVE_CRITICAL_SECTION();}static int8_t mem_handler(void *state, Message *msg){  switch(msg->type){  case MSG_TIMER_TIMEOUT:    {      mem_defrag();      break;    }  case MSG_INIT:    {      ker_timer_init(KER_MEM_PID, 0, TIMER_REPEAT);      ker_timer_start(KER_MEM_PID, 0, 10 * 1024L);      break;    }  case MSG_DEBUG:    {      break;    }  default:    return -EINVAL;  }  return SOS_OK;}#endif /* #if 0 */#if 0static void verify_memory( void ){  Block* block;  block = (Block*)malloc_heap;  Block* next_block;  while(block != mSentinel) {    next_block = block + (block->blockhdr.blocks & ~RESERVED);    if( block->blockhdr.blocks & RESERVED ) {      if( block->blockhdr.owner != BLOCK_GUARD_BYTE(block) ) {	ker_led(LED_RED_TOGGLE);	return;      }    }    if( next_block != mSentinel) {      if( (next_block->blockhdr.blocks & ~RESERVED) > ((MALLOC_HEAP_SIZE + (BLOCK_SIZE - 1))/BLOCK_SIZE) ) {	ker_led(LED_GREEN_TOGGLE);	ker_led(LED_RED_TOGGLE);	return;      }	    }    block = next_block;  }}#endif#ifdef SOS_DEBUG_MALLOC#ifndef SOS_SFIstatic void printMem(char* s){  Block* block;  int i = 0;  DEBUG("%s\n", s);  for (block = mSentinel->next; block != mSentinel; block = block->next)    {      /*	if(block->blockhdr.owner != BLOCK_GUARD_BYTE(block)) {	DEBUG("detect memory corruption in PrintMem\n");	DEBUG("possible owner %d %d\n", block->blockhdr.owner, BLOCK_GUARD_BYTE(block));	} else {      */      DEBUG("block %d : block: %x, prev : %x, next : %x, blocks : %d\n", i,	    (unsigned int) block, 	    (unsigned int) block->prev, 	    (unsigned int) block->next, 	    (unsigned int) block->blockhdr.blocks);	      //}      i++;    }  DEBUG("Memory Map:\n");  block = (Block*)malloc_heap;  i = 0;  while(block != mSentinel) {    DEBUG("block %d : addr: %x size: %d alloc: %d owner: %d check %d\n", i++, 	  (unsigned int) block, 	  (unsigned int) (block->blockhdr.blocks & ~RESERVED), 	  (unsigned int) (block->blockhdr.blocks & RESERVED), 	  (unsigned int) block->blockhdr.owner,	  (unsigned int) BLOCK_GUARD_BYTE(block));    block += block->blockhdr.blocks & ~RESERVED;  }}#elsestatic void printMem(char* s){  Block* block;  int i = 0;  DEBUG("%s\n", s);  for (block = mSentinel->next; block != mSentinel; block = block->next){    DEBUG("Block %d : Addr: %x, Prev : %x, Next : %x, Blocks : %d\n", i++, (uint32_t)block, (uint32_t)block->prev, (uint32_t)block->next, block->blockhdr.blocks);	  }  DEBUG("Memory Map:\n");  block = (Block*)malloc_heap;  i = 0;  while(block != mSentinel) {    DEBUG("block %d : Addr: %x size: %d alloc: %d owner: %d\n", i++, (uint32_t)block, block->blockhdr.blocks & ~RESERVED, block->blockhdr.blocks & RESERVED, block->blockhdr.owner);    block += block->blockhdr.blocks & ~RESERVED;  }}#endif // SOS_SFI#endif/** * Use by SYS API to notify module's panic */int8_t ker_mod_panic(sos_pid_t pid){	  return ker_panic();}/** * Used by the kernel to notify kernel component panic */int8_t ker_panic(void){  uint16_t val;  LED_DBG(LED_RED_ON);  LED_DBG(LED_GREEN_ON);  LED_DBG(LED_YELLOW_ON);  val = 0xffff;  while (1){#ifndef DISABLE_WDT    watchdog_reset();#endif    if (val == 0){      LED_DBG(LED_RED_TOGGLE);      LED_DBG(LED_GREEN_TOGGLE);      LED_DBG(LED_YELLOW_TOGGLE);#ifdef SOS_SIM      DEBUG("Malloc_Exception");#endif    }    val--;  }  return -EINVAL;	}void* ker_sys_malloc(uint16_t size){      sos_pid_t my_id = ker_get_current_pid();      void *ret = sos_blk_mem_alloc(size, my_id, true);      if( ret != NULL ) {            return ret;      }      ker_mod_panic(my_id);      return NULL;}void* ker_sys_realloc(void* pntr, uint16_t newSize){  void *ret = sos_blk_mem_realloc(pntr, newSize, true);  if( ret != NULL ) {    return ret;  }  ker_mod_panic(ker_get_current_pid());  return NULL;}void ker_sys_free(void *pntr) {  sos_blk_mem_free(pntr, true);}	int8_t ker_sys_change_own( void* ptr ){  sos_pid_t my_id = ker_get_current_pid();      if( SOS_OK != sos_blk_mem_change_own( ptr, my_id, true ) ) {	ker_mod_panic(my_id);  }  return SOS_OK;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -