《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

198 lines
4.4 KiB

  1. #include <stdlib.h>
  2. #include <assert.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. struct buddy2 {
  6. unsigned size;
  7. unsigned longest[1];
  8. };
  9. struct buddy2* buddy2_new( int size );
  10. void buddy2_destroy( struct buddy2* self );
  11. int buddy2_alloc(struct buddy2* self, int size);
  12. void buddy2_free(struct buddy2* self, int offset);
  13. int buddy2_size(struct buddy2* self, int offset);
  14. void buddy2_dump(struct buddy2* self);
  15. #define LEFT_LEAF(index) ((index) * 2 + 1)
  16. #define RIGHT_LEAF(index) ((index) * 2 + 2)
  17. #define PARENT(index) ( ((index) + 1) / 2 - 1)
  18. #define IS_POWER_OF_2(x) (!((x)&((x)-1)))
  19. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  20. #define ALLOC malloc
  21. #define FREE free
  22. static unsigned fixsize(unsigned size) {
  23. size |= size >> 1;
  24. size |= size >> 2;
  25. size |= size >> 4;
  26. size |= size >> 8;
  27. size |= size >> 16;
  28. return size+1;
  29. }
  30. struct buddy2* buddy2_new( int size ) {
  31. struct buddy2* self;
  32. unsigned node_size;
  33. int i;
  34. if (size < 1 || !IS_POWER_OF_2(size))
  35. return NULL;
  36. self = (struct buddy2*)ALLOC( 2 * size * sizeof(unsigned));
  37. self->size = size;
  38. node_size = size * 2;
  39. for (i = 0; i < 2 * size - 1; ++i) {
  40. if (IS_POWER_OF_2(i+1))
  41. node_size /= 2;
  42. self->longest[i] = node_size;
  43. }
  44. return self;
  45. }
  46. void buddy2_destroy( struct buddy2* self) {
  47. FREE(self);
  48. }
  49. int buddy2_alloc(struct buddy2* self, int size) {
  50. unsigned index = 0;
  51. unsigned node_size;
  52. unsigned offset = 0;
  53. if (self==NULL)
  54. return -1;
  55. if (size <= 0)
  56. size = 1;
  57. else if (!IS_POWER_OF_2(size))
  58. size = fixsize(size);
  59. if (self->longest[index] < size)
  60. return -1;
  61. for(node_size = self->size; node_size != size; node_size /= 2 ) {
  62. if (self->longest[LEFT_LEAF(index)] >= size)
  63. index = LEFT_LEAF(index);
  64. else
  65. index = RIGHT_LEAF(index);
  66. }
  67. self->longest[index] = 0;
  68. offset = (index + 1) * node_size - self->size;
  69. while (index) {
  70. index = PARENT(index);
  71. self->longest[index] =
  72. MAX(self->longest[LEFT_LEAF(index)], self->longest[RIGHT_LEAF(index)]);
  73. }
  74. return offset;
  75. }
  76. void buddy2_free(struct buddy2* self, int offset) {
  77. unsigned node_size, index = 0;
  78. unsigned left_longest, right_longest;
  79. assert(self && offset >= 0 && offset < self->size);
  80. node_size = 1;
  81. index = offset + self->size - 1;
  82. for (; self->longest[index] ; index = PARENT(index)) {
  83. node_size *= 2;
  84. if (index == 0)
  85. return;
  86. }
  87. self->longest[index] = node_size;
  88. while (index) {
  89. index = PARENT(index);
  90. node_size *= 2;
  91. left_longest = self->longest[LEFT_LEAF(index)];
  92. right_longest = self->longest[RIGHT_LEAF(index)];
  93. if (left_longest + right_longest == node_size)
  94. self->longest[index] = node_size;
  95. else
  96. self->longest[index] = MAX(left_longest, right_longest);
  97. }
  98. }
  99. int buddy2_size(struct buddy2* self, int offset) {
  100. unsigned node_size, index = 0;
  101. assert(self && offset >= 0 && offset < self->size);
  102. node_size = 1;
  103. for (index = offset + self->size - 1; self->longest[index] ; index = PARENT(index))
  104. node_size *= 2;
  105. return node_size;
  106. }
  107. void buddy2_dump(struct buddy2* self) {
  108. char canvas[65];
  109. int i,j;
  110. unsigned node_size, offset;
  111. if (self == NULL) {
  112. printf("buddy2_dump: (struct buddy2*)self == NULL");
  113. return;
  114. }
  115. if (self->size > 64) {
  116. printf("buddy2_dump: (struct buddy2*)self is too big to dump");
  117. return;
  118. }
  119. memset(canvas,'_', sizeof(canvas));
  120. node_size = self->size * 2;
  121. for (i = 0; i < 2 * self->size - 1; ++i) {
  122. if ( IS_POWER_OF_2(i+1) )
  123. node_size /= 2;
  124. if ( self->longest[i] == 0 ) {
  125. if (i >= self->size - 1) {
  126. canvas[i - self->size + 1] = '*';
  127. }
  128. else if (self->longest[LEFT_LEAF(i)] && self->longest[RIGHT_LEAF(i)]) {
  129. offset = (i+1) * node_size - self->size;
  130. for (j = offset; j < offset + node_size; ++j)
  131. canvas[j] = '*';
  132. }
  133. }
  134. }
  135. canvas[self->size] = '\0';
  136. puts(canvas);
  137. }
  138. int main() {
  139. char cmd[80];
  140. int arg;
  141. struct buddy2* buddy = buddy2_new(32);
  142. buddy2_dump(buddy);
  143. for (;;) {
  144. scanf("%s %d", cmd, &arg);
  145. if (strcmp(cmd, "alloc") == 0) {
  146. printf("allocated@%d\n", buddy2_alloc(buddy, arg));
  147. buddy2_dump(buddy);
  148. } else if (strcmp(cmd, "free") == 0) {
  149. buddy2_free(buddy, arg);
  150. buddy2_dump(buddy);
  151. } else if (strcmp(cmd, "size") == 0) {
  152. printf("size: %d\n", buddy2_size(buddy, arg));
  153. buddy2_dump(buddy);
  154. } else
  155. buddy2_dump(buddy);
  156. }
  157. }