allocb.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. enum
  15. {
  16. Hdrspc = 64, /* leave room for high-level headers */
  17. Bdead = 0x51494F42, /* "QIOB" */
  18. };
  19. struct
  20. {
  21. Lock;
  22. ulong bytes;
  23. } ialloc;
  24. static Block*
  25. _allocb(int size)
  26. {
  27. Block *b;
  28. uint8_t *p;
  29. int n;
  30. n = BLOCKALIGN + ROUNDUP(size+Hdrspc, BLOCKALIGN) + sizeof(Block);
  31. if((p = malloc(n)) == nil)
  32. return nil;
  33. b = (Block*)(p + n - sizeof(Block)); /* block at end of allocated space */
  34. b->base = p;
  35. b->next = nil;
  36. b->list = nil;
  37. b->free = 0;
  38. b->flag = 0;
  39. /* align base and bounds of data */
  40. b->lim = (uint8_t*)(PTR2UINT(b) & ~(BLOCKALIGN-1));
  41. /* align start of writable data, leaving space below for added headers */
  42. b->rp = b->lim - ROUNDUP(size, BLOCKALIGN);
  43. b->wp = b->rp;
  44. if(b->rp < b->base || b->lim - b->rp < size)
  45. panic("_allocb");
  46. return b;
  47. }
  48. Block*
  49. allocb(int size)
  50. {
  51. Block *b;
  52. /*
  53. * Check in a process and wait until successful.
  54. * Can still error out of here, though.
  55. */
  56. if(up == nil)
  57. panic("allocb without up: %#p\n", getcallerpc(&size));
  58. if((b = _allocb(size)) == nil){
  59. mallocsummary();
  60. panic("allocb: no memory for %d bytes\n", size);
  61. }
  62. return b;
  63. }
  64. Block*
  65. iallocb(int size)
  66. {
  67. Block *b;
  68. static int m1, m2, mp;
  69. if(ialloc.bytes > conf.ialloc){
  70. if((m1++%10000)==0){
  71. if(mp++ > 1000){
  72. active.exiting = 1;
  73. exit(0);
  74. }
  75. iprint("iallocb: limited %lud/%lud\n",
  76. ialloc.bytes, conf.ialloc);
  77. }
  78. return nil;
  79. }
  80. if((b = _allocb(size)) == nil){
  81. if((m2++%10000)==0){
  82. if(mp++ > 1000){
  83. active.exiting = 1;
  84. exit(0);
  85. }
  86. iprint("iallocb: no memory %lud/%lud\n",
  87. ialloc.bytes, conf.ialloc);
  88. }
  89. return nil;
  90. }
  91. b->flag = BINTR;
  92. ilock(&ialloc);
  93. ialloc.bytes += b->lim - b->base;
  94. iunlock(&ialloc);
  95. return b;
  96. }
  97. void
  98. freeb(Block *b)
  99. {
  100. void *dead = (void*)Bdead;
  101. uint8_t *p;
  102. if(b == nil)
  103. return;
  104. /*
  105. * drivers which perform non cache coherent DMA manage their own buffer
  106. * pool of uncached buffers and provide their own free routine.
  107. */
  108. if(b->free) {
  109. b->free(b);
  110. return;
  111. }
  112. if(b->flag & BINTR) {
  113. ilock(&ialloc);
  114. ialloc.bytes -= b->lim - b->base;
  115. iunlock(&ialloc);
  116. }
  117. p = b->base;
  118. /* poison the block in case someone is still holding onto it */
  119. b->next = dead;
  120. b->rp = dead;
  121. b->wp = dead;
  122. b->lim = dead;
  123. b->base = dead;
  124. free(p);
  125. }
  126. void
  127. checkb(Block *b, char *msg)
  128. {
  129. void *dead = (void*)Bdead;
  130. if(b == dead)
  131. panic("checkb b %s %#p", msg, b);
  132. if(b->base == dead || b->lim == dead || b->next == dead
  133. || b->rp == dead || b->wp == dead){
  134. print("checkb: base %#p lim %#p next %#p\n",
  135. b->base, b->lim, b->next);
  136. print("checkb: rp %#p wp %#p\n", b->rp, b->wp);
  137. panic("checkb dead: %s\n", msg);
  138. }
  139. if(b->base > b->lim)
  140. panic("checkb 0 %s %#p %#p", msg, b->base, b->lim);
  141. if(b->rp < b->base)
  142. panic("checkb 1 %s %#p %#p", msg, b->base, b->rp);
  143. if(b->wp < b->base)
  144. panic("checkb 2 %s %#p %#p", msg, b->base, b->wp);
  145. if(b->rp > b->lim)
  146. panic("checkb 3 %s %#p %#p", msg, b->rp, b->lim);
  147. if(b->wp > b->lim)
  148. panic("checkb 4 %s %#p %#p", msg, b->wp, b->lim);
  149. }
  150. void
  151. iallocsummary(void)
  152. {
  153. print("ialloc %lud/%lud\n", ialloc.bytes, conf.ialloc);
  154. }