free.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include "heap.h"
  2. #ifdef CONFIG_ACTIONS_TRACE
  3. #include <trace.h>
  4. #endif
  5. //#define CHECK_FREE_TASK_PRIO
  6. typedef union{
  7. unsigned short info[2];
  8. unsigned long int_info;
  9. }mem_node_info_t;
  10. extern void alloc_err_print(char *who, unsigned int data, void *caller);
  11. extern void check_mem_debug(void *where, struct mem_info *mem_info, void *caller, \
  12. struct buddy_debug_info *buddy_debug, uint32_t size);
  13. static void del_buddy(struct mem_info *mem_info, int index, int nr)
  14. {
  15. for(; index < BUDDYS_SIZE - nr; index++)
  16. mem_info->buddys[index] = mem_info->buddys[index+nr];
  17. for(nr--; nr >= 0; nr--)
  18. mem_info->buddys[index+nr] = (uint8_t)-1;
  19. }
  20. static void free_panic(void *where, void *caller, int err_no)
  21. {
  22. os_printk("BUG:task ");
  23. os_printk(" free %p from ", where);
  24. os_printk(" errno %d\n", err_no);
  25. //panic("buddy free error");
  26. }
  27. void mem_buddy_free(void *where, struct mem_info *mem_info, void *caller)
  28. {
  29. #ifdef CONFIG_SYS_IRQ_LOCK
  30. SYS_IRQ_FLAGS flags;
  31. #endif
  32. int i, size, page_num = -1;
  33. uint8_t buddy_no;
  34. void *page;
  35. //mem_node_info_t node_info;
  36. struct buddy_debug_info buddy_debug;
  37. //printk("-- free from %x caller %x ptr %x\n", mem_info, caller, where);
  38. #ifdef CONFIG_ACTIONS_TRACE
  39. TRACE_FREE(where, caller);
  40. #endif
  41. if(where == NULL || mem_info == NULL)
  42. free_panic(where, caller, -EINVAL);
  43. buddy_no = pagepool_convert_addr_to_pageindex(where);
  44. #ifdef CONFIG_SYS_IRQ_LOCK
  45. sys_irq_lock(&flags);
  46. #endif
  47. for(i = 0; i < BUDDYS_SIZE; i++)
  48. {
  49. if (mem_info->buddys[i] == (uint8_t) -1)
  50. break;
  51. if((mem_info->buddys[i] & 0x80) == 0)
  52. {
  53. if(mem_info->buddys[i] == buddy_no)
  54. {
  55. page_num = 0;
  56. break;
  57. }
  58. continue;
  59. }
  60. if((mem_info->buddys[i] & 0x7f) == buddy_no)
  61. {
  62. if (i + 1 < BUDDYS_SIZE && mem_info->buddys[i + 1] != (uint8_t) -1
  63. && (mem_info->buddys[i + 1] & (uint8_t) 0xc0) == (uint8_t) 0xc0)
  64. {
  65. page_num = mem_info->buddys[i + 1] & (uint8_t) 0x3f;
  66. }
  67. else
  68. {
  69. page_num = 1;
  70. }
  71. break;
  72. }
  73. //if (i + 1 < BUDDYS_SIZE && mem_info->buddys[i + 1] != (uint8_t) -1
  74. // && (mem_info->buddys[i + 1] & (uint8_t) 0xc0) == (uint8_t) 0xc0)
  75. {
  76. i++;
  77. }
  78. }
  79. if(i == BUDDYS_SIZE || page_num == -1)
  80. free_panic(where, caller, -EACCES);
  81. if(page_num == 0)
  82. {
  83. size = buddy_free(buddy_no, where, NULL);
  84. if(size <= 0)
  85. free_panic(where, caller, -EIO);
  86. if(rom_is_buddy_idled(buddy_no, &g_rom_buddy_data))
  87. {
  88. for(i = 0; i < BUDDYS_SIZE; i++)
  89. {
  90. if(mem_info->buddys[i] == buddy_no)
  91. break;
  92. }
  93. del_buddy(mem_info, i, 1);
  94. page_num = 1;
  95. }
  96. mem_info->alloc_size -= size;
  97. memcpy(&buddy_debug, (void *)((char *)where + size - 8), sizeof(buddy_debug));
  98. check_mem_debug(where, mem_info, caller, &buddy_debug, size);
  99. }
  100. else
  101. {
  102. if((unsigned int)where & (PAGE_SIZE - 1))
  103. free_panic(where, caller, -EPERM);
  104. for(i = 0; i < BUDDYS_SIZE; i++)
  105. {
  106. if(mem_info->buddys[i] == (buddy_no | 0x80))
  107. break;
  108. }
  109. del_buddy(mem_info, i, 2/*1+(page_num>1)*/);
  110. size = PAGE_SIZE * page_num;
  111. mem_info->alloc_size -= size;
  112. memcpy(&buddy_debug, (void *)((char *)where + size - 8), sizeof(buddy_debug));
  113. check_mem_debug(where, mem_info, caller, &buddy_debug, size);
  114. }
  115. if(page_num > 0)
  116. {
  117. int ret_val;
  118. page = pagepool_convert_index_to_addr(buddy_no);
  119. //printk("buddy_no %d page %x freelist next %x prev %x\n", buddy_no, page, freelist.next_index, freelist.prev_index);
  120. ret_val = pfree(page, page_num, caller);
  121. if(ret_val < 0){
  122. free_panic(where, caller, -EBUSY);
  123. }
  124. //printk("pagenum %d free pagenum %d \n", page_num, freepage_num[0]);
  125. }
  126. #ifdef CONFIG_SYS_IRQ_LOCK
  127. sys_irq_unlock(&flags);
  128. #endif
  129. }
  130. #if 0
  131. void free(void *where)
  132. {
  133. if(_is_in_isr())
  134. {
  135. free_panic(where, __builtin_return_address(0), -EPERM);
  136. return;
  137. }
  138. free_inner(where, current_mem_info(), __builtin_return_address(0));
  139. }
  140. void free_anon(void *where, k_tid_t tid)
  141. {
  142. if(tid == NULL)
  143. tid = _main_thread;
  144. free_inner(where, get_mem_info(tid), __builtin_return_address(0));
  145. }
  146. #endif