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.

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