Source code of Windows XP (NT5)
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.

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