mm.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * GLX Hardware Device Driver common code
  3. * Copyright (C) 1999 Wittawat Yamwong
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the "Software"),
  7. * to deal in the Software without restriction, including without limitation
  8. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. * and/or sell copies of the Software, and to permit persons to whom the
  10. * Software is furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included
  13. * in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  16. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
  19. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  20. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  21. * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. *
  23. */
  24. #include <stdlib.h>
  25. #include <assert.h>
  26. #include "xf86drm.h"
  27. #include "libdrm_macros.h"
  28. #include "mm.h"
  29. drm_private void mmDumpMemInfo(const struct mem_block *heap)
  30. {
  31. drmMsg("Memory heap %p:\n", (void *)heap);
  32. if (heap == 0) {
  33. drmMsg(" heap == 0\n");
  34. } else {
  35. const struct mem_block *p;
  36. for (p = heap->next; p != heap; p = p->next) {
  37. drmMsg(" Offset:%08x, Size:%08x, %c%c\n", p->ofs,
  38. p->size, p->free ? 'F' : '.',
  39. p->reserved ? 'R' : '.');
  40. }
  41. drmMsg("\nFree list:\n");
  42. for (p = heap->next_free; p != heap; p = p->next_free) {
  43. drmMsg(" FREE Offset:%08x, Size:%08x, %c%c\n", p->ofs,
  44. p->size, p->free ? 'F' : '.',
  45. p->reserved ? 'R' : '.');
  46. }
  47. }
  48. drmMsg("End of memory blocks\n");
  49. }
  50. drm_private struct mem_block *mmInit(int ofs, int size)
  51. {
  52. struct mem_block *heap, *block;
  53. if (size <= 0)
  54. return NULL;
  55. heap = (struct mem_block *)calloc(1, sizeof(struct mem_block));
  56. if (!heap)
  57. return NULL;
  58. block = (struct mem_block *)calloc(1, sizeof(struct mem_block));
  59. if (!block) {
  60. free(heap);
  61. return NULL;
  62. }
  63. heap->next = block;
  64. heap->prev = block;
  65. heap->next_free = block;
  66. heap->prev_free = block;
  67. block->heap = heap;
  68. block->next = heap;
  69. block->prev = heap;
  70. block->next_free = heap;
  71. block->prev_free = heap;
  72. block->ofs = ofs;
  73. block->size = size;
  74. block->free = 1;
  75. return heap;
  76. }
  77. static struct mem_block *SliceBlock(struct mem_block *p,
  78. int startofs, int size,
  79. int reserved, int alignment)
  80. {
  81. struct mem_block *newblock;
  82. /* break left [p, newblock, p->next], then p = newblock */
  83. if (startofs > p->ofs) {
  84. newblock =
  85. (struct mem_block *)calloc(1, sizeof(struct mem_block));
  86. if (!newblock)
  87. return NULL;
  88. newblock->ofs = startofs;
  89. newblock->size = p->size - (startofs - p->ofs);
  90. newblock->free = 1;
  91. newblock->heap = p->heap;
  92. newblock->next = p->next;
  93. newblock->prev = p;
  94. p->next->prev = newblock;
  95. p->next = newblock;
  96. newblock->next_free = p->next_free;
  97. newblock->prev_free = p;
  98. p->next_free->prev_free = newblock;
  99. p->next_free = newblock;
  100. p->size -= newblock->size;
  101. p = newblock;
  102. }
  103. /* break right, also [p, newblock, p->next] */
  104. if (size < p->size) {
  105. newblock =
  106. (struct mem_block *)calloc(1, sizeof(struct mem_block));
  107. if (!newblock)
  108. return NULL;
  109. newblock->ofs = startofs + size;
  110. newblock->size = p->size - size;
  111. newblock->free = 1;
  112. newblock->heap = p->heap;
  113. newblock->next = p->next;
  114. newblock->prev = p;
  115. p->next->prev = newblock;
  116. p->next = newblock;
  117. newblock->next_free = p->next_free;
  118. newblock->prev_free = p;
  119. p->next_free->prev_free = newblock;
  120. p->next_free = newblock;
  121. p->size = size;
  122. }
  123. /* p = middle block */
  124. p->free = 0;
  125. /* Remove p from the free list:
  126. */
  127. p->next_free->prev_free = p->prev_free;
  128. p->prev_free->next_free = p->next_free;
  129. p->next_free = 0;
  130. p->prev_free = 0;
  131. p->reserved = reserved;
  132. return p;
  133. }
  134. drm_private struct mem_block *mmAllocMem(struct mem_block *heap, int size,
  135. int align2, int startSearch)
  136. {
  137. struct mem_block *p;
  138. const int mask = (1 << align2) - 1;
  139. int startofs = 0;
  140. int endofs;
  141. if (!heap || align2 < 0 || size <= 0)
  142. return NULL;
  143. for (p = heap->next_free; p != heap; p = p->next_free) {
  144. assert(p->free);
  145. startofs = (p->ofs + mask) & ~mask;
  146. if (startofs < startSearch) {
  147. startofs = startSearch;
  148. }
  149. endofs = startofs + size;
  150. if (endofs <= (p->ofs + p->size))
  151. break;
  152. }
  153. if (p == heap)
  154. return NULL;
  155. assert(p->free);
  156. p = SliceBlock(p, startofs, size, 0, mask + 1);
  157. return p;
  158. }
  159. static int Join2Blocks(struct mem_block *p)
  160. {
  161. /* XXX there should be some assertions here */
  162. /* NOTE: heap->free == 0 */
  163. if (p->free && p->next->free) {
  164. struct mem_block *q = p->next;
  165. assert(p->ofs + p->size == q->ofs);
  166. p->size += q->size;
  167. p->next = q->next;
  168. q->next->prev = p;
  169. q->next_free->prev_free = q->prev_free;
  170. q->prev_free->next_free = q->next_free;
  171. free(q);
  172. return 1;
  173. }
  174. return 0;
  175. }
  176. drm_private int mmFreeMem(struct mem_block *b)
  177. {
  178. if (!b)
  179. return 0;
  180. if (b->free) {
  181. drmMsg("block already free\n");
  182. return -1;
  183. }
  184. if (b->reserved) {
  185. drmMsg("block is reserved\n");
  186. return -1;
  187. }
  188. b->free = 1;
  189. b->next_free = b->heap->next_free;
  190. b->prev_free = b->heap;
  191. b->next_free->prev_free = b;
  192. b->prev_free->next_free = b;
  193. Join2Blocks(b);
  194. if (b->prev != b->heap)
  195. Join2Blocks(b->prev);
  196. return 0;
  197. }
  198. drm_private void mmDestroy(struct mem_block *heap)
  199. {
  200. struct mem_block *p;
  201. if (!heap)
  202. return;
  203. for (p = heap->next; p != heap;) {
  204. struct mem_block *next = p->next;
  205. free(p);
  206. p = next;
  207. }
  208. free(heap);
  209. }