xf86drmSL.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /* xf86drmSL.c -- Skip list support
  2. * Created: Mon May 10 09:28:13 1999 by faith@precisioninsight.com
  3. *
  4. * SPDX-FileCopyrightText: 1999 Precision Insight, Inc., Cedar Park, Texas.
  5. * SPDX-License-Identifier: MIT
  6. * SPDX-FileContributor: Rickard E. (Rik) Faith <faith@valinux.com>
  7. *
  8. * DESCRIPTION
  9. *
  10. * This file contains a straightforward skip list implementation.n
  11. *
  12. * FUTURE ENHANCEMENTS
  13. *
  14. * REFERENCES
  15. *
  16. * [Pugh90] William Pugh. Skip Lists: A Probabilistic Alternative to
  17. * Balanced Trees. CACM 33(6), June 1990, pp. 668-676.
  18. *
  19. */
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include "libdrm_macros.h"
  23. #include "xf86drm.h"
  24. #define SL_LIST_MAGIC 0xfacade00LU
  25. #define SL_ENTRY_MAGIC 0x00fab1edLU
  26. #define SL_FREED_MAGIC 0xdecea5edLU
  27. #define SL_MAX_LEVEL 16
  28. #define SL_RANDOM_SEED 0xc01055a1LU
  29. #define SL_RANDOM_DECL static void *state = NULL
  30. #define SL_RANDOM_INIT(seed) if (!state) state = drmRandomCreate(seed)
  31. #define SL_RANDOM drmRandom(state)
  32. typedef struct SLEntry {
  33. unsigned long magic; /* SL_ENTRY_MAGIC */
  34. unsigned long key;
  35. void *value;
  36. int levels;
  37. struct SLEntry *forward[1]; /* variable sized array */
  38. } SLEntry, *SLEntryPtr;
  39. typedef struct SkipList {
  40. unsigned long magic; /* SL_LIST_MAGIC */
  41. int level;
  42. int count;
  43. SLEntryPtr head;
  44. SLEntryPtr p0; /* Position for iteration */
  45. } SkipList, *SkipListPtr;
  46. static SLEntryPtr SLCreateEntry(int max_level, unsigned long key, void *value)
  47. {
  48. SLEntryPtr entry;
  49. if (max_level < 0 || max_level > SL_MAX_LEVEL) max_level = SL_MAX_LEVEL;
  50. entry = drmMalloc(sizeof(*entry)
  51. + (max_level + 1) * sizeof(entry->forward[0]));
  52. if (!entry) return NULL;
  53. entry->magic = SL_ENTRY_MAGIC;
  54. entry->key = key;
  55. entry->value = value;
  56. entry->levels = max_level + 1;
  57. return entry;
  58. }
  59. static int SLRandomLevel(void)
  60. {
  61. int level = 1;
  62. SL_RANDOM_DECL;
  63. SL_RANDOM_INIT(SL_RANDOM_SEED);
  64. while ((SL_RANDOM & 0x01) && level < SL_MAX_LEVEL) ++level;
  65. return level;
  66. }
  67. drm_public void *drmSLCreate(void)
  68. {
  69. SkipListPtr list;
  70. int i;
  71. list = drmMalloc(sizeof(*list));
  72. if (!list) return NULL;
  73. list->magic = SL_LIST_MAGIC;
  74. list->level = 0;
  75. list->head = SLCreateEntry(SL_MAX_LEVEL, 0, NULL);
  76. list->count = 0;
  77. for (i = 0; i <= SL_MAX_LEVEL; i++) list->head->forward[i] = NULL;
  78. return list;
  79. }
  80. drm_public int drmSLDestroy(void *l)
  81. {
  82. SkipListPtr list = (SkipListPtr)l;
  83. SLEntryPtr entry;
  84. SLEntryPtr next;
  85. if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
  86. for (entry = list->head; entry; entry = next) {
  87. if (entry->magic != SL_ENTRY_MAGIC) return -1; /* Bad magic */
  88. next = entry->forward[0];
  89. entry->magic = SL_FREED_MAGIC;
  90. drmFree(entry);
  91. }
  92. list->magic = SL_FREED_MAGIC;
  93. drmFree(list);
  94. return 0;
  95. }
  96. static SLEntryPtr SLLocate(void *l, unsigned long key, SLEntryPtr *update)
  97. {
  98. SkipListPtr list = (SkipListPtr)l;
  99. SLEntryPtr entry;
  100. int i;
  101. if (list->magic != SL_LIST_MAGIC) return NULL;
  102. for (i = list->level, entry = list->head; i >= 0; i--) {
  103. while (entry->forward[i] && entry->forward[i]->key < key)
  104. entry = entry->forward[i];
  105. update[i] = entry;
  106. }
  107. return entry->forward[0];
  108. }
  109. drm_public int drmSLInsert(void *l, unsigned long key, void *value)
  110. {
  111. SkipListPtr list = (SkipListPtr)l;
  112. SLEntryPtr entry;
  113. SLEntryPtr update[SL_MAX_LEVEL + 1];
  114. int level;
  115. int i;
  116. if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
  117. entry = SLLocate(list, key, update);
  118. if (entry && entry->key == key) return 1; /* Already in list */
  119. level = SLRandomLevel();
  120. if (level > list->level) {
  121. level = ++list->level;
  122. update[level] = list->head;
  123. }
  124. entry = SLCreateEntry(level, key, value);
  125. /* Fix up forward pointers */
  126. for (i = 0; i <= level; i++) {
  127. entry->forward[i] = update[i]->forward[i];
  128. update[i]->forward[i] = entry;
  129. }
  130. ++list->count;
  131. return 0; /* Added to table */
  132. }
  133. drm_public int drmSLDelete(void *l, unsigned long key)
  134. {
  135. SkipListPtr list = (SkipListPtr)l;
  136. SLEntryPtr update[SL_MAX_LEVEL + 1];
  137. SLEntryPtr entry;
  138. int i;
  139. if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
  140. entry = SLLocate(list, key, update);
  141. if (!entry || entry->key != key) return 1; /* Not found */
  142. /* Fix up forward pointers */
  143. for (i = 0; i <= list->level; i++) {
  144. if (update[i]->forward[i] == entry)
  145. update[i]->forward[i] = entry->forward[i];
  146. }
  147. entry->magic = SL_FREED_MAGIC;
  148. drmFree(entry);
  149. while (list->level && !list->head->forward[list->level]) --list->level;
  150. --list->count;
  151. return 0;
  152. }
  153. drm_public int drmSLLookup(void *l, unsigned long key, void **value)
  154. {
  155. SkipListPtr list = (SkipListPtr)l;
  156. SLEntryPtr update[SL_MAX_LEVEL + 1];
  157. SLEntryPtr entry;
  158. entry = SLLocate(list, key, update);
  159. if (entry && entry->key == key) {
  160. *value = entry;
  161. return 0;
  162. }
  163. *value = NULL;
  164. return -1;
  165. }
  166. drm_public int drmSLLookupNeighbors(void *l, unsigned long key,
  167. unsigned long *prev_key, void **prev_value,
  168. unsigned long *next_key, void **next_value)
  169. {
  170. SkipListPtr list = (SkipListPtr)l;
  171. SLEntryPtr update[SL_MAX_LEVEL + 1] = {0};
  172. int retcode = 0;
  173. SLLocate(list, key, update);
  174. *prev_key = *next_key = key;
  175. *prev_value = *next_value = NULL;
  176. if (update[0]) {
  177. *prev_key = update[0]->key;
  178. *prev_value = update[0]->value;
  179. ++retcode;
  180. if (update[0]->forward[0]) {
  181. *next_key = update[0]->forward[0]->key;
  182. *next_value = update[0]->forward[0]->value;
  183. ++retcode;
  184. }
  185. }
  186. return retcode;
  187. }
  188. drm_public int drmSLNext(void *l, unsigned long *key, void **value)
  189. {
  190. SkipListPtr list = (SkipListPtr)l;
  191. SLEntryPtr entry;
  192. if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
  193. entry = list->p0;
  194. if (entry) {
  195. list->p0 = entry->forward[0];
  196. *key = entry->key;
  197. *value = entry->value;
  198. return 1;
  199. }
  200. list->p0 = NULL;
  201. return 0;
  202. }
  203. drm_public int drmSLFirst(void *l, unsigned long *key, void **value)
  204. {
  205. SkipListPtr list = (SkipListPtr)l;
  206. if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
  207. list->p0 = list->head->forward[0];
  208. return drmSLNext(list, key, value);
  209. }
  210. /* Dump internal data structures for debugging. */
  211. drm_public void drmSLDump(void *l)
  212. {
  213. SkipListPtr list = (SkipListPtr)l;
  214. SLEntryPtr entry;
  215. int i;
  216. if (list->magic != SL_LIST_MAGIC) {
  217. printf("Bad magic: 0x%08lx (expected 0x%08lx)\n",
  218. list->magic, SL_LIST_MAGIC);
  219. return;
  220. }
  221. printf("Level = %d, count = %d\n", list->level, list->count);
  222. for (entry = list->head; entry; entry = entry->forward[0]) {
  223. if (entry->magic != SL_ENTRY_MAGIC) {
  224. printf("Bad magic: 0x%08lx (expected 0x%08lx)\n",
  225. list->magic, SL_ENTRY_MAGIC);
  226. }
  227. printf("\nEntry %p <0x%08lx, %p> has %2d levels\n",
  228. entry, entry->key, entry->value, entry->levels);
  229. for (i = 0; i < entry->levels; i++) {
  230. if (entry->forward[i]) {
  231. printf(" %2d: %p <0x%08lx, %p>\n",
  232. i,
  233. entry->forward[i],
  234. entry->forward[i]->key,
  235. entry->forward[i]->value);
  236. } else {
  237. printf(" %2d: %p\n", i, entry->forward[i]);
  238. }
  239. }
  240. }
  241. }