Leaked source code of windows server 2003
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.

260 lines
6.5 KiB

  1. /*
  2. * bitmap allocation routines.
  3. *
  4. * utility routines to manage a bit-mapped free list, and find
  5. * free sections
  6. */
  7. #include <precomp.h>
  8. #ifdef REWRITE
  9. Timings on windiff indicated that not much time was spent here, so it wasn't
  10. worth the rewrite. BUT - could do much better. To find the first bit in
  11. a dword mask it with FFFF0000 to see which half the bit is in and then
  12. go on by five binary chops. (You need to wory about the byte order and bit order
  13. of the bitmap - and I haven't - but the code is something like
  14. bitnum = 0
  15. if (dw&0xffff0000) {bitnum +=16; dw >>=16}
  16. if (dw&0x0000ff00) {bitnum +=8; dw >>=8}
  17. if (dw&0x000000f0) {bitnum +=4; dw >>=4}
  18. if (dw&0x0000000c) {bitnum +=2; dw >>=2}
  19. if (dw&0x00000002) {bitnum +=1; dw >>=1}
  20. Forget the "find the biggest section" stuff - change the spec and just
  21. return(a place if we find enough it or fail.
  22. Special case to search more efficiently for sections of up to 32 bits.
  23. (For mamory heap usage this means that we will have one heap that handles
  24. requests from (say) 16 to 512 bytes (16 bytes per bit) and another heap
  25. for requests (say) 513 to 4096 bytes (128 bits per byte) and so on.
  26. In this case create a mask in a dword with the number of bits set that
  27. we are looking for (keep this we might need it again), shift it the
  28. number of bits to correspond to the start bit that we found (it's two
  29. dwords by now as it will likely shift across a dword boundary) and then
  30. just mask to see if all those bits are on i.e. if ((mask & dw)==mask)
  31. Later. Maybe.
  32. Laurie
  33. #endif //REWRITE
  34. /* routines to manage bitmapped freelists. Each map is an array
  35. * of unsigned longs where bit 0 of the first long represents
  36. * block 1
  37. */
  38. BOOL gbit_set(DWORD FAR * map, long blknr, long nblks, BOOL op_set);
  39. /* initialise a pre-allocated map of ulongs to represent a free
  40. * area of nblks
  41. */
  42. void APIENTRY
  43. gbit_init(DWORD FAR * map, long nblks)
  44. {
  45. long i;
  46. long leftover = nblks % 32;
  47. long blks = nblks / 32;
  48. DWORD last = 0;
  49. for (i=0; i < blks; i++) {
  50. map[i] = 0xffffffff;
  51. }
  52. for (i = 0; i < leftover; i++) {
  53. last = (last << 1) | 1;
  54. }
  55. if(leftover)
  56. map[blks] = last;
  57. }
  58. /* mark a region starting at blknr for nblks, as busy (ie 0) */
  59. BOOL APIENTRY
  60. gbit_alloc(DWORD FAR * map, long blknr, long nblks)
  61. {
  62. return(gbit_set(map, blknr, nblks, FALSE));
  63. }
  64. /* mark region - if op_set, to 1s, otherwise to 0s */
  65. BOOL
  66. gbit_set(DWORD FAR * map, long blknr, long nblks, BOOL op_set)
  67. {
  68. long first;
  69. long last;
  70. long fullwords;
  71. long startbit, startword;
  72. long i;
  73. DWORD dword = 0;
  74. blknr--;
  75. first = min(32 - (blknr % 32), nblks);
  76. nblks -= first;
  77. last = nblks % 32;
  78. fullwords = (nblks - last) / 32;
  79. startword = blknr / 32;
  80. startbit = blknr % 32;
  81. for (i = 0; i < first; i++) {
  82. dword = (dword << 1) | 1;
  83. }
  84. dword <<= startbit;
  85. if (op_set) {
  86. map[startword] |= dword;
  87. dword = 0xffffffff;
  88. } else {
  89. map[startword] &= ~dword;
  90. dword = 0;
  91. }
  92. startword++;
  93. for (i = 0; i < fullwords; i++) {
  94. map[startword+i] = dword;
  95. }
  96. startword += fullwords;
  97. for(i = 0, dword = 0; i < last; i++) {
  98. dword = (dword << 1) | 1;
  99. }
  100. if (last) {
  101. if (op_set) {
  102. map[startword] |= dword;
  103. } else {
  104. map[startword] &= ~dword;
  105. }
  106. }
  107. return(TRUE);
  108. }
  109. /* mark region of nblks starting at blknr to 0s - ie not busy */
  110. BOOL APIENTRY
  111. gbit_free(DWORD FAR * map, long blknr, long nblks)
  112. {
  113. return(gbit_set(map, blknr, nblks, TRUE));
  114. }
  115. /* find a free segment (ie contiguous sequence of 1s) of nblks in length.
  116. * If not found, find longest sequence. Store address of segment in *blknr.
  117. *
  118. * Return value is nr of blks in sequence found. Region is *not* marked busy.
  119. */
  120. long APIENTRY
  121. gbit_findfree(DWORD FAR* map, long nblks, long mapsize, long FAR * blknr)
  122. {
  123. long curblk, startblk, len, i;
  124. long startbit, nfull, nlast, nbitsleft;
  125. DWORD mask;
  126. long mapblks = (mapsize + 31) / 32;
  127. long aubegin = 0, aulen = 0;
  128. long curbit = 0;
  129. /* main loop looking at segments */
  130. for (curblk = 0; curblk < mapblks; ) {
  131. loop:
  132. /* loop finding first 1 */
  133. for (; curblk < mapblks; curblk++, curbit = 0) {
  134. if (map[curblk] > 0) {
  135. break;
  136. }
  137. }
  138. if (curblk >= mapblks)
  139. break;
  140. /* find first 1 in this long */
  141. startblk = curblk;
  142. for (mask = 1, i = 0; i < curbit; i++) {
  143. mask <<= 1;
  144. }
  145. for(; curbit < 32; curbit++, mask <<= 1) {
  146. if (map[curblk] & mask) {
  147. break;
  148. }
  149. }
  150. if (curbit >= 32) {
  151. /* abandon this word - start again with next word */
  152. curblk++;
  153. curbit = 0;
  154. goto loop;
  155. }
  156. /* we've now found a 1 - calc remaining
  157. * bits in this word, complete words etc required.
  158. */
  159. startbit = curbit;
  160. nbitsleft = min( (32 - curbit), nblks);
  161. nfull = (nblks - nbitsleft) / 32;
  162. nlast = (nblks - nbitsleft) % 32;
  163. /* check for required sequence within this word */
  164. for (i = 0; i < nbitsleft; i++, curbit++, mask <<= 1) {
  165. if ((map[curblk] & mask) == 0) {
  166. /* abandon and start again - start
  167. * next pass at curbit in same word
  168. */
  169. /* store free region if longest yet */
  170. if (i > aulen) {
  171. aulen = i;
  172. aubegin = curblk * 32 + startbit +1;
  173. }
  174. goto loop;
  175. }
  176. }
  177. /* check for nfull full words */
  178. for (curblk++; curblk <= startblk + nfull; curblk++) {
  179. if (curblk >= mapblks) {
  180. /* end of map - abandon here and exit at top
  181. * of loop
  182. */
  183. len = nbitsleft +
  184. ((curblk - (startblk + 1)) * 32);
  185. if (len > aulen) {
  186. aubegin = startblk * 32 + startbit + 1;
  187. aulen = len;
  188. }
  189. goto loop;
  190. }
  191. if (map[curblk] != 0xffffffff) {
  192. /* not a full word - start again at this bit */
  193. len = 0;
  194. curbit = 0;
  195. for (mask = 1; mask & map[curblk]; mask <<= 1) {
  196. len++;
  197. curbit++;
  198. }
  199. len += nbitsleft +
  200. (curblk - (startblk+ 1)) * 32;
  201. if (len > aulen) {
  202. aulen = len;
  203. aubegin = startblk * 32 + startbit + 1;
  204. }
  205. /* continue with current blk, bit */
  206. goto loop;
  207. }
  208. }
  209. /* left-over bits required in last word */
  210. mask = 1;
  211. for (curbit = 0; curbit < nlast; curbit++, mask <<= 1) {
  212. if ((map[curblk] & mask) == 0) {
  213. len = nbitsleft + (nfull * 32);
  214. len += curbit;
  215. if (len > aulen) {
  216. aulen = len;
  217. aubegin = startblk * 32 + startbit + 1;
  218. }
  219. goto loop;
  220. }
  221. }
  222. /* ok - found a block big enough! */
  223. aubegin = startblk * 32 + startbit + 1;
  224. *blknr = aubegin;
  225. return(nblks);
  226. }
  227. /* end of map - return longest sequence */
  228. *blknr = aubegin;
  229. return(aulen);
  230. }