alloc.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #include "stdafx.h"
  2. #include "defs.h"
  3. // up to 100 blocks of 100,000 atoms (old)
  4. // up to 1000 blocks of 100 atoms
  5. #define M 100
  6. #define N 100
  7. U **mem;
  8. int mcount;
  9. U *free_list;
  10. int free_count;
  11. U *
  12. alloc(void)
  13. {
  14. U *p;
  15. if (free_count == 0) {
  16. if (mcount == 0)
  17. alloc_mem();
  18. else {
  19. gc();
  20. if (free_count < N * mcount / 2)
  21. alloc_mem();
  22. }
  23. if (free_count == 0)
  24. stop("atom space exhausted");
  25. }
  26. p = free_list;
  27. free_list = free_list->u.cons.cdr;
  28. free_count--;
  29. return p;
  30. }
  31. U *
  32. alloc_tensor(int nelem)
  33. {
  34. int i;
  35. U *p;
  36. p = alloc();
  37. p->k = TENSOR;
  38. p->u.tensor = (T *) malloc(sizeof (T) + nelem * sizeof (U *));
  39. if (p->u.tensor == NULL)
  40. out_of_memory();
  41. p->u.tensor->nelem = nelem;
  42. for (i = 0; i < nelem; i++)
  43. p->u.tensor->elem[i] = zero;
  44. return p;
  45. }
  46. // garbage collector
  47. void
  48. gc(void)
  49. {
  50. int i, j;
  51. U *p;
  52. // tag everything
  53. for (i = 0; i < mcount; i++) {
  54. p = mem[i];
  55. for (j = 0; j < N; j++)
  56. p[j].tag = 1;
  57. }
  58. // untag what's used
  59. untag(p0);
  60. untag(p1);
  61. untag(p2);
  62. untag(p3);
  63. untag(p4);
  64. untag(p5);
  65. untag(p6);
  66. untag(p7);
  67. untag(p8);
  68. untag(p9);
  69. untag(one);
  70. untag(zero);
  71. untag(imaginaryunit);
  72. for (i = 0; i < NSYM; i++) {
  73. untag(binding[i]);
  74. untag(arglist[i]);
  75. }
  76. for (i = 0; i < tos; i++)
  77. untag(stack[i]);
  78. for (i = (int) (frame - stack); i < TOS; i++)
  79. untag(stack[i]);
  80. // collect everything that's still tagged
  81. free_count = 0;
  82. for (i = 0; i < mcount; i++) {
  83. p = mem[i];
  84. for (j = 0; j < N; j++) {
  85. if (p[j].tag == 0)
  86. continue;
  87. // still tagged so it's unused, put on free list
  88. switch (p[j].k) {
  89. case TENSOR:
  90. free(p[j].u.tensor);
  91. break;
  92. case STR:
  93. free(p[j].u.str);
  94. break;
  95. case NUM:
  96. mfree(p[j].u.q.a);
  97. mfree(p[j].u.q.b);
  98. break;
  99. }
  100. p[j].k = CONS; // so no double free occurs above
  101. p[j].u.cons.cdr = free_list;
  102. free_list = p + j;
  103. free_count++;
  104. }
  105. }
  106. }
  107. void
  108. untag(U *p)
  109. {
  110. int i;
  111. if (iscons(p)) {
  112. do {
  113. if (p->tag == 0)
  114. return;
  115. p->tag = 0;
  116. untag(p->u.cons.car);
  117. p = p->u.cons.cdr;
  118. } while (iscons(p));
  119. untag(p);
  120. return;
  121. }
  122. if (p->tag) {
  123. p->tag = 0;
  124. if (istensor(p)) {
  125. for (i = 0; i < p->u.tensor->nelem; i++)
  126. untag(p->u.tensor->elem[i]);
  127. }
  128. }
  129. }
  130. // get memory for 100,000 atoms
  131. void
  132. alloc_mem(void)
  133. {
  134. int i;
  135. U *p;
  136. if (mcount == M)
  137. return;
  138. p = (U *) malloc(N * sizeof (struct U));
  139. if (p == NULL)
  140. return;
  141. mem[mcount++] = p;
  142. for (i = 0; i < N; i++) {
  143. p[i].k = CONS; // so no free in gc
  144. p[i].u.cons.cdr = p + i + 1;
  145. }
  146. p[N - 1].u.cons.cdr = free_list;
  147. free_list = p;
  148. free_count += N;
  149. }
  150. void
  151. print_mem_info(void)
  152. {
  153. char buf[100];
  154. sprintf(buf, "%d blocks (%d bytes/block)", N * mcount, (int) sizeof (U));
  155. printstr(buf);
  156. sprintf(buf, "%d free", free_count);
  157. printstr(buf);
  158. sprintf(buf, "%d used", N * mcount - free_count);
  159. printstr(buf);
  160. }