xalloc.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #define datoff ((ulong)((Xhdr*)0)->data)
  7. enum
  8. {
  9. Chunk = 64*1024,
  10. Nhole = 128,
  11. Magichole = 0x484F4C45, /* HOLE */
  12. };
  13. typedef struct Hole Hole;
  14. typedef struct Xalloc Xalloc;
  15. typedef struct Xhdr Xhdr;
  16. struct Hole
  17. {
  18. ulong addr;
  19. ulong size;
  20. ulong top;
  21. Hole* link;
  22. };
  23. struct Xhdr
  24. {
  25. ulong size;
  26. ulong magix;
  27. char data[1];
  28. };
  29. struct Xalloc
  30. {
  31. Lock;
  32. Hole hole[Nhole];
  33. Hole* flist;
  34. Hole* table;
  35. };
  36. static Xalloc xlists;
  37. void
  38. xinit(void)
  39. {
  40. Hole *h, *eh;
  41. int upages, np0, np1;
  42. eh = &xlists.hole[Nhole-1];
  43. for(h = xlists.hole; h < eh; h++)
  44. h->link = h+1;
  45. xlists.flist = xlists.hole;
  46. upages = conf.upages;
  47. np1 = upages;
  48. if(np1 > conf.npage1)
  49. np1 = conf.npage1;
  50. palloc.p1 = conf.base1 + (conf.npage1 - np1)*BY2PG;
  51. conf.npage1 -= np1;
  52. xhole(conf.base1, conf.npage1*BY2PG);
  53. conf.npage1 = conf.base1+(conf.npage1*BY2PG);
  54. upages -= np1;
  55. np0 = upages;
  56. if(np0 > conf.npage0)
  57. np0 = conf.npage0;
  58. palloc.p0 = conf.base0 + (conf.npage0 - np0)*BY2PG;
  59. conf.npage0 -= np0;
  60. xhole(conf.base0, conf.npage0*BY2PG);
  61. conf.npage0 = conf.base0+(conf.npage0*BY2PG);
  62. palloc.np0 = np0;
  63. palloc.np1 = np1;
  64. /* Save the bounds of kernel alloc memory for kernel mmu mapping */
  65. conf.base0 = (ulong)KADDR(conf.base0);
  66. conf.base1 = (ulong)KADDR(conf.base1);
  67. conf.npage0 = (ulong)KADDR(conf.npage0);
  68. conf.npage1 = (ulong)KADDR(conf.npage1);
  69. }
  70. void*
  71. xspanalloc(ulong size, int align, ulong span)
  72. {
  73. ulong a, v, t;
  74. a = (ulong)xalloc(size+align+span);
  75. if(a == 0)
  76. panic("xspanalloc: %lud %d %lux\n", size, align, span);
  77. if(span > 2) {
  78. v = (a + span) & ~(span-1);
  79. t = v - a;
  80. if(t > 0)
  81. xhole(PADDR(a), t);
  82. t = a + span - v;
  83. if(t > 0)
  84. xhole(PADDR(v+size+align), t);
  85. }
  86. else
  87. v = a;
  88. if(align > 1)
  89. v = (v + align) & ~(align-1);
  90. return (void*)v;
  91. }
  92. void*
  93. xallocz(ulong size, int zero)
  94. {
  95. Xhdr *p;
  96. Hole *h, **l;
  97. size += BY2V + sizeof(Xhdr);
  98. size &= ~(BY2V-1);
  99. ilock(&xlists);
  100. l = &xlists.table;
  101. for(h = *l; h; h = h->link) {
  102. if(h->size >= size) {
  103. p = (Xhdr*)h->addr;
  104. h->addr += size;
  105. h->size -= size;
  106. if(h->size == 0) {
  107. *l = h->link;
  108. h->link = xlists.flist;
  109. xlists.flist = h;
  110. }
  111. iunlock(&xlists);
  112. p = KADDR(p);
  113. p->magix = Magichole;
  114. p->size = size;
  115. if(zero)
  116. memset(p->data, 0, size);
  117. return p->data;
  118. }
  119. l = &h->link;
  120. }
  121. iunlock(&xlists);
  122. return nil;
  123. }
  124. void*
  125. xalloc(ulong size)
  126. {
  127. return xallocz(size, 1);
  128. }
  129. void
  130. xfree(void *p)
  131. {
  132. Xhdr *x;
  133. x = (Xhdr*)((ulong)p - datoff);
  134. if(x->magix != Magichole) {
  135. xsummary();
  136. panic("xfree(0x%lux) 0x%lux!=0x%lux", p, (ulong)Magichole, x->magix);
  137. }
  138. xhole(PADDR(x), x->size);
  139. }
  140. int
  141. xmerge(void *vp, void *vq)
  142. {
  143. Xhdr *p, *q;
  144. p = vp;
  145. if((uchar*)vp+p->size == (uchar*)vq) {
  146. q = vq;
  147. p->size += q->size;
  148. return 1;
  149. }
  150. return 0;
  151. }
  152. void
  153. xhole(ulong addr, ulong size)
  154. {
  155. ulong top;
  156. Hole *h, *c, **l;
  157. if(size == 0)
  158. return;
  159. top = addr + size;
  160. ilock(&xlists);
  161. l = &xlists.table;
  162. for(h = *l; h; h = h->link) {
  163. if(h->top == addr) {
  164. h->size += size;
  165. h->top = h->addr+h->size;
  166. c = h->link;
  167. if(c && h->top == c->addr) {
  168. h->top += c->size;
  169. h->size += c->size;
  170. h->link = c->link;
  171. c->link = xlists.flist;
  172. xlists.flist = c;
  173. }
  174. iunlock(&xlists);
  175. return;
  176. }
  177. if(h->addr > addr)
  178. break;
  179. l = &h->link;
  180. }
  181. if(h && top == h->addr) {
  182. h->addr -= size;
  183. h->size += size;
  184. iunlock(&xlists);
  185. return;
  186. }
  187. if(xlists.flist == nil) {
  188. iunlock(&xlists);
  189. print("xfree: no free holes, leaked %lud bytes\n", size);
  190. return;
  191. }
  192. h = xlists.flist;
  193. xlists.flist = h->link;
  194. h->addr = addr;
  195. h->top = top;
  196. h->size = size;
  197. h->link = *l;
  198. *l = h;
  199. iunlock(&xlists);
  200. }
  201. void
  202. xsummary(void)
  203. {
  204. int i;
  205. Hole *h;
  206. i = 0;
  207. for(h = xlists.flist; h; h = h->link)
  208. i++;
  209. print("%d holes free\n", i);
  210. i = 0;
  211. for(h = xlists.table; h; h = h->link) {
  212. print("%.8lux %.8lux %lud\n", h->addr, h->top, h->size);
  213. i += h->size;
  214. }
  215. print("%d bytes free\n", i);
  216. }