ged_hashtable.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Copyright (C) 2015 MediaTek Inc.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include "ged_base.h"
  14. #include "ged_hashtable.h"
  15. #include <linux/hashtable.h>
  16. typedef struct GED_HASHTABLE_TAG
  17. {
  18. unsigned int ui32Bits;
  19. unsigned int ui32Length;
  20. unsigned int ui32CurrentID;
  21. unsigned int ui32Count;
  22. struct hlist_head* psHashTable;
  23. } GED_HASHTABLE;
  24. typedef struct GED_HASHNODE_TAG
  25. {
  26. unsigned int ui32ID;
  27. void* pvoid;
  28. struct hlist_node sNode;
  29. } GED_HASHNODE;
  30. #define GED_HASHTABLE_INIT_ID 1234 // 0 = invalid
  31. void* __ged_hashtable_find(struct hlist_head *head, unsigned int ui32ID)
  32. {
  33. GED_HASHNODE* psHN;
  34. hlist_for_each_entry_rcu(psHN, head, sNode)
  35. {
  36. if (psHN->ui32ID == ui32ID)
  37. {
  38. return psHN;
  39. }
  40. }
  41. return NULL;
  42. }
  43. static int ged_hash(GED_HASHTABLE_HANDLE hHashTable, unsigned int ui32ID)
  44. {
  45. GED_HASHTABLE* psHT = (GED_HASHTABLE*)hHashTable;
  46. return hash_32(ui32ID, psHT->ui32Bits);
  47. }
  48. GED_HASHTABLE_HANDLE ged_hashtable_create(unsigned int ui32Bits)
  49. {
  50. GED_HASHTABLE* psHT;
  51. unsigned int i;
  52. if (ui32Bits > 20)
  53. {
  54. // 1048576 slots !?
  55. // Need to check the necessary
  56. return NULL;
  57. }
  58. psHT = (GED_HASHTABLE*)ged_alloc(sizeof(GED_HASHTABLE));
  59. if (psHT)
  60. {
  61. psHT->ui32Bits = ui32Bits;
  62. psHT->ui32Length = 1 << ui32Bits;
  63. psHT->ui32CurrentID = GED_HASHTABLE_INIT_ID; // 0 = invalid
  64. psHT->psHashTable = (struct hlist_head*)ged_alloc(psHT->ui32Length * sizeof(struct hlist_head));
  65. if (psHT->psHashTable)
  66. {
  67. for (i = 0; i < psHT->ui32Length; i++)
  68. {
  69. INIT_HLIST_HEAD(&psHT->psHashTable[i]);
  70. }
  71. return (GED_HASHTABLE_HANDLE)psHT;
  72. }
  73. }
  74. ged_hashtable_destroy(psHT);
  75. return NULL;
  76. }
  77. void ged_hashtable_destroy(GED_HASHTABLE_HANDLE hHashTable)
  78. {
  79. GED_HASHTABLE* psHT = (GED_HASHTABLE*)hHashTable;
  80. if (psHT)
  81. {
  82. int i = 0;
  83. while(psHT->ui32Count > 0)
  84. {
  85. unsigned int ui32ID = 0;
  86. GED_HASHNODE* psHN;
  87. // get one to be freed
  88. for (;i < psHT->ui32Length; i++)
  89. {
  90. struct hlist_head *head = &psHT->psHashTable[i];
  91. hlist_for_each_entry_rcu(psHN, head, sNode)
  92. {
  93. ui32ID = psHN->ui32ID;
  94. break;
  95. }
  96. if (0 < ui32ID)
  97. {
  98. break;
  99. }
  100. }
  101. if (i >= psHT->ui32Length)
  102. {
  103. break;
  104. }
  105. ged_hashtable_remove(psHT, ui32ID);
  106. }
  107. /* free the hash table */
  108. ged_free(psHT->psHashTable, psHT->ui32Length * sizeof(struct hlist_head));
  109. ged_free(psHT, sizeof(GED_HASHTABLE));
  110. }
  111. }
  112. GED_ERROR ged_hashtable_insert(GED_HASHTABLE_HANDLE hHashTable, void* pvoid, unsigned int* pui32ID)
  113. {
  114. GED_HASHTABLE* psHT = (GED_HASHTABLE*)hHashTable;
  115. GED_HASHNODE* psHN = NULL;
  116. unsigned int ui32Hash, ui32ID;
  117. if ((!psHT) || (!pui32ID))
  118. {
  119. return GED_ERROR_INVALID_PARAMS;
  120. }
  121. ui32ID = psHT->ui32CurrentID + 1;
  122. while(1)
  123. {
  124. ui32Hash = ged_hash(psHT, ui32ID);
  125. psHN = __ged_hashtable_find(&psHT->psHashTable[ui32Hash], ui32ID);
  126. if (psHN != NULL)
  127. {
  128. ui32ID++;
  129. if (ui32ID == 0)//skip the value 0
  130. {
  131. ui32ID = 1;
  132. }
  133. if (ui32ID == psHT->ui32CurrentID)
  134. {
  135. return GED_ERROR_FAIL;
  136. }
  137. }
  138. else
  139. {
  140. break;
  141. }
  142. };
  143. psHN = (GED_HASHNODE*)ged_alloc(sizeof(GED_HASHNODE));
  144. if (psHN)
  145. {
  146. psHN->pvoid = pvoid;
  147. psHN->ui32ID = ui32ID;
  148. psHT->ui32CurrentID = ui32ID;
  149. *pui32ID = ui32ID;
  150. hlist_add_head_rcu(&psHN->sNode, &psHT->psHashTable[ui32Hash]);
  151. psHT->ui32Count += 1;
  152. return GED_OK;
  153. }
  154. return GED_ERROR_OOM;
  155. }
  156. void ged_hashtable_remove(GED_HASHTABLE_HANDLE hHashTable, unsigned int ui32ID)
  157. {
  158. GED_HASHTABLE* psHT = (GED_HASHTABLE*)hHashTable;
  159. if (psHT)
  160. {
  161. unsigned int ui32Hash = ged_hash(psHT, ui32ID);
  162. GED_HASHNODE* psHN = __ged_hashtable_find(&psHT->psHashTable[ui32Hash], ui32ID);
  163. if (psHN)
  164. {
  165. hlist_del_rcu(&psHN->sNode);
  166. synchronize_rcu();
  167. ged_free(psHN, sizeof(GED_HASHNODE));
  168. psHT->ui32Count -= 1;
  169. }
  170. }
  171. }
  172. void* ged_hashtable_find(GED_HASHTABLE_HANDLE hHashTable, unsigned int ui32ID)
  173. {
  174. GED_HASHTABLE* psHT = (GED_HASHTABLE*)hHashTable;
  175. if (psHT)
  176. {
  177. unsigned int ui32Hash = ged_hash(psHT, ui32ID);
  178. GED_HASHNODE* psHN = __ged_hashtable_find(&psHT->psHashTable[ui32Hash], ui32ID);
  179. if (psHN)
  180. {
  181. return psHN->pvoid;
  182. }
  183. #ifdef GED_DEBUG
  184. if (ui32ID != 0)
  185. {
  186. GED_LOGE("ged_hashtable_find: ui32ID=%u ui32Hash=%u psHN=%p\n", ui32ID, ui32Hash, psHN);
  187. }
  188. #endif
  189. }
  190. return NULL;
  191. }
  192. GED_ERROR ged_hashtable_set(GED_HASHTABLE_HANDLE hHashTable, unsigned int ui32ID, void* pvoid)
  193. {
  194. GED_HASHTABLE* psHT = (GED_HASHTABLE*)hHashTable;
  195. if (psHT)
  196. {
  197. unsigned int ui32Hash = ged_hash(psHT, ui32ID);
  198. GED_HASHNODE* psHN = __ged_hashtable_find(&psHT->psHashTable[ui32Hash], ui32ID);
  199. if (psHN)
  200. {
  201. psHN->pvoid = pvoid;
  202. return GED_OK;
  203. }
  204. }
  205. return GED_ERROR_INVALID_PARAMS;
  206. }