simple_idr.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /*
  2. * simple_idr.c
  3. *
  4. * Copyright (c) 2007-2019 Allwinnertech Co., Ltd.
  5. *
  6. *
  7. * This software is licensed under the terms of the GNU General Public
  8. * License version 2, as published by the Free Software Foundation, and
  9. * may be copied, distributed, and modified under those terms.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. */
  17. //not apply it in the IRQ, a simple idr from linux
  18. #include <stdio.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #include "g2d_bsp.h"
  23. #include "simple_idr.h"
  24. static struct id_layer** find_empty_slot(struct id_layer *up_layer, int *id_index)
  25. {
  26. //first right empty 0~31
  27. int i = 0, start = 0, id = 0;
  28. for (i = 0; i < IDR_SIZE/32; i++)
  29. if(up_layer->bitmap[i] != IDR32_MASK)
  30. break;
  31. if (i == IDR_SIZE/32) {
  32. *id_index = NO_ID;
  33. return NULL;
  34. }
  35. if (up_layer->bitmap[i] == 0)
  36. goto cal;
  37. id = ~up_layer->bitmap[i];
  38. // 0~31 bit
  39. if (!(id&0x0000ffff)) {
  40. start +=16;
  41. id >>= 16;
  42. }
  43. if (!(id&0x00ff)) {
  44. start += 8;
  45. id >>= 8;
  46. }
  47. if (!(id&0x0f)) {
  48. start += 4;
  49. id >>= 4;
  50. }
  51. if (!(id&0x3)) {
  52. start += 2;
  53. id >>= 2;
  54. }
  55. if (!(id&0x1)) {
  56. start += 1;
  57. id >>= 1;
  58. }
  59. cal:
  60. *id_index = i*32+start;
  61. return &up_layer->layer[*id_index];
  62. }
  63. int id_alloc(struct id_dir *dir, void *value)
  64. {
  65. int id = NO_ID, id_index = NO_ID;
  66. int i = 0;
  67. int curr_lvl;
  68. struct id_layer **cur = NULL, *tmp = NULL;
  69. if (dir == NULL || dir->status == -1)
  70. return NO_ID;
  71. hal_sem_wait(dir->lock);
  72. if (dir->status == -1)
  73. goto out;
  74. dir->status = 1;
  75. if (dir->lu_cache[0] != NULL) {
  76. tmp = dir->lu_cache[0];
  77. id = dir->lu_id;
  78. cur = find_empty_slot(tmp, &id_index);
  79. id = (id&(~0xff)) + id_index;
  80. }else{
  81. //add a new top
  82. if (dir->top == NULL || find_empty_slot(dir->top, &id_index) == NULL) {
  83. if (dir->top && dir->cur_max_level > 2) {
  84. G2D_INFO_MSG("a full idr,we only support 32bit\n");
  85. goto out;
  86. }
  87. tmp = (struct id_layer*)hal_malloc(sizeof(struct id_layer));
  88. memset(tmp, 0, sizeof(struct id_layer));
  89. tmp->layer[0] = dir->top;
  90. tmp->bitmap[0] = 0x01;//0 is NO_ID
  91. tmp->num_layer = 1;
  92. dir->cur_max_level++;
  93. dir->top = tmp;
  94. if (dir->head) {
  95. dir->head->pre = tmp;
  96. }
  97. tmp->next = dir->head;
  98. }
  99. curr_lvl = dir->cur_max_level;
  100. for (cur= &dir->top; *cur != NULL; id <<= 8, id += id_index, curr_lvl--) {
  101. tmp = *cur;
  102. dir->lu_cache[curr_lvl] = tmp;
  103. cur = find_empty_slot(tmp, &id_index);
  104. if (curr_lvl > 0 && *cur == NULL) {
  105. //add a new child idr
  106. *cur = (struct id_layer*)hal_malloc(sizeof(struct id_layer));
  107. if (*cur == NULL) {
  108. G2D_INFO_MSG("atomic alloc idr mem err.\n");
  109. goto out;
  110. }
  111. memset(*cur, 0, sizeof(struct id_layer));
  112. tmp->num_layer++;
  113. (*cur)->next = dir->head;
  114. (*cur)->pre = NULL;
  115. dir->head = *cur;
  116. }
  117. }
  118. }
  119. dir->lu_id = id;
  120. *cur = (struct id_layer*)value;
  121. tmp->bitmap[id_index/32] |= 1 << (id_index%32);
  122. tmp->num_layer++;
  123. if (tmp->num_layer == IDR_SIZE) {
  124. dir->lu_cache[0] = NULL;
  125. for (i = 1; dir->lu_cache[i] != NULL && i < dir->cur_max_level; i++) {
  126. id_index = (id>>(8*i)) & 0xff;
  127. dir->lu_cache[i]->bitmap[id_index/32] |= 1 << (id_index%32);
  128. if (find_empty_slot(dir->lu_cache[i], &id_index) != NULL) {
  129. break;
  130. }
  131. }
  132. }
  133. dir->status = 0;
  134. out:
  135. hal_sem_post(dir->lock);
  136. // printf("id_alloc:%d == %08x\n",id, value);
  137. return id;
  138. }
  139. void id_free(struct id_dir *dir, int id)
  140. {
  141. struct id_layer* lu[4] = {NULL, NULL, NULL, NULL};
  142. int i = 0, id_index = 0;
  143. if (id>>((dir->cur_max_level+1)*8) || id == NO_ID
  144. || dir->top == NULL || dir->status == -1) {
  145. G2D_INFO_MSG("give a err id:%d, max:%ld\n", id, (1ul << ((dir->cur_max_level+1)* 8)) - 1);
  146. return;
  147. }
  148. hal_sem_wait(dir->lock);
  149. if (dir->status == -1)
  150. goto out;
  151. dir->status = 1;
  152. lu[dir->cur_max_level] = dir->top;
  153. for (i = dir->cur_max_level; i > 0; ) {
  154. id_index = (id>>(i*8)) & 0xff;
  155. i--;
  156. lu[i] = lu[i+1]->layer[id_index];
  157. }
  158. id_index = id&0xff;
  159. lu[0]->layer[id_index] = NULL;
  160. lu[0]->num_layer--;
  161. lu[0]->bitmap[id_index/32] &= ~(1<<(id_index % 32));
  162. for (i = 1; i <= dir->cur_max_level; i++) {
  163. id_index = (id>>(i*8)) & 0xff;
  164. lu[i]->bitmap[id_index/32] &= ~(1<<(id_index % 32));
  165. if (lu[i-1]->num_layer == 0) {
  166. //top will not empty due to NO_ID, least 1 top layer.
  167. if (lu[i]->layer[id_index]->next != NULL)
  168. lu[i]->layer[id_index]->next->pre = lu[i]->layer[id_index]->pre;
  169. if (lu[i]->layer[id_index]->pre != NULL)
  170. lu[i]->layer[id_index]->pre->next = lu[i]->layer[id_index]->next;
  171. else
  172. dir->head = lu[i]->layer[id_index]->next;
  173. free(lu[i]->layer[id_index]);
  174. lu[i]->layer[id_index] = NULL;
  175. lu[i]->num_layer--;
  176. }
  177. }
  178. //deal_top:
  179. while (dir->top->num_layer == 1 && dir->cur_max_level > 0
  180. && dir->top->layer[0] != NULL && dir->top->bitmap[0]^0x01) {
  181. lu[0] = dir->top;
  182. dir->top = lu[0]->layer[0];
  183. if (lu[0]->next != NULL)
  184. lu[0]->next->pre = lu[0]->pre;
  185. if (lu[0]->pre != NULL)
  186. lu[0]->pre->next = lu[0]->next;
  187. else
  188. dir->head = lu[0]->next;
  189. free(lu[0]);
  190. dir->cur_max_level--;
  191. }
  192. dir->status = 0;
  193. out:
  194. hal_sem_post(dir->lock);
  195. //printf("leave id_free: %d \n", id);
  196. }
  197. void* id_get(struct id_dir *dir, int id)
  198. {
  199. int id_index, i;
  200. struct id_layer *lu = NULL;
  201. if (dir == NULL || dir->top == NULL || dir->status == -1 || id == NO_ID)
  202. return NULL;
  203. //the atomic area , but not happen
  204. if (id>>((dir->cur_max_level+1)*8))
  205. return NULL;
  206. hal_sem_wait(dir->lock);
  207. if (dir->status == -1)
  208. goto out;
  209. dir->status = 1;
  210. lu = dir->top;
  211. for (i = dir->cur_max_level; i >= 0; i--) {
  212. id_index = (id>>(i*8)) & 0xff;
  213. lu = lu->layer[id_index];
  214. if (lu == NULL) {
  215. G2D_INFO_MSG("give a err id:%d\n", id);
  216. goto out;
  217. }
  218. }
  219. dir->status = 0;
  220. out:
  221. hal_sem_post(dir->lock);
  222. //printf("got id:%d=%08x\n",id,lu);
  223. return (void*)lu;
  224. }
  225. struct id_dir* id_creat(void)
  226. {
  227. struct id_dir* idr;
  228. int i;
  229. idr = (struct id_dir*)hal_malloc(sizeof(struct id_dir));
  230. if(idr == NULL) {
  231. G2D_INFO_MSG("malloc idr err.\n");
  232. return NULL;
  233. }
  234. memset(idr, 0, sizeof(struct id_dir));
  235. idr->cur_max_level = -1;
  236. idr->lock = hal_sem_create(1);
  237. for(i = 0; i < 4; i++)
  238. idr->lu_cache[i] = NULL;
  239. idr->lu_id = 0;
  240. idr->head = NULL;
  241. idr->top = (struct id_layer*)hal_malloc(sizeof(struct id_layer));
  242. if (idr->top == NULL) {
  243. G2D_INFO_MSG("malloc id_layer err.\n");
  244. goto out;
  245. }
  246. memset(idr->top, 0, sizeof(struct id_layer));
  247. idr->top->bitmap[0] = 0x01; //0 is NO_ID
  248. idr->top->num_layer = 1;
  249. idr->cur_max_level = 0;
  250. idr->head = idr->top;
  251. idr->lu_cache[0] = idr->top;
  252. out:
  253. return idr;
  254. }
  255. void id_destroyed(struct id_dir *dir)
  256. {
  257. struct id_layer* free_id_layer;
  258. hal_sem_wait(dir->lock);
  259. dir->status = -1;
  260. hal_sem_post(dir->lock);
  261. while(dir->head != NULL) {
  262. free_id_layer = dir->head;
  263. dir->head = free_id_layer->next;
  264. free(free_id_layer);
  265. }
  266. free(dir);
  267. }