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.

284 lines
6.9 KiB

  1. // list.c
  2. //
  3. // a VM growable array package
  4. #include "mbrmake.h"
  5. typedef struct _list {
  6. WORD cItems;
  7. } SLIST;
  8. typedef struct _biglist {
  9. WORD cItems;
  10. VA vaNext;
  11. } BLIST;
  12. typedef union _mixlist {
  13. SLIST sml;
  14. BLIST big;
  15. } GLIST;
  16. // this are the two VM lock numbers for the list package
  17. //
  18. #define LIST_LOCK 10
  19. #define LIST_LOCK2 11
  20. // Beware! For the system to work properly this number must
  21. // be small enough that the VM free lists won't overflow
  22. // i.e. C_ITEMS_MAX * sizeof(biggest_thing_stored) <= C_FREE_LIST_MAX
  23. //
  24. #define C_ITEMS_MAX 16
  25. #pragma intrinsic(memcpy)
  26. #define cBlock 1
  27. VA
  28. VaAddList(VA far *pvaList, LPV lpvData, WORD cbData, WORD grp)
  29. // add the given item to the list; create if necessary
  30. // return the virtual address of the most recently added item
  31. //
  32. {
  33. VA vaListNew;
  34. VA vaDirtyOnExit = vaNil;
  35. WORD cbBlock, cItems, cAlloc;
  36. GLIST far *lpList, *lpListNew;
  37. #ifdef SWAP_INFO
  38. iVMGrp = grp;
  39. #endif
  40. #if cBlock != 1
  41. if (cBlock == 0) cBlock = C_ITEMS_MAX;
  42. #endif
  43. top: // for tail recursion...
  44. // current list is empty -- create a new list with one thing in it
  45. if (*pvaList == vaNil) {
  46. if (cBlock == C_ITEMS_MAX) {
  47. *pvaList = VaAllocGrpCb(grp, cbData*cBlock + sizeof(BLIST));
  48. lpList = LpvFromVa(*pvaList, LIST_LOCK);
  49. lpList->big.vaNext = vaNil;
  50. lpList->big.cItems = 1;
  51. memcpy(((LPCH)lpList) + sizeof(BLIST), lpvData, cbData);
  52. if (vaDirtyOnExit) {
  53. DirtyVa(vaDirtyOnExit);
  54. UnlockW(LIST_LOCK+1);
  55. }
  56. DirtyVa(*pvaList);
  57. UnlockW(LIST_LOCK);
  58. return (PBYTE)*pvaList + sizeof(BLIST);
  59. }
  60. else {
  61. *pvaList = VaAllocGrpCb(grp, cbData*cBlock + sizeof(SLIST));
  62. lpList = LpvFromVa(*pvaList, LIST_LOCK);
  63. lpList->sml.cItems = 1;
  64. memcpy(((LPCH)lpList) + sizeof(SLIST), lpvData, cbData);
  65. if (vaDirtyOnExit) {
  66. DirtyVa(vaDirtyOnExit);
  67. UnlockW(LIST_LOCK+1);
  68. }
  69. DirtyVa(*pvaList);
  70. UnlockW(LIST_LOCK);
  71. return (PBYTE)*pvaList + sizeof(SLIST);
  72. }
  73. }
  74. lpList = LpvFromVa(*pvaList, LIST_LOCK);
  75. cItems = lpList->sml.cItems;
  76. // if current list has extension blocks, recursively add to the
  77. // tail of this list
  78. if (cItems >= C_ITEMS_MAX) {
  79. vaDirtyOnExit = *pvaList;
  80. lpList->big.cItems++;
  81. DirtyVa(*pvaList);
  82. LpvFromVa(*pvaList, LIST_LOCK+1); // lock in mem so address stays good
  83. pvaList = &lpList->big.vaNext;
  84. UnlockW(LIST_LOCK);
  85. goto top;
  86. }
  87. cbBlock = cItems * cbData;
  88. cAlloc = cItems % cBlock;
  89. cAlloc = cItems - cAlloc + ( cAlloc ? cBlock : 0 );
  90. // do we need to reallocate? If not do a fast insert
  91. //
  92. if (cItems < cAlloc) {
  93. if (cAlloc >= C_ITEMS_MAX) {
  94. memcpy(((LPCH)lpList) + cbBlock + sizeof(BLIST), lpvData, cbData);
  95. lpList->big.cItems++;
  96. DirtyVa(*pvaList);
  97. UnlockW(LIST_LOCK);
  98. return (PBYTE)*pvaList + cbBlock + sizeof(BLIST);
  99. }
  100. else {
  101. memcpy(((LPCH)lpList) + cbBlock + sizeof(SLIST), lpvData, cbData);
  102. lpList->sml.cItems++;
  103. DirtyVa(*pvaList);
  104. UnlockW(LIST_LOCK);
  105. return (PBYTE)*pvaList + cbBlock + sizeof(SLIST);
  106. }
  107. }
  108. // test if the next block will fit without turning the current list into
  109. // a chained list... allocate a new block & copy the old data
  110. if (cItems + cBlock < C_ITEMS_MAX) {
  111. vaListNew = VaAllocGrpCb(grp, cbBlock + cbData*cBlock + sizeof(SLIST));
  112. lpListNew = LpvFromVa(vaListNew, 0);
  113. memcpy((LPCH)lpListNew, lpList, cbBlock + sizeof(SLIST));
  114. memcpy((LPCH)lpListNew + cbBlock + sizeof(SLIST), lpvData, cbData);
  115. lpListNew->sml.cItems++;
  116. DirtyVa(vaListNew);
  117. FreeGrpVa(grp, *pvaList, cbBlock + sizeof(SLIST));
  118. *pvaList = vaListNew;
  119. if (vaDirtyOnExit) {
  120. DirtyVa(vaDirtyOnExit);
  121. UnlockW(LIST_LOCK+1);
  122. }
  123. UnlockW(LIST_LOCK);
  124. return (PBYTE)vaListNew + cbBlock + sizeof(SLIST);
  125. }
  126. // this is the last item that will go into this block,
  127. // allocate a new block c/w link field & copy the old data
  128. // set the link field to 0 for now
  129. #if cBlock != 1
  130. cBlock = C_ITEMS_MAX - cItems;
  131. #endif
  132. vaListNew = VaAllocGrpCb(grp, cbBlock + cbData*cBlock + sizeof(BLIST));
  133. lpListNew = LpvFromVa(vaListNew, 0);
  134. memcpy(lpListNew + 1 , ((SLIST FAR *)lpList) + 1, cbBlock);
  135. memcpy(((LPCH)lpListNew) + cbBlock + sizeof(BLIST), lpvData, cbData);
  136. lpListNew->big.cItems = lpList->sml.cItems + 1;
  137. lpListNew->big.vaNext = vaNil;
  138. DirtyVa(vaListNew);
  139. FreeGrpVa(grp, *pvaList, cbBlock + sizeof(SLIST));
  140. *pvaList = vaListNew;
  141. if (vaDirtyOnExit) {
  142. DirtyVa(vaDirtyOnExit);
  143. UnlockW(LIST_LOCK+1);
  144. }
  145. UnlockW(LIST_LOCK);
  146. return (PBYTE)vaListNew + cbBlock + sizeof(BLIST);
  147. }
  148. WORD
  149. CItemsList(VA vaList)
  150. // return total number of items in array
  151. //
  152. {
  153. if (vaList == vaNil)
  154. return 0;
  155. #ifdef SWAP_INFO
  156. iVMGrp = grpList;
  157. #endif
  158. return ((SLIST FAR *)LpvFromVa(vaList, 0))->cItems;
  159. }
  160. // to use the following iterator say something like
  161. //
  162. // vaPropList = cSYM.vaPropList;
  163. // while (cprop = CItemsIterate(&vaProps, &vaPropList, cBlock)) {
  164. // gPROP(vaProps);
  165. // for (;--cprop >= 0; cPROP++) {
  166. // cPROP.etc = ;
  167. //
  168. // }
  169. // }
  170. //
  171. //
  172. // The ENM_LIST, ENM_END, ENM_BREAK macros "do the right thing" with
  173. // these lists.
  174. //
  175. WORD
  176. CItemsIterate(VA FAR *vaData, VA FAR *vaNext)
  177. // give number of elements in current block and pointer to next block
  178. //
  179. {
  180. GLIST FAR *lpgList;
  181. WORD cItems, cAlloc;
  182. if (*vaNext == vaNil)
  183. return 0;
  184. #ifdef SWAP_INFO
  185. iVMGrp = grpList;
  186. #endif
  187. #if cBlock != 1
  188. if (cBlock == 0) cBlock = C_ITEMS_MAX;
  189. #endif
  190. lpgList = LpvFromVa(*vaNext, 0);
  191. cItems = lpgList->sml.cItems;
  192. if (cItems >= C_ITEMS_MAX) {
  193. *vaData = (PBYTE)*vaNext + sizeof(BLIST);
  194. *vaNext = lpgList->big.vaNext;
  195. return C_ITEMS_MAX;
  196. }
  197. if (cBlock == 0)
  198. cAlloc = C_ITEMS_MAX;
  199. else {
  200. cAlloc = cItems % cBlock;
  201. cAlloc = cItems - cAlloc + ( cAlloc ? cBlock : 0 );
  202. }
  203. if (cAlloc >= C_ITEMS_MAX)
  204. *vaData = (PBYTE)*vaNext + sizeof(BLIST);
  205. else
  206. *vaData = (PBYTE)*vaNext + sizeof(SLIST);
  207. *vaNext = 0;
  208. return cItems;
  209. }
  210. VOID
  211. FreeList(VA vaList, WORD cbData)
  212. // free up all the memory associated with this list
  213. //
  214. {
  215. (PBYTE)vaList + cbData;
  216. printf("FreeList is currently not working\n");
  217. #if 0
  218. GLIST FAR * lpgList;
  219. VA vaNextList;
  220. if (vaList == vaNil)
  221. return;
  222. top: // tail recursion
  223. lpgList = LpvFromVa(vaList, 0);
  224. if (lpgList->sml.cItems >= C_ITEMS_MAX) {
  225. vaNextList = lpgList->big.vaNext;
  226. FreeVa(vaList, C_ITEMS_MAX * cbData + sizeof(BLIST));
  227. vaList = vaNextList;
  228. goto top; // tail recursion
  229. }
  230. FreeVa(vaList, lpgList->sml.cItems * cbData + sizeof(SLIST));
  231. return;
  232. #endif
  233. }