allocb.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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 Lock;
  22. uint32_t 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. Proc *up = externup();
  52. Block *b;
  53. /*
  54. * Check in a process and wait until successful.
  55. * Can still error out of here, though.
  56. */
  57. if(up == nil)
  58. panic("allocb without up: %#p\n", getcallerpc(&size));
  59. if((b = _allocb(size)) == nil){
  60. mallocsummary();
  61. panic("allocb: no memory for %d bytes\n", size);
  62. }
  63. return b;
  64. }
  65. Block*
  66. iallocb(int size)
  67. {
  68. Block *b;
  69. static int m1, m2, mp;
  70. if(ialloc.bytes > conf.ialloc){
  71. if((m1++%10000)==0){
  72. if(mp++ > 1000){
  73. active.exiting = 1;
  74. exit(0);
  75. }
  76. iprint("iallocb: limited %lu/%lu\n",
  77. ialloc.bytes, conf.ialloc);
  78. }
  79. return nil;
  80. }
  81. if((b = _allocb(size)) == nil){
  82. if((m2++%10000)==0){
  83. if(mp++ > 1000){
  84. active.exiting = 1;
  85. exit(0);
  86. }
  87. iprint("iallocb: no memory %lu/%lu\n",
  88. ialloc.bytes, conf.ialloc);
  89. }
  90. return nil;
  91. }
  92. b->flag = BINTR;
  93. ilock(&ialloc.Lock);
  94. ialloc.bytes += b->lim - b->base;
  95. iunlock(&ialloc.Lock);
  96. return b;
  97. }
  98. void
  99. freeb(Block *b)
  100. {
  101. void *dead = (void*)Bdead;
  102. uint8_t *p;
  103. if(b == nil)
  104. return;
  105. /*
  106. * drivers which perform non cache coherent DMA manage their own buffer
  107. * pool of uncached buffers and provide their own free routine.
  108. */
  109. if(b->free) {
  110. b->free(b);
  111. return;
  112. }
  113. if(b->flag & BINTR) {
  114. ilock(&ialloc.Lock);
  115. ialloc.bytes -= b->lim - b->base;
  116. iunlock(&ialloc.Lock);
  117. }
  118. p = b->base;
  119. /* poison the block in case someone is still holding onto it */
  120. b->next = dead;
  121. b->rp = dead;
  122. b->wp = dead;
  123. b->lim = dead;
  124. b->base = dead;
  125. free(p);
  126. }
  127. void
  128. checkb(Block *b, char *msg)
  129. {
  130. void *dead = (void*)Bdead;
  131. if(b == dead)
  132. panic("checkb b %s %#p", msg, b);
  133. if(b->base == dead || b->lim == dead || b->next == dead
  134. || b->rp == dead || b->wp == dead){
  135. print("checkb: base %#p lim %#p next %#p\n",
  136. b->base, b->lim, b->next);
  137. print("checkb: rp %#p wp %#p\n", b->rp, b->wp);
  138. panic("checkb dead: %s\n", msg);
  139. }
  140. if(b->base > b->lim)
  141. panic("checkb 0 %s %#p %#p", msg, b->base, b->lim);
  142. if(b->rp < b->base)
  143. panic("checkb 1 %s %#p %#p", msg, b->base, b->rp);
  144. if(b->wp < b->base)
  145. panic("checkb 2 %s %#p %#p", msg, b->base, b->wp);
  146. if(b->rp > b->lim)
  147. panic("checkb 3 %s %#p %#p", msg, b->rp, b->lim);
  148. if(b->wp > b->lim)
  149. panic("checkb 4 %s %#p %#p", msg, b->wp, b->lim);
  150. }
  151. void
  152. iallocsummary(void)
  153. {
  154. print("ialloc %lu/%lu\n", ialloc.bytes, conf.ialloc);
  155. }