bin.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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 <libc.h>
  11. #include <bin.h>
  12. enum
  13. {
  14. StructAlign = sizeof(union {int64_t vl; double d; uint32_t p; void *v;
  15. struct{int64_t v;}vs; struct{double d;}ds; struct{uint32_t p;}ss; struct{void *v;}xs;})
  16. };
  17. enum
  18. {
  19. BinSize = 8*1024
  20. };
  21. struct Bin
  22. {
  23. Bin *next;
  24. uint32_t total; /* total bytes allocated in can->next */
  25. uintptr pos;
  26. uintptr end;
  27. uintptr v; /* last value allocated */
  28. uint8_t body[BinSize];
  29. };
  30. /*
  31. * allocator which allows an entire set to be freed at one time
  32. */
  33. static Bin*
  34. mkbin(Bin *bin, uint32_t size)
  35. {
  36. Bin *b;
  37. size = ((size << 1) + (BinSize - 1)) & ~(BinSize - 1);
  38. b = malloc(sizeof(Bin) + size - BinSize);
  39. if(b == nil)
  40. return nil;
  41. b->next = bin;
  42. b->total = 0;
  43. if(bin != nil)
  44. b->total = bin->total + bin->pos - (uintptr)bin->body;
  45. b->pos = (uintptr)b->body;
  46. b->end = b->pos + size;
  47. return b;
  48. }
  49. void*
  50. binalloc(Bin **bin, uint32_t size, int zero)
  51. {
  52. Bin *b;
  53. uintptr p;
  54. if(size == 0)
  55. size = 1;
  56. b = *bin;
  57. if(b == nil){
  58. b = mkbin(nil, size);
  59. if(b == nil)
  60. return nil;
  61. *bin = b;
  62. }
  63. p = b->pos;
  64. p = (p + (StructAlign - 1)) & ~(StructAlign - 1);
  65. if(p + size > b->end){
  66. b = mkbin(b, size);
  67. if(b == nil)
  68. return nil;
  69. *bin = b;
  70. p = b->pos;
  71. }
  72. b->pos = p + size;
  73. b->v = p;
  74. if(zero)
  75. memset((void*)p, 0, size);
  76. return (void*)p;
  77. }
  78. void*
  79. bingrow(Bin **bin, void *op, uint32_t osize, uint32_t size, int zero)
  80. {
  81. Bin *b;
  82. void *np;
  83. uintptr p;
  84. p = (uintptr)op;
  85. b = *bin;
  86. if(b != nil && p == b->v && p + size <= b->end){
  87. b->pos = p + size;
  88. if(zero)
  89. memset((char*)p + osize, 0, size - osize);
  90. return op;
  91. }
  92. np = binalloc(bin, size, zero);
  93. if(np == nil)
  94. return nil;
  95. memmove(np, op, osize);
  96. return np;
  97. }
  98. void
  99. binfree(Bin **bin)
  100. {
  101. Bin *last;
  102. while(*bin != nil){
  103. last = *bin;
  104. *bin = (*bin)->next;
  105. last->pos = (uintptr)last->body;
  106. free(last);
  107. }
  108. }