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.

814 lines
24 KiB

  1. /*++ BUILD Version: 0009 // Increment this if a change has global effects
  2. Copyright (c) 1987-1993 Microsoft Corporation
  3. Module Name:
  4. midatlas.c
  5. Abstract:
  6. This module defines the data structure used in mapping MIDS to the corresponding requests/
  7. contexts associated with them.
  8. Author:
  9. Balan Sethu Raman (SethuR) 26-Aug-95 Created
  10. Notes:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include "midatlsp.h"
  15. VOID
  16. RxInitializeMidMapFreeList (
  17. struct _MID_MAP_ *pMidMap
  18. );
  19. VOID
  20. RxUninitializeMidMap (
  21. struct _MID_MAP_ *pMidMap,
  22. PCONTEXT_DESTRUCTOR pContextDestructor
  23. );
  24. #ifdef ALLOC_PRAGMA
  25. #pragma alloc_text(PAGE, RxInitializeMidMapFreeList)
  26. #pragma alloc_text(PAGE, RxCreateMidAtlas)
  27. #pragma alloc_text(PAGE, RxUninitializeMidMap)
  28. #pragma alloc_text(PAGE, RxDestroyMidAtlas)
  29. #endif
  30. #define ENTRY_TYPE_FREE_MID_LIST (0x1)
  31. #define ENTRY_TYPE_VALID_CONTEXT (0x2)
  32. #define ENTRY_TYPE_MID_MAP (0x3)
  33. #define ENTRY_TYPE_MASK (0x3)
  34. #define MID_MAP_FLAGS_CAN_BE_EXPANDED (0x1)
  35. #define MID_MAP_FLAGS_FREE_POOL (0x2)
  36. //INLINE ULONG _GetEntryType(PVOID pEntry)
  37. #define _GetEntryType(pEntry) \
  38. ((ULONG)((ULONG_PTR)(pEntry)) & ENTRY_TYPE_MASK)
  39. //INLINE PVOID _GetEntryPointer(PVOID pEntry)
  40. #define _GetEntryPointer(pEntry) \
  41. ((PVOID)((ULONG_PTR)(pEntry) & ~ENTRY_TYPE_MASK))
  42. #define _MakeEntry(pContext,EntryType) \
  43. (PVOID)((ULONG_PTR)(pContext) | (EntryType))
  44. //INLINE PMID_MAP _GetFirstMidMap()
  45. /*++
  46. Routine Description:
  47. This first MID_MAP instance in the list
  48. Return Value:
  49. a valid PMID_MAP, NULL if none exists.
  50. Notes:
  51. This routine assumes that the necessary concurrency control action has been taken
  52. --*/
  53. #define _GetFirstMidMap(pListHead) \
  54. (IsListEmpty(pListHead) \
  55. ? NULL \
  56. : (PMID_MAP) \
  57. (CONTAINING_RECORD((pListHead)->Flink, \
  58. MID_MAP, \
  59. MidMapList)))
  60. //INLINE PSMBCEDB_SERVER_ENTRY GetNextMidMap(PLIST_ENTRY pListHead, PMID_MAP pMidMap)
  61. /*++
  62. Routine Description:
  63. This routine returns the next MID_MAP in the list
  64. Arguments:
  65. pListHead - the list of MID_MAP's
  66. pMidMap - the current instance
  67. Return Value:
  68. a valid PMID_MAP, NULL if none exists.
  69. Notes:
  70. This routine assumes that the necessary concurrency control action has been taken
  71. --*/
  72. #define _GetNextMidMap(pListHead,pMidMap) \
  73. (((pMidMap)->MidMapList.Flink == pListHead) \
  74. ? NULL \
  75. : (PMID_MAP) \
  76. (CONTAINING_RECORD((pMidMap)->MidMapList.Flink, \
  77. MID_MAP, \
  78. MidMapList)))
  79. //INLINE VOID _AddMidMap(
  80. // PLIST_ENTRY pListHead,
  81. // PMID_MAP pMidMap)
  82. /*++
  83. Routine Description:
  84. This routine adds a MID_MAP instance to a list
  85. Arguments:
  86. pListHead - the list of MID_MAP's
  87. pMidMap - the MID_MAP to be added
  88. --*/
  89. #define _AddMidMap(pListHead,pMidMap) \
  90. { \
  91. PMID_MAP pPredecessor; \
  92. pPredecessor = _GetFirstMidMap(pListHead); \
  93. while (pPredecessor != NULL) { \
  94. if (pPredecessor->Level < pMidMap->Level) { \
  95. pPredecessor = _GetNextMidMap(pListHead,pPredecessor); \
  96. } else { \
  97. pPredecessor = (PMID_MAP) \
  98. CONTAINING_RECORD( \
  99. pPredecessor->MidMapList.Blink, \
  100. MID_MAP, \
  101. MidMapList); \
  102. break; \
  103. } \
  104. } \
  105. \
  106. if (pPredecessor == NULL) { \
  107. InsertTailList(pListHead,&((pMidMap)->MidMapList)); \
  108. } else { \
  109. (pMidMap)->MidMapList.Flink = pPredecessor->MidMapList.Flink; \
  110. pPredecessor->MidMapList.Flink = &(pMidMap)->MidMapList; \
  111. \
  112. (pMidMap)->MidMapList.Blink = &pPredecessor->MidMapList; \
  113. (pMidMap)->MidMapList.Flink->Blink = &(pMidMap)->MidMapList; \
  114. } \
  115. }
  116. //INLINE VOID _RemoveMidMap(PMID_MAP pMidMap)
  117. /*++
  118. Routine Description:
  119. This routine removes a MID_MAP instance from the list
  120. Arguments:
  121. pMidMap - the MID_MAP instance to be removed
  122. --*/
  123. #define _RemoveMidMap(pMidMap) \
  124. RemoveEntryList(&(pMidMap)->MidMapList)
  125. VOID
  126. RxInitializeMidMapFreeList(PMID_MAP pMidMap)
  127. /*++
  128. Routine Description:
  129. This routine initializes a MID_MAP data structure.
  130. Arguments:
  131. pMidMap - the MID_MAP instance to be initialized.
  132. Notes:
  133. --*/
  134. {
  135. USHORT i;
  136. PVOID *pEntryValue = (PVOID *)&pMidMap->Entries[1];
  137. PVOID *pEntriesPointer = (PVOID *)&pMidMap->Entries;
  138. PAGED_CODE();
  139. //DbgPrint("RxInitializeMidMapFreeList .. Entry\n");
  140. if (pMidMap->MaximumNumberOfMids > 0) {
  141. pMidMap->pFreeMidListHead = pMidMap->Entries;
  142. for (i = 1; i <= pMidMap->MaximumNumberOfMids - 1;i++,pEntryValue++) {
  143. *pEntriesPointer++ = _MakeEntry(pEntryValue,ENTRY_TYPE_FREE_MID_LIST);
  144. }
  145. *pEntriesPointer = _MakeEntry(NULL,ENTRY_TYPE_FREE_MID_LIST);
  146. }
  147. //DbgPrint("RxInitializeMidMapFreeList .. Exit\n");
  148. }
  149. PRX_MID_ATLAS
  150. RxCreateMidAtlas(
  151. USHORT MaximumNumberOfMids,
  152. USHORT MidsAllocatedAtStart)
  153. /*++
  154. Routine Description:
  155. This routine allocates a new instance of MID_ATLAS data structure.
  156. Arguments:
  157. MaximumNumberOfMids - the maximum number of MIDS in the atlas.
  158. MidsAllocatedAtStart - the number of MIDS allocated at start
  159. Notes:
  160. --*/
  161. {
  162. PRX_MID_ATLAS pMidAtlas;
  163. PMID_MAP pMidMap;
  164. ULONG AtlasSize;
  165. USHORT MidsAllocatedRoundedToPowerOf2;
  166. USHORT MaximumMidsRoundedToPowerOf2;
  167. UCHAR MidFieldWidth,MaximumMidFieldWidth;
  168. PAGED_CODE();
  169. // Round off the Mids allocated at Start to a power of two
  170. MaximumMidsRoundedToPowerOf2 = 0x100;
  171. MaximumMidFieldWidth = 8;
  172. if (MaximumMidsRoundedToPowerOf2 != MaximumNumberOfMids) {
  173. if (MaximumNumberOfMids > MaximumMidsRoundedToPowerOf2) {
  174. while (MaximumNumberOfMids > MaximumMidsRoundedToPowerOf2) {
  175. MaximumMidsRoundedToPowerOf2 = MaximumMidsRoundedToPowerOf2 << 1;
  176. MaximumMidFieldWidth++;
  177. }
  178. } else {
  179. while (MaximumNumberOfMids < MaximumMidsRoundedToPowerOf2) {
  180. MaximumMidsRoundedToPowerOf2 = MaximumMidsRoundedToPowerOf2 >> 1;
  181. MaximumMidFieldWidth--;
  182. }
  183. MaximumMidFieldWidth++;
  184. MaximumMidsRoundedToPowerOf2 = MaximumMidsRoundedToPowerOf2 << 1;
  185. }
  186. }
  187. MidsAllocatedRoundedToPowerOf2 = 0x100;
  188. MidFieldWidth = 8;
  189. if (MidsAllocatedRoundedToPowerOf2 != MidsAllocatedAtStart) {
  190. if (MidsAllocatedAtStart > MidsAllocatedRoundedToPowerOf2) {
  191. while (MidsAllocatedAtStart > MidsAllocatedRoundedToPowerOf2) {
  192. MidsAllocatedRoundedToPowerOf2 = MidsAllocatedRoundedToPowerOf2 << 1;
  193. MidFieldWidth++;
  194. }
  195. } else {
  196. while (MidsAllocatedAtStart < MidsAllocatedRoundedToPowerOf2) {
  197. MidsAllocatedRoundedToPowerOf2 = MidsAllocatedRoundedToPowerOf2 >> 1;
  198. MidFieldWidth--;
  199. }
  200. MidFieldWidth++;
  201. MidsAllocatedRoundedToPowerOf2 = MidsAllocatedRoundedToPowerOf2 << 1;
  202. }
  203. }
  204. AtlasSize = sizeof(RX_MID_ATLAS) +
  205. FIELD_OFFSET(MID_MAP,Entries);
  206. if (MaximumNumberOfMids == MidsAllocatedAtStart) {
  207. AtlasSize += (sizeof(PVOID) * MidsAllocatedAtStart);
  208. } else {
  209. AtlasSize += (sizeof(PVOID) * MidsAllocatedRoundedToPowerOf2);
  210. }
  211. pMidAtlas = (PRX_MID_ATLAS)RxAllocatePoolWithTag(
  212. NonPagedPool,
  213. AtlasSize,
  214. RXCE_MIDATLAS_POOLTAG);
  215. if (pMidAtlas != NULL) {
  216. pMidMap = (PMID_MAP)(pMidAtlas + 1);
  217. pMidMap->Flags = 0;
  218. pMidAtlas->MaximumNumberOfMids = MaximumNumberOfMids;
  219. pMidAtlas->MidsAllocated = MidsAllocatedAtStart;
  220. pMidAtlas->NumberOfMidsInUse = 0;
  221. pMidAtlas->NumberOfMidsDiscarded = 0;
  222. pMidAtlas->MaximumMidFieldWidth = MaximumMidFieldWidth;
  223. pMidMap->MaximumNumberOfMids = MidsAllocatedAtStart;
  224. pMidMap->NumberOfMidsInUse = 0;
  225. pMidMap->BaseMid = 0;
  226. pMidMap->IndexMask = MidsAllocatedRoundedToPowerOf2 - 1;
  227. pMidMap->IndexAlignmentCount = 0;
  228. pMidMap->IndexFieldWidth = MidFieldWidth;
  229. pMidMap->Level = 1;
  230. InitializeListHead(&pMidAtlas->MidMapFreeList);
  231. InitializeListHead(&pMidAtlas->MidMapExpansionList);
  232. RxInitializeMidMapFreeList(pMidMap);
  233. _AddMidMap(&pMidAtlas->MidMapFreeList,pMidMap);
  234. pMidAtlas->pRootMidMap = pMidMap;
  235. if (MaximumNumberOfMids > MidsAllocatedAtStart) {
  236. // Round off the maximum number of MIDS to determine the level and the
  237. // size of the quantum ( allocation increments)
  238. pMidMap->Flags |= MID_MAP_FLAGS_CAN_BE_EXPANDED;
  239. pMidAtlas->MidQuantum = 32;
  240. pMidAtlas->MidQuantumFieldWidth = 5;
  241. MaximumMidsRoundedToPowerOf2 = MaximumMidsRoundedToPowerOf2 >> (pMidMap->IndexAlignmentCount + 5);
  242. if (MaximumMidsRoundedToPowerOf2 > 0) {
  243. pMidAtlas->NumberOfLevels = 3;
  244. } else {
  245. pMidAtlas->NumberOfLevels = 2;
  246. }
  247. } else {
  248. pMidAtlas->MidQuantum = 0;
  249. pMidAtlas->NumberOfLevels = 1;
  250. pMidMap->Flags &= ~MID_MAP_FLAGS_CAN_BE_EXPANDED;
  251. }
  252. }
  253. //DbgPrint("RxAllocatMidAtlas .. Exit (pMidAtlas) %lx\n",pMidAtlas);
  254. return pMidAtlas;
  255. }
  256. VOID
  257. RxUninitializeMidMap(
  258. PMID_MAP pMidMap,
  259. PCONTEXT_DESTRUCTOR pContextDestructor)
  260. /*++
  261. Routine Description:
  262. This routine uninitializes a MID_MAP data structure.
  263. Arguments:
  264. pMidMap -- the MID_MAP instance to be uninitialized.
  265. pContextDestructor -- the context destructor
  266. Notes:
  267. --*/
  268. {
  269. USHORT i;
  270. ULONG EntryType;
  271. PAGED_CODE();
  272. //DbgPrint("RxUninitializeMidMap .. Entry No.Of MIDS in Use %ld\n",pMidMap->NumberOfMidsInUse);
  273. RxLog(("_UninitMidMap .. num= %ld\n",pMidMap->NumberOfMidsInUse));
  274. RxWmiLog(LOG,
  275. RxUninitializeMidMap,
  276. LOGXSHORT(pMidMap->NumberOfMidsInUse));
  277. for (i = 0; i < pMidMap->MaximumNumberOfMids; i++) {
  278. PMID_MAP pChildMidMap;
  279. EntryType = _GetEntryType(pMidMap->Entries[i]);
  280. switch (EntryType) {
  281. case ENTRY_TYPE_MID_MAP :
  282. {
  283. pChildMidMap = (PMID_MAP)_GetEntryPointer(pMidMap->Entries[i]);
  284. RxUninitializeMidMap(pChildMidMap,pContextDestructor);
  285. }
  286. break;
  287. case ENTRY_TYPE_VALID_CONTEXT :
  288. {
  289. if (pContextDestructor != NULL) {
  290. PVOID pContext;
  291. pContext = _GetEntryPointer(pMidMap->Entries[i]);
  292. (pContextDestructor)(pContext);
  293. }
  294. }
  295. break;
  296. default:
  297. break;
  298. }
  299. }
  300. if (pMidMap->Flags & MID_MAP_FLAGS_FREE_POOL) {
  301. RxFreePool(pMidMap);
  302. }
  303. //DbgPrint("RxUninitializeMidMap .. Exit\n");
  304. }
  305. VOID
  306. RxDestroyMidAtlas(
  307. PRX_MID_ATLAS pMidAtlas,
  308. PCONTEXT_DESTRUCTOR pContextDestructor)
  309. /*++
  310. Routine Description:
  311. This routine frees a MID_ATLAS instance. As a side effect it invokes the
  312. passed in context destructor on every valid context in the MID_ATLAS
  313. Arguments:
  314. pMidAtlas - the MID_ATLAS instance to be freed.
  315. PCONTEXT_DESTRUCTOR - the associated context destructor
  316. Notes:
  317. --*/
  318. {
  319. PAGED_CODE();
  320. //DbgPrint("RxFreeMidAtlas .. Entry\n");
  321. RxUninitializeMidMap(pMidAtlas->pRootMidMap,pContextDestructor);
  322. RxFreePool(pMidAtlas);
  323. //DbgPrint("RxFreeMidAtlas .. Exit\n");
  324. }
  325. PVOID
  326. RxMapMidToContext(
  327. PRX_MID_ATLAS pMidAtlas,
  328. USHORT Mid)
  329. /*++
  330. Routine Description:
  331. This routine maps a MID to its associated context in a MID_ATLAS.
  332. Arguments:
  333. pMidAtlas - the MID_ATLAS instance.
  334. Mid - the MId to be mapped
  335. Return value:
  336. the associated context, NULL if none exists
  337. Notes:
  338. --*/
  339. {
  340. ULONG EntryType;
  341. PMID_MAP pMidMap = pMidAtlas->pRootMidMap;
  342. PVOID pContext;
  343. ULONG Index;
  344. //DbgPrint("RxMapMidToContext Mid %lx ",Mid);
  345. for (;;) {
  346. Index = (Mid & pMidMap->IndexMask) >> pMidMap->IndexAlignmentCount;
  347. if( Index >= pMidMap->MaximumNumberOfMids ) {
  348. pContext = NULL;
  349. break;
  350. }
  351. pContext = pMidMap->Entries[Index];
  352. EntryType = _GetEntryType(pContext);
  353. pContext = (PVOID)_GetEntryPointer(pContext);
  354. if (EntryType == ENTRY_TYPE_VALID_CONTEXT) {
  355. break;
  356. } else if (EntryType == ENTRY_TYPE_FREE_MID_LIST) {
  357. pContext = NULL;
  358. break;
  359. } else if (EntryType == ENTRY_TYPE_MID_MAP) {
  360. pMidMap = (PMID_MAP)pContext;
  361. } else {
  362. pContext = NULL;
  363. break;
  364. }
  365. }
  366. //DbgPrint("Context %lx \n",pContext);
  367. return pContext;
  368. }
  369. NTSTATUS
  370. RxMapAndDissociateMidFromContext(
  371. PRX_MID_ATLAS pMidAtlas,
  372. USHORT Mid,
  373. PVOID *pContextPointer)
  374. /*++
  375. Routine Description:
  376. This routine maps a MID to its associated context in a MID_ATLAS.
  377. Arguments:
  378. pMidAtlas - the MID_ATLAS instance.
  379. Mid - the MId to be mapped
  380. Return value:
  381. the associated context, NULL if none exists
  382. Notes:
  383. --*/
  384. {
  385. ULONG EntryType;
  386. PMID_MAP pMidMap = pMidAtlas->pRootMidMap;
  387. PVOID pContext;
  388. PVOID *pEntry;
  389. //DbgPrint("RxMapAndDissociateMidFromContext Mid %lx ",Mid);
  390. for (;;) {
  391. pEntry = &pMidMap->Entries[(Mid & pMidMap->IndexMask) >> pMidMap->IndexAlignmentCount];
  392. pContext = *pEntry;
  393. EntryType = _GetEntryType(pContext);
  394. pContext = (PVOID)_GetEntryPointer(pContext);
  395. if (EntryType == ENTRY_TYPE_VALID_CONTEXT) {
  396. pMidMap->NumberOfMidsInUse--;
  397. if (pMidMap->pFreeMidListHead == NULL) {
  398. _RemoveMidMap(pMidMap);
  399. _AddMidMap(&pMidAtlas->MidMapFreeList,pMidMap);
  400. }
  401. *pEntry = _MakeEntry(pMidMap->pFreeMidListHead,ENTRY_TYPE_FREE_MID_LIST);
  402. pMidMap->pFreeMidListHead = pEntry;
  403. break;
  404. } else if (EntryType == ENTRY_TYPE_FREE_MID_LIST) {
  405. pContext = NULL;
  406. break;
  407. } else if (EntryType == ENTRY_TYPE_MID_MAP) {
  408. pMidMap = (PMID_MAP)pContext;
  409. }
  410. }
  411. pMidAtlas->NumberOfMidsInUse--;
  412. //DbgPrint("Context %lx\n",pContext);
  413. *pContextPointer = pContext;
  414. return STATUS_SUCCESS;
  415. }
  416. NTSTATUS
  417. RxReassociateMid(
  418. PRX_MID_ATLAS pMidAtlas,
  419. USHORT Mid,
  420. PVOID pNewContext)
  421. /*++
  422. Routine Description:
  423. This routine maps a MID to its associated context in a MID_ATLAS.
  424. Arguments:
  425. pMidAtlas - the MID_ATLAS instance.
  426. Mid - the MId to be mapped
  427. pNewContext - the new context
  428. Return value:
  429. the associated context, NULL if none exists
  430. Notes:
  431. --*/
  432. {
  433. ULONG EntryType;
  434. PMID_MAP pMidMap = pMidAtlas->pRootMidMap;
  435. PVOID pContext;
  436. //DbgPrint("RxReassociateMid Mid %lx ",Mid);
  437. for (;;) {
  438. pContext = pMidMap->Entries[(Mid & pMidMap->IndexMask) >> pMidMap->IndexAlignmentCount];
  439. EntryType = _GetEntryType(pContext);
  440. pContext = (PVOID)_GetEntryPointer(pContext);
  441. if (EntryType == ENTRY_TYPE_VALID_CONTEXT) {
  442. pMidMap->Entries[(Mid & pMidMap->IndexMask) >> pMidMap->IndexAlignmentCount]
  443. = _MakeEntry(pNewContext,ENTRY_TYPE_VALID_CONTEXT);
  444. break;
  445. } else if (EntryType == ENTRY_TYPE_FREE_MID_LIST) {
  446. ASSERT(!"Valid MID Atlas");
  447. break;
  448. } else if (EntryType == ENTRY_TYPE_MID_MAP) {
  449. pMidMap = (PMID_MAP)pContext;
  450. }
  451. }
  452. //DbgPrint("New COntext %lx\n",pNewContext);
  453. return STATUS_SUCCESS;
  454. }
  455. NTSTATUS
  456. RxAssociateContextWithMid(
  457. PRX_MID_ATLAS pMidAtlas,
  458. PVOID pContext,
  459. PUSHORT pNewMid)
  460. /*++
  461. Routine Description:
  462. This routine initializes a MID_MAP data structure.
  463. Arguments:
  464. pMidMap - the MID_MAP instance to be initialized.
  465. Return Value:
  466. STATUS_SUCCESS if successful, otherwise one of the following errors
  467. STATUS_INSUFFICIENT_RESOURCES
  468. STATUS_UNSUCCESSFUL -- no mid could be associated
  469. Notes:
  470. --*/
  471. {
  472. NTSTATUS Status;
  473. PMID_MAP pMidMap;
  474. PVOID *pContextPointer;
  475. // Reject requests that exceed our MID limit
  476. if( pMidAtlas->NumberOfMidsInUse >= pMidAtlas->MaximumNumberOfMids )
  477. {
  478. return STATUS_UNSUCCESSFUL;
  479. }
  480. //DbgPrint("RxAssociateContextWithMid Context %lx ",pContext);
  481. // Scan the list of MID_MAP's which have free entries in them.
  482. if ((pMidMap = _GetFirstMidMap(&pMidAtlas->MidMapFreeList)) != NULL) {
  483. ASSERT(pMidMap->pFreeMidListHead != _MakeEntry(NULL,ENTRY_TYPE_FREE_MID_LIST));
  484. pMidMap->NumberOfMidsInUse++;
  485. pContextPointer = pMidMap->pFreeMidListHead;
  486. pMidMap->pFreeMidListHead = _GetEntryPointer(*(pMidMap->pFreeMidListHead));
  487. *pContextPointer = _MakeEntry(pContext,ENTRY_TYPE_VALID_CONTEXT);
  488. *pNewMid = ((USHORT)
  489. (pContextPointer - (PVOID *)&pMidMap->Entries)
  490. << pMidMap->IndexAlignmentCount) |
  491. pMidMap->BaseMid;
  492. // Check if the MID_MAP needs to be removed from the list of MID_MAP's with
  493. // free entries
  494. if (pMidMap->pFreeMidListHead == NULL) {
  495. _RemoveMidMap(pMidMap);
  496. // Check if it can be added to the expansion list.
  497. if (pMidAtlas->NumberOfLevels > pMidMap->Level) {
  498. _AddMidMap(&pMidAtlas->MidMapExpansionList,pMidMap);
  499. }
  500. }
  501. Status = STATUS_SUCCESS;
  502. } else if ((pMidMap = _GetFirstMidMap(&pMidAtlas->MidMapExpansionList)) != NULL) {
  503. PMID_MAP pNewMidMap;
  504. USHORT i;
  505. ULONG NewMidMapSize;
  506. // Locate the index in the mid map for the new mid map
  507. pMidMap = _GetFirstMidMap(&pMidAtlas->MidMapExpansionList);
  508. while (pMidMap != NULL) {
  509. for (i = 0; i < pMidMap->MaximumNumberOfMids; i++) {
  510. if (_GetEntryType(pMidMap->Entries[i]) != ENTRY_TYPE_MID_MAP) {
  511. break;
  512. }
  513. }
  514. if (i < pMidMap->MaximumNumberOfMids) {
  515. break;
  516. } else {
  517. pMidMap->Flags &= ~MID_MAP_FLAGS_CAN_BE_EXPANDED;
  518. _RemoveMidMap(pMidMap);
  519. pMidMap = _GetNextMidMap(&pMidAtlas->MidMapExpansionList,pMidMap);
  520. }
  521. }
  522. if (pMidMap != NULL) {
  523. USHORT NumberOfEntriesInMap = pMidAtlas->MaximumNumberOfMids -
  524. pMidAtlas->NumberOfMidsInUse;
  525. if (NumberOfEntriesInMap > pMidAtlas->MidQuantum) {
  526. NumberOfEntriesInMap = pMidAtlas->MidQuantum;
  527. }
  528. // The smallest MIDMAP we can do is 3 given the MIDMAP logic
  529. if ( (NumberOfEntriesInMap > 0) && (NumberOfEntriesInMap < 3) ) {
  530. NumberOfEntriesInMap = 3;
  531. }
  532. if (NumberOfEntriesInMap > 0) {
  533. NewMidMapSize = FIELD_OFFSET(MID_MAP,Entries) +
  534. NumberOfEntriesInMap * sizeof(PVOID);
  535. pNewMidMap = (PMID_MAP)RxAllocatePoolWithTag(
  536. NonPagedPool,
  537. NewMidMapSize,
  538. RXCE_MIDATLAS_POOLTAG);
  539. if (pNewMidMap != NULL) {
  540. pNewMidMap->Flags = MID_MAP_FLAGS_FREE_POOL;
  541. pNewMidMap->MaximumNumberOfMids = NumberOfEntriesInMap;
  542. pNewMidMap->NumberOfMidsInUse = 0;
  543. pNewMidMap->BaseMid = (pMidMap->BaseMid |
  544. i << pMidMap->IndexAlignmentCount);
  545. pNewMidMap->IndexAlignmentCount = pMidMap->IndexAlignmentCount +
  546. pMidMap->IndexFieldWidth;
  547. pNewMidMap->IndexMask = (pMidAtlas->MidQuantum - 1) << pNewMidMap->IndexAlignmentCount;
  548. pNewMidMap->IndexFieldWidth = pMidAtlas->MidQuantumFieldWidth;
  549. RxInitializeMidMapFreeList(pNewMidMap);
  550. //
  551. // After the RxInitializeMidMapFreeList call above the
  552. // pFreeMidListHead points to Entries[0]. We will be storing
  553. // the value pMidMap->Entries[i] at this location so we need
  554. // to make pFreeMidListHead point to Entries[1].
  555. //
  556. pNewMidMap->pFreeMidListHead = _GetEntryPointer(*(pNewMidMap->pFreeMidListHead));
  557. //
  558. // Set up the mid map appropriately.
  559. //
  560. pNewMidMap->NumberOfMidsInUse = 1;
  561. pNewMidMap->Entries[0] = pMidMap->Entries[i];
  562. pNewMidMap->Level = pMidMap->Level + 1;
  563. //
  564. // The new MinMap is stored at the pMidMap->Entries[i] location.
  565. //
  566. pMidMap->Entries[i] = _MakeEntry(pNewMidMap,ENTRY_TYPE_MID_MAP);
  567. //
  568. // Update the free list and the expansion list respectively.
  569. //
  570. _AddMidMap(&pMidAtlas->MidMapFreeList,pNewMidMap);
  571. pNewMidMap->NumberOfMidsInUse++;
  572. pContextPointer = pNewMidMap->pFreeMidListHead;
  573. pNewMidMap->pFreeMidListHead = _GetEntryPointer(*(pNewMidMap->pFreeMidListHead));
  574. *pContextPointer = _MakeEntry(pContext,ENTRY_TYPE_VALID_CONTEXT);
  575. *pNewMid = ((USHORT)
  576. (pContextPointer - (PVOID *)&pNewMidMap->Entries)
  577. << pNewMidMap->IndexAlignmentCount) |
  578. pNewMidMap->BaseMid;
  579. Status = STATUS_SUCCESS;
  580. } else {
  581. Status = STATUS_INSUFFICIENT_RESOURCES;
  582. }
  583. } else {
  584. Status = STATUS_UNSUCCESSFUL;
  585. }
  586. } else {
  587. Status = STATUS_UNSUCCESSFUL;
  588. }
  589. } else {
  590. Status = STATUS_UNSUCCESSFUL;
  591. }
  592. if (Status == (STATUS_SUCCESS)) {
  593. pMidAtlas->NumberOfMidsInUse++;
  594. }
  595. //DbgPrint("Mid %lx\n",*pNewMid);
  596. return Status;
  597. }