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.

1418 lines
44 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. buffer.c
  5. Abstract:
  6. This module contains routines for handling non-bufferring TDI
  7. providers. The AFD interface assumes that bufferring will be done
  8. below AFD; if the TDI provider doesn't buffer, then AFD must.
  9. Author:
  10. David Treadwell (davidtr) 21-Feb-1992
  11. Revision History:
  12. --*/
  13. #include "afdp.h"
  14. PAFD_BUFFER
  15. AfdInitializeBuffer (
  16. IN PVOID MemBlock,
  17. IN ULONG BufferDataSize,
  18. IN ULONG AddressSize,
  19. IN CCHAR StackSize
  20. );
  21. VOID
  22. AfdInitializeBufferTag (
  23. IN PAFD_BUFFER_TAG AfdBufferTag,
  24. IN ULONG AddressSize
  25. );
  26. PAFD_BUFFER
  27. AfdGetBufferSlow (
  28. IN ULONG BufferDataSize,
  29. IN ULONG AddressSize,
  30. IN PEPROCESS Process,
  31. IN CCHAR StackSize
  32. );
  33. #if DBG
  34. VOID
  35. AfdFreeBufferReal (
  36. PVOID AfdBuffer
  37. );
  38. #endif
  39. #ifdef ALLOC_PRAGMA
  40. #pragma alloc_text( PAGEAFD, AfdAllocateBuffer )
  41. #pragma alloc_text( PAGEAFD, AfdFreeBuffer )
  42. #if DBG
  43. #pragma alloc_text( PAGEAFD, AfdFreeBufferReal )
  44. #endif
  45. #pragma alloc_text( PAGEAFD, AfdCalculateBufferSize )
  46. #pragma alloc_text( PAGEAFD, AfdInitializeBuffer )
  47. #pragma alloc_text( PAGEAFD, AfdGetBufferFast )
  48. #ifdef _AFD_VARIABLE_STACK_
  49. #pragma alloc_text( PAGEAFD, AfdGetBufferWithMaxStackSize )
  50. #endif //_AFD_VARIABLE_STACK_
  51. #pragma alloc_text( PAGEAFD, AfdGetBufferSlow )
  52. #pragma alloc_text( PAGEAFD, AfdReturnBuffer )
  53. #pragma alloc_text( PAGEAFD, AfdAllocateBufferTag )
  54. #pragma alloc_text( PAGEAFD, AfdFreeBufferTag )
  55. #pragma alloc_text( PAGEAFD, AfdAllocateRemoteAddress )
  56. #pragma alloc_text( PAGEAFD, AfdFreeRemoteAddress )
  57. #pragma alloc_text( PAGEAFD, AfdInitializeBufferTag )
  58. #pragma alloc_text( PAGEAFD, AfdGetBufferTag )
  59. #pragma alloc_text( INIT, AfdInitializeBufferManager)
  60. #endif
  61. PVOID
  62. AfdAllocateBuffer (
  63. IN POOL_TYPE PoolType,
  64. IN SIZE_T NumberOfBytes,
  65. IN ULONG Tag
  66. )
  67. /*++
  68. Routine Description:
  69. Used by the lookaside list allocation function to allocate a new
  70. AFD buffer structure. The returned structure will be fully
  71. initialized.
  72. Arguments:
  73. PoolType - passed to ExAllocatePoolWithTag.
  74. NumberOfBytes - the number of bytes required for the data buffer
  75. portion of the AFD buffer.
  76. Tag - passed to ExAllocatePoolWithTag.
  77. Return Value:
  78. PVOID - a fully initialized PAFD_BUFFER, or NULL if the allocation
  79. attempt fails.
  80. --*/
  81. {
  82. ULONG dataLength;
  83. PVOID memBlock;
  84. //
  85. // Get nonpaged pool for the buffer.
  86. //
  87. memBlock = AFD_ALLOCATE_POOL( PoolType, NumberOfBytes, Tag );
  88. if ( memBlock == NULL ) {
  89. return NULL;
  90. }
  91. if (NumberOfBytes==AfdLookasideLists->SmallBufferList.L.Size) {
  92. dataLength = AfdSmallBufferSize;
  93. }
  94. else if (NumberOfBytes==AfdLookasideLists->MediumBufferList.L.Size) {
  95. dataLength = AfdMediumBufferSize;
  96. }
  97. else if (NumberOfBytes==AfdLookasideLists->LargeBufferList.L.Size) {
  98. dataLength = AfdLargeBufferSize;
  99. }
  100. else {
  101. ASSERT (!"Unknown buffer length");
  102. return NULL;
  103. }
  104. //
  105. // Initialize the buffer and return a pointer to it.
  106. //
  107. #if DBG
  108. {
  109. PAFD_BUFFER afdBuffer = AfdInitializeBuffer( memBlock,
  110. dataLength,
  111. AfdStandardAddressLength,
  112. AfdTdiStackSize );
  113. ASSERT ((PCHAR)afdBuffer+sizeof (AFD_BUFFER)<=(PCHAR)memBlock+NumberOfBytes &&
  114. (PCHAR)afdBuffer->Buffer+dataLength<=(PCHAR)memBlock+NumberOfBytes &&
  115. (PCHAR)afdBuffer->Irp+IoSizeOfIrp(AfdTdiStackSize)<=(PCHAR)memBlock+NumberOfBytes &&
  116. (PCHAR)afdBuffer->Mdl+MmSizeOfMdl(afdBuffer->Buffer, dataLength)<=(PCHAR)memBlock+NumberOfBytes &&
  117. (PCHAR)afdBuffer->TdiInfo.RemoteAddress+AfdStandardAddressLength<=(PCHAR)memBlock+NumberOfBytes);
  118. return afdBuffer;
  119. }
  120. #else
  121. return AfdInitializeBuffer( memBlock, dataLength, AfdStandardAddressLength, AfdTdiStackSize );
  122. #endif
  123. } // AfdAllocateBuffer
  124. VOID
  125. NTAPI
  126. AfdFreeBuffer (
  127. PVOID AfdBuffer
  128. )
  129. {
  130. ASSERT( ((PAFD_BUFFER)AfdBuffer)->BufferLength == AfdSmallBufferSize ||
  131. ((PAFD_BUFFER)AfdBuffer)->BufferLength == AfdMediumBufferSize ||
  132. ((PAFD_BUFFER)AfdBuffer)->BufferLength == AfdLargeBufferSize );
  133. #if DBG
  134. AfdFreeBufferReal (AfdBuffer);
  135. }
  136. VOID
  137. NTAPI
  138. AfdFreeBufferReal (
  139. PVOID AfdBuffer
  140. )
  141. {
  142. #endif
  143. {
  144. PAFD_BUFFER hdr = AfdBuffer;
  145. switch (hdr->Placement) {
  146. case AFD_PLACEMENT_BUFFER:
  147. AfdBuffer = hdr->Buffer;
  148. break;
  149. case AFD_PLACEMENT_HDR:
  150. AfdBuffer = hdr;
  151. break;
  152. case AFD_PLACEMENT_MDL:
  153. AfdBuffer = hdr->Mdl;
  154. break;
  155. case AFD_PLACEMENT_IRP:
  156. AfdBuffer = hdr->Irp;
  157. break;
  158. default:
  159. ASSERT (!"Unknown placement!");
  160. __assume (0);
  161. }
  162. if (hdr->AlignmentAdjusted) {
  163. //
  164. // The original memory block was adjusted to meet alignment
  165. // requirement of AFD buffers.
  166. // The amount of adjustment should be stored in the space
  167. // used for adjustment (right below the first piece).
  168. //
  169. ASSERT ((*(((PSIZE_T)AfdBuffer)-1))>0 &&
  170. (*(((PSIZE_T)AfdBuffer)-1))<AfdBufferAlignment);
  171. AfdBuffer = (PUCHAR)AfdBuffer - (*(((PSIZE_T)AfdBuffer)-1));
  172. }
  173. AFD_FREE_POOL (AfdBuffer, AFD_DATA_BUFFER_POOL_TAG);
  174. }
  175. }
  176. PVOID
  177. AfdAllocateBufferTag (
  178. IN POOL_TYPE PoolType,
  179. IN SIZE_T NumberOfBytes,
  180. IN ULONG Tag
  181. )
  182. /*++
  183. Routine Description:
  184. Used by the lookaside list allocation function to allocate a new
  185. AFD buffer tag structure. The returned structure will be fully
  186. initialized.
  187. Arguments:
  188. PoolType - passed to ExAllocatePoolWithTag.
  189. NumberOfBytes - the number of bytes required for the data buffer
  190. portion of the AFD buffer tag (0).
  191. Tag - passed to ExAllocatePoolWithTag.
  192. Return Value:
  193. PVOID - a fully initialized PAFD_BUFFER_TAG, or NULL if the allocation
  194. attempt fails.
  195. --*/
  196. {
  197. PAFD_BUFFER_TAG afdBufferTag;
  198. //
  199. // The requested length must be the same as buffer tag size
  200. //
  201. ASSERT(NumberOfBytes == sizeof (AFD_BUFFER_TAG) );
  202. //
  203. // Get nonpaged pool for the buffer tag.
  204. //
  205. afdBufferTag = AFD_ALLOCATE_POOL( PoolType, NumberOfBytes, Tag );
  206. if ( afdBufferTag == NULL ) {
  207. return NULL;
  208. }
  209. //
  210. // Initialize the buffer tag and return a pointer to it.
  211. //
  212. AfdInitializeBufferTag( afdBufferTag, 0 );
  213. return afdBufferTag;
  214. } // AfdAllocateBufferTag
  215. VOID
  216. NTAPI
  217. AfdFreeBufferTag (
  218. PVOID AfdBufferTag
  219. )
  220. {
  221. AFD_FREE_POOL (AfdBufferTag, AFD_DATA_BUFFER_POOL_TAG);
  222. }
  223. PVOID
  224. AfdAllocateRemoteAddress (
  225. IN POOL_TYPE PoolType,
  226. IN SIZE_T NumberOfBytes,
  227. IN ULONG Tag
  228. )
  229. /*++
  230. Routine Description:
  231. Used by the lookaside list allocation function to allocate a new
  232. remote address structure. The returned structure will be fully
  233. initialized.
  234. Arguments:
  235. PoolType - passed to ExAllocatePoolWithTag.
  236. NumberOfBytes - the number of bytes required for the data buffer
  237. portion of the AFD buffer tag (0).
  238. Tag - passed to ExAllocatePoolWithTag.
  239. Return Value:
  240. PVOID - a fully initialized remote address, or NULL if the allocation
  241. attempt fails.
  242. --*/
  243. {
  244. //
  245. // The requested length must be the same as standard address size
  246. //
  247. ASSERT(NumberOfBytes == AfdStandardAddressLength );
  248. //
  249. // Get nonpaged pool for the remote address.
  250. //
  251. return AFD_ALLOCATE_POOL( PoolType, NumberOfBytes, Tag );
  252. } // AfdAllocateRemoteAddress
  253. VOID
  254. NTAPI
  255. AfdFreeRemoteAddress (
  256. PVOID AfdBufferTag
  257. )
  258. {
  259. AFD_FREE_POOL (AfdBufferTag, AFD_REMOTE_ADDRESS_POOL_TAG);
  260. }
  261. ULONG
  262. AfdCalculateBufferSize (
  263. IN ULONG BufferDataSize,
  264. IN ULONG AddressSize,
  265. IN CCHAR StackSize
  266. )
  267. /*++
  268. Routine Description:
  269. Determines the size of an AFD buffer structure given the amount of
  270. data that the buffer contains.
  271. Arguments:
  272. BufferDataSize - data length of the buffer.
  273. AddressSize - length of address structure for the buffer.
  274. Return Value:
  275. Number of bytes needed for an AFD_BUFFER structure for data of
  276. this size.
  277. --*/
  278. {
  279. ULONG irpSize;
  280. ULONG mdlSize;
  281. ULONG hdrSize;
  282. ULONG size;
  283. //
  284. // Determine the sizes of the various components of an AFD_BUFFER
  285. // structure.
  286. //
  287. hdrSize = sizeof (AFD_BUFFER);
  288. irpSize = IoSizeOfIrp( StackSize );
  289. //
  290. // For mdl size calculation we rely on ex guarantee that buffer will be
  291. // aligned on the page boundary (for allocations >= PAGE_SIZE)
  292. // or will not spawn pages (for allocations < PAGE_SIZE).
  293. //
  294. mdlSize = (CLONG)MmSizeOfMdl( NULL, BufferDataSize );
  295. size = ALIGN_UP_A(hdrSize,AFD_MINIMUM_BUFFER_ALIGNMENT) +
  296. ALIGN_UP_A(irpSize,AFD_MINIMUM_BUFFER_ALIGNMENT) +
  297. ALIGN_UP_A(mdlSize,AFD_MINIMUM_BUFFER_ALIGNMENT) +
  298. ALIGN_UP_A(BufferDataSize,AFD_MINIMUM_BUFFER_ALIGNMENT) +
  299. AddressSize;
  300. if (size>=PAGE_SIZE) {
  301. return size;
  302. }
  303. else {
  304. if (StackSize==AfdTdiStackSize) {
  305. size += AfdAlignmentOverhead;
  306. }
  307. else {
  308. size += AfdBufferAlignment-AFD_MINIMUM_BUFFER_ALIGNMENT;
  309. }
  310. if (size>=PAGE_SIZE) {
  311. //
  312. // PAGE_SIZE allocations are aligned, ignore any extra overhead
  313. //
  314. return PAGE_SIZE;
  315. }
  316. else {
  317. return size;
  318. }
  319. }
  320. } // AfdCalculateBufferSize
  321. PAFD_BUFFER
  322. FASTCALL
  323. AfdGetBufferFast (
  324. IN ULONG BufferDataSize,
  325. IN ULONG AddressSize,
  326. IN PEPROCESS Process
  327. )
  328. /*++
  329. Routine Description:
  330. Obtains a buffer of the appropriate size for the caller. Uses
  331. the preallocated buffers if possible, or else allocates a new buffer
  332. structure if required.
  333. Arguments:
  334. BufferDataSize - the size of the data buffer that goes along with the
  335. buffer structure.
  336. AddressSize - size of the address field required for the buffer.
  337. Return Value:
  338. PAFD_BUFFER - a pointer to an AFD_BUFFER structure, or NULL if one
  339. was not available or could not be allocated.
  340. --*/
  341. {
  342. PAFD_BUFFER afdBuffer;
  343. NTSTATUS status;
  344. //
  345. // If possible, allocate the buffer from one of the lookaside lists.
  346. //
  347. if ( AddressSize <= AfdStandardAddressLength &&
  348. BufferDataSize <= AfdLargeBufferSize ) {
  349. PNPAGED_LOOKASIDE_LIST lookasideList;
  350. if ( BufferDataSize <= AfdSmallBufferSize ) {
  351. lookasideList = &AfdLookasideLists->SmallBufferList;
  352. } else if ( BufferDataSize <= AfdMediumBufferSize ) {
  353. lookasideList = &AfdLookasideLists->MediumBufferList;
  354. } else {
  355. lookasideList = &AfdLookasideLists->LargeBufferList;
  356. }
  357. afdBuffer = ExAllocateFromNPagedLookasideList( lookasideList );
  358. if ( afdBuffer != NULL) {
  359. if (!afdBuffer->Lookaside) {
  360. status = PsChargeProcessPoolQuota (
  361. (PEPROCESS)((ULONG_PTR)Process & (~AFDB_RAISE_ON_FAILURE)),
  362. NonPagedPool,
  363. lookasideList->L.Size);
  364. if (!NT_SUCCESS (status)) {
  365. AfdFreeBuffer (afdBuffer);
  366. goto ExitQuotaFailure;
  367. }
  368. AfdRecordQuotaHistory(
  369. process,
  370. (LONG)lookasideList->L.Size,
  371. "BuffAlloc ",
  372. afdBuffer
  373. );
  374. AfdRecordPoolQuotaCharged(lookasideList->L.Size);
  375. }
  376. #if DBG
  377. RtlGetCallersAddress(
  378. &afdBuffer->Caller,
  379. &afdBuffer->CallersCaller
  380. );
  381. #endif
  382. return afdBuffer;
  383. }
  384. }
  385. else {
  386. afdBuffer = AfdGetBufferSlow (BufferDataSize, AddressSize, Process, AfdTdiStackSize);
  387. #if DBG
  388. if (afdBuffer!=NULL) {
  389. RtlGetCallersAddress(
  390. &afdBuffer->Caller,
  391. &afdBuffer->CallersCaller
  392. );
  393. }
  394. #endif
  395. return afdBuffer;
  396. }
  397. status = STATUS_INSUFFICIENT_RESOURCES;
  398. ExitQuotaFailure:
  399. if ((ULONG_PTR)Process & AFDB_RAISE_ON_FAILURE) {
  400. ExRaiseStatus (status);
  401. }
  402. return NULL;
  403. } // AfdGetBuffer
  404. #ifdef _AFD_VARIABLE_STACK_
  405. PAFD_BUFFER
  406. FASTCALL
  407. AfdGetBufferWithMaxStackSize (
  408. IN ULONG BufferDataSize,
  409. IN ULONG AddressSize,
  410. IN PEPROCESS Process
  411. )
  412. {
  413. PAFD_BUFFER afdBuffer;
  414. afdBuffer = AfdGetBufferSlow (BufferDataSize, AddressSize, Process, AfdMaxStackSize);
  415. #if DBG
  416. if (afdBuffer!=NULL) {
  417. RtlGetCallersAddress(
  418. &afdBuffer->Caller,
  419. &afdBuffer->CallersCaller
  420. );
  421. }
  422. #endif
  423. return afdBuffer;
  424. }
  425. #endif // _AFD_VARIABLE_STACK_
  426. PAFD_BUFFER
  427. AfdGetBufferSlow (
  428. IN ULONG BufferDataSize,
  429. IN ULONG AddressSize,
  430. IN PEPROCESS Process,
  431. IN CCHAR StackSize
  432. )
  433. {
  434. NTSTATUS status;
  435. if (AddressSize<=0xFFFF) {
  436. PVOID memBlock;
  437. LONG sz;
  438. ULONG bufferSize;
  439. //
  440. // Couldn't find an appropriate buffer that was preallocated.
  441. // Allocate one manually. If the buffer size requested was
  442. // zero bytes, give them four bytes. This is because some of
  443. // the routines like MmSizeOfMdl() cannot handle getting passed
  444. // in a length of zero.
  445. //
  446. // !!! It would be good to ROUND_TO_PAGES for this allocation
  447. // if appropriate, then use entire buffer size.
  448. //
  449. if ( BufferDataSize == 0 ) {
  450. BufferDataSize = sizeof(ULONG);
  451. }
  452. bufferSize = AfdCalculateBufferSize( BufferDataSize, AddressSize, StackSize );
  453. //
  454. // Check for overflow (stack size comes from trusted source - no need to check
  455. // for overflow).
  456. //
  457. if (bufferSize>=BufferDataSize && bufferSize>=AddressSize) {
  458. memBlock = AFD_ALLOCATE_POOL(
  459. NonPagedPool,
  460. bufferSize,
  461. AFD_DATA_BUFFER_POOL_TAG
  462. );
  463. if ( memBlock != NULL) {
  464. status = PsChargeProcessPoolQuota (
  465. (PEPROCESS)((ULONG_PTR)Process & (~AFDB_RAISE_ON_FAILURE)),
  466. NonPagedPool,
  467. sz = BufferDataSize
  468. +AfdBufferOverhead
  469. +AddressSize
  470. -AfdStandardAddressLength
  471. +BufferDataSize<PAGE_SIZE
  472. ? min (AfdAlignmentOverhead, PAGE_SIZE-BufferDataSize)
  473. : 0);
  474. if (NT_SUCCESS (status)) {
  475. PAFD_BUFFER afdBuffer;
  476. //
  477. // Initialize the AFD buffer structure and return it.
  478. //
  479. afdBuffer = AfdInitializeBuffer( memBlock,
  480. BufferDataSize,
  481. AddressSize,
  482. StackSize);
  483. ASSERT ((PCHAR)afdBuffer+sizeof (AFD_BUFFER)<=(PCHAR)memBlock+bufferSize &&
  484. (PCHAR)afdBuffer->Buffer+BufferDataSize<=(PCHAR)memBlock+bufferSize &&
  485. (PCHAR)afdBuffer->Irp+IoSizeOfIrp(StackSize)<=(PCHAR)memBlock+bufferSize &&
  486. (PCHAR)afdBuffer->Mdl+MmSizeOfMdl(afdBuffer->Buffer, BufferDataSize)<=(PCHAR)memBlock+bufferSize &&
  487. (PCHAR)afdBuffer->TdiInfo.RemoteAddress+AddressSize<=(PCHAR)memBlock+bufferSize);
  488. AfdRecordPoolQuotaCharged(sz);
  489. AfdRecordQuotaHistory(
  490. process,
  491. sz,
  492. "BuffAlloc ",
  493. afdBuffer
  494. );
  495. return afdBuffer;
  496. }
  497. else {
  498. AFD_FREE_POOL (memBlock, AFD_DATA_BUFFER_POOL_TAG);
  499. goto ExitQuotaFailure;
  500. }
  501. } // memblock==NULL
  502. } // overflow
  503. }
  504. else {
  505. // TDI does not support addresses > USHORT
  506. ASSERT (FALSE);
  507. }
  508. //
  509. // This is default status code.
  510. // Quota failures jump directly to the
  511. // label below to raise the status returned by
  512. // the quota charging code if requested by the caller..
  513. //
  514. status = STATUS_INSUFFICIENT_RESOURCES;
  515. ExitQuotaFailure:
  516. if ((ULONG_PTR)Process & AFDB_RAISE_ON_FAILURE) {
  517. ExRaiseStatus (status);
  518. }
  519. return NULL;
  520. }
  521. PAFD_BUFFER_TAG
  522. AfdGetBufferTag (
  523. IN ULONG AddressSize,
  524. IN PEPROCESS Process
  525. )
  526. /*++
  527. Routine Description:
  528. Obtains a buffer for tagging TDSU received via chained indication. Uses
  529. the preallocated buffers if possible, or else allocates a new buffer
  530. structure if required.
  531. Arguments:
  532. AddressSize - size of the address field required for the buffer.
  533. Return Value:
  534. PAFD_BUFFER_TAG - a pointer to an AFD_BUFFER_TAG structure, or NULL if one
  535. was not available or could not be allocated.
  536. --*/
  537. {
  538. PAFD_BUFFER_TAG afdBufferTag;
  539. ULONG bufferSize;
  540. NTSTATUS status;
  541. if ( AddressSize <= AfdStandardAddressLength) {
  542. if (AddressSize>0)
  543. AddressSize = AfdStandardAddressLength;
  544. afdBufferTag = ExAllocateFromNPagedLookasideList(
  545. &AfdLookasideLists->BufferTagList );
  546. if ( afdBufferTag != NULL &&
  547. ( AddressSize==0 ||
  548. (afdBufferTag->TdiInfo.RemoteAddress =
  549. ExAllocateFromNPagedLookasideList(
  550. &AfdLookasideLists->RemoteAddrList ))!=NULL ) ) {
  551. afdBufferTag->AllocatedAddressLength = (USHORT)AddressSize;
  552. if (!afdBufferTag->Lookaside) {
  553. status = PsChargeProcessPoolQuota (
  554. (PEPROCESS)((ULONG_PTR)Process & (~AFDB_RAISE_ON_FAILURE)),
  555. NonPagedPool,
  556. sizeof (AFD_BUFFER_TAG)+AddressSize);
  557. if (!NT_SUCCESS (status)) {
  558. if ((afdBufferTag->TdiInfo.RemoteAddress!=NULL) &&
  559. (afdBufferTag->TdiInfo.RemoteAddress != (PVOID)(afdBufferTag+1))) {
  560. ExFreeToNPagedLookasideList( &AfdLookasideLists->RemoteAddrList,
  561. afdBufferTag->TdiInfo.RemoteAddress );
  562. }
  563. AFD_FREE_POOL (afdBufferTag, AFD_DATA_BUFFER_POOL_TAG);
  564. goto ExitQuotaFailure;
  565. }
  566. AfdRecordQuotaHistory(
  567. process,
  568. (LONG)(sizeof (AFD_BUFFER_TAG)+AddressSize),
  569. "BuffAlloc ",
  570. afdBufferTag
  571. );
  572. AfdRecordPoolQuotaCharged(sizeof (AFD_BUFFER_TAG)+AddressSize);
  573. }
  574. #if DBG
  575. RtlGetCallersAddress(
  576. &afdBufferTag->Caller,
  577. &afdBufferTag->CallersCaller
  578. );
  579. #endif
  580. return afdBufferTag;
  581. } // afdBufferTag==NULL || RemoteAddress==NULL
  582. }
  583. else if (AddressSize<=0xFFFF) {
  584. bufferSize = sizeof (AFD_BUFFER_TAG) + AddressSize;
  585. afdBufferTag = AFD_ALLOCATE_POOL(
  586. NonPagedPool,
  587. bufferSize,
  588. AFD_DATA_BUFFER_POOL_TAG
  589. );
  590. if (afdBufferTag!=NULL) {
  591. status = PsChargeProcessPoolQuota (
  592. (PEPROCESS)((ULONG_PTR)Process & (~AFDB_RAISE_ON_FAILURE)),
  593. NonPagedPool,
  594. bufferSize);
  595. if (NT_SUCCESS (status)) {
  596. //
  597. // Initialize the AFD buffer structure and return it.
  598. //
  599. AfdInitializeBufferTag (afdBufferTag, AddressSize);
  600. AfdRecordQuotaHistory(
  601. process,
  602. (LONG)bufferSize,
  603. "BuffAlloc ",
  604. afdBufferTag
  605. );
  606. AfdRecordPoolQuotaCharged(bufferSize);
  607. #if DBG
  608. RtlGetCallersAddress(
  609. &afdBufferTag->Caller,
  610. &afdBufferTag->CallersCaller
  611. );
  612. #endif
  613. return afdBufferTag;
  614. }
  615. else {
  616. AFD_FREE_POOL (afdBufferTag, AFD_DATA_BUFFER_POOL_TAG);
  617. goto ExitQuotaFailure;
  618. }
  619. }
  620. }
  621. else {
  622. // TDI does not support addresses > USHORT
  623. ASSERT (FALSE);
  624. }
  625. //
  626. // This is default status code.
  627. // Quota failures jump directly to the
  628. // label below to raise the status returned by
  629. // the quota charging code if requested by the caller..
  630. //
  631. status = STATUS_INSUFFICIENT_RESOURCES;
  632. ExitQuotaFailure:
  633. if ((ULONG_PTR)Process & AFDB_RAISE_ON_FAILURE) {
  634. ExRaiseStatus (status);
  635. }
  636. return NULL;
  637. }
  638. VOID
  639. AfdReturnBuffer (
  640. IN PAFD_BUFFER_HEADER AfdBufferHeader,
  641. IN PEPROCESS Process
  642. )
  643. /*++
  644. Routine Description:
  645. Returns an AFD buffer to the appropriate global list, or frees
  646. it if necessary.
  647. Arguments:
  648. AfdBufferHeader - points to the AFD_BUFFER_HEADER structure to return or free.
  649. Return Value:
  650. None.
  651. --*/
  652. {
  653. if (AfdBufferHeader->BufferLength!=AfdBufferTagSize) {
  654. PNPAGED_LOOKASIDE_LIST lookasideList;
  655. PAFD_BUFFER AfdBuffer = CONTAINING_RECORD (AfdBufferHeader, AFD_BUFFER, Header);
  656. ASSERT (IS_VALID_AFD_BUFFER (AfdBuffer));
  657. //
  658. // Most of the AFD buffer must be zeroed when returning the buffer.
  659. //
  660. ASSERT( !AfdBuffer->ExpeditedData );
  661. ASSERT( AfdBuffer->Mdl->ByteCount == AfdBuffer->BufferLength );
  662. ASSERT( AfdBuffer->Mdl->Next == NULL );
  663. //
  664. // If appropriate, return the buffer to one of the AFD buffer
  665. // lookaside lists.
  666. //
  667. #ifdef _AFD_VARIABLE_STACK_
  668. if (AfdBuffer->Irp->StackCount==AfdTdiStackSize &&
  669. AfdBuffer->AllocatedAddressLength == AfdStandardAddressLength &&
  670. AfdBuffer->BufferLength <= AfdLargeBufferSize) {
  671. #else // _AFD_VARIABLE_STACK_
  672. ASSERT (AfdBuffer->Irp->StackCount==AfdTdiStackSize);
  673. if (AfdBuffer->AllocatedAddressLength == AfdStandardAddressLength &&
  674. AfdBuffer->BufferLength <= AfdLargeBufferSize) {
  675. #endif // _AFD_VARIABLE_STACK_
  676. if (AfdBuffer->BufferLength==AfdSmallBufferSize) {
  677. lookasideList = &AfdLookasideLists->SmallBufferList;
  678. } else if (AfdBuffer->BufferLength == AfdMediumBufferSize) {
  679. lookasideList = &AfdLookasideLists->MediumBufferList;
  680. } else {
  681. ASSERT (AfdBuffer->BufferLength==AfdLargeBufferSize);
  682. lookasideList = &AfdLookasideLists->LargeBufferList;
  683. }
  684. if (!AfdBuffer->Lookaside) {
  685. PsReturnPoolQuota (Process, NonPagedPool, lookasideList->L.Size);
  686. AfdRecordQuotaHistory(
  687. Process,
  688. -(LONG)lookasideList->L.Size,
  689. "BuffDealloc ",
  690. AfdBuffer
  691. );
  692. AfdRecordPoolQuotaReturned(
  693. lookasideList->L.Size
  694. );
  695. AfdBuffer->Lookaside = TRUE;
  696. }
  697. ExFreeToNPagedLookasideList( lookasideList, AfdBuffer );
  698. return;
  699. }
  700. // The buffer was not from a lookaside list allocation, so just free
  701. // the pool we used for it.
  702. //
  703. #ifdef _AFD_VARIABLE_STACK_
  704. ASSERT (AfdBuffer->Irp->StackCount>=AfdTdiStackSize &&
  705. AfdBuffer->Irp->StackCount<=AfdMaxStackSize);
  706. #endif // _AFD_VARIABLE_STACK_
  707. ASSERT (AfdBuffer->Lookaside==FALSE);
  708. {
  709. LONG sz;
  710. PsReturnPoolQuota (Process,
  711. NonPagedPool,
  712. sz=AfdBuffer->BufferLength
  713. +AfdBufferOverhead
  714. +AfdBuffer->AllocatedAddressLength
  715. -AfdStandardAddressLength
  716. +AfdBuffer->BufferLength<PAGE_SIZE
  717. ? min (AfdAlignmentOverhead, PAGE_SIZE-AfdBuffer->BufferLength)
  718. : 0);
  719. AfdRecordQuotaHistory(
  720. Process,
  721. -(LONG)sz,
  722. "BuffDealloc ",
  723. AfdBuffer
  724. );
  725. AfdRecordPoolQuotaReturned(
  726. sz
  727. );
  728. }
  729. #if DBG
  730. AfdFreeBufferReal (AfdBuffer);
  731. #else
  732. AfdFreeBuffer (AfdBuffer);
  733. #endif
  734. return;
  735. }
  736. else {
  737. PAFD_BUFFER_TAG AfdBufferTag = CONTAINING_RECORD (AfdBufferHeader, AFD_BUFFER_TAG, Header);
  738. ASSERT( !AfdBufferTag->ExpeditedData );
  739. if (AfdBufferTag->NdisPacket) {
  740. AfdBufferTag->NdisPacket = FALSE;
  741. TdiReturnChainedReceives (&AfdBufferTag->Context, 1);
  742. }
  743. if (AfdBufferTag->TdiInfo.RemoteAddress != (PVOID)(AfdBufferTag+1)) {
  744. if (AfdBufferTag->TdiInfo.RemoteAddress!=NULL) {
  745. ASSERT (AfdBufferTag->AllocatedAddressLength==AfdStandardAddressLength);
  746. ExFreeToNPagedLookasideList( &AfdLookasideLists->RemoteAddrList,
  747. AfdBufferTag->TdiInfo.RemoteAddress );
  748. AfdBufferTag->TdiInfo.RemoteAddress = NULL;
  749. }
  750. else {
  751. ASSERT (AfdBufferTag->AllocatedAddressLength==0);
  752. }
  753. if (!AfdBufferTag->Lookaside) {
  754. LONG sz;
  755. PsReturnPoolQuota (
  756. Process,
  757. NonPagedPool,
  758. sz=sizeof (AFD_BUFFER_TAG)
  759. + AfdBufferTag->AllocatedAddressLength);
  760. AfdRecordQuotaHistory(
  761. Process,
  762. -(LONG)sz,
  763. "BuffDealloc ",
  764. AfdBufferTag
  765. );
  766. AfdRecordPoolQuotaReturned(
  767. sz
  768. );
  769. AfdBufferTag->Lookaside = TRUE;
  770. }
  771. ExFreeToNPagedLookasideList( &AfdLookasideLists->BufferTagList, AfdBufferTag );
  772. }
  773. else {
  774. LONG sz;
  775. ASSERT (AfdBufferTag->AllocatedAddressLength>AfdStandardAddressLength);
  776. ASSERT (AfdBufferTag->Lookaside == FALSE);
  777. PsReturnPoolQuota (
  778. Process,
  779. NonPagedPool,
  780. sz = sizeof (AFD_BUFFER_TAG)
  781. + AfdBufferTag->AllocatedAddressLength);
  782. AfdRecordQuotaHistory(
  783. Process,
  784. -(LONG)sz,
  785. "BuffDealloc ",
  786. AfdBufferTag
  787. );
  788. AfdRecordPoolQuotaReturned(
  789. sz
  790. );
  791. AFD_FREE_POOL(
  792. AfdBufferTag,
  793. AFD_DATA_BUFFER_POOL_TAG
  794. );
  795. }
  796. }
  797. } // AfdReturnBuffer
  798. PAFD_BUFFER
  799. AfdInitializeBuffer (
  800. IN PVOID MemoryBlock,
  801. IN ULONG BufferDataSize,
  802. IN ULONG AddressSize,
  803. IN CCHAR StackSize
  804. )
  805. /*++
  806. Routine Description:
  807. Initializes an AFD buffer. Sets up fields in the actual AFD_BUFFER
  808. structure and initializes the IRP and MDL associated with the
  809. buffer. This routine assumes that the caller has properly allocated
  810. sufficient space for all this.
  811. Arguments:
  812. AfdBuffer - points to the AFD_BUFFER structure to initialize.
  813. BufferDataSize - the size of the data buffer that goes along with the
  814. buffer structure.
  815. AddressSize - the size of data allocated for the address buffer.
  816. ListHead - the global list this buffer belongs to, or NULL if it
  817. doesn't belong on any list. This routine does NOT place the
  818. buffer structure on the list.
  819. Return Value:
  820. None.
  821. --*/
  822. {
  823. USHORT irpSize;
  824. SIZE_T mdlSize;
  825. SIZE_T hdrSize;
  826. PAFD_BUFFER hdr;
  827. PMDL mdl;
  828. PIRP irp;
  829. PVOID buf;
  830. PVOID addr;
  831. UCHAR placement;
  832. SIZE_T alignment;
  833. #ifdef AFD_CHECK_ALIGNMENT
  834. PLONG alignmentCounters = (PLONG)&AfdAlignmentTable[AfdAlignmentTableSize];
  835. #endif
  836. irpSize = IoSizeOfIrp( StackSize );
  837. mdlSize = (ULONG)MmSizeOfMdl( NULL, BufferDataSize );
  838. hdrSize = sizeof (AFD_BUFFER);
  839. //
  840. // Compute the index into (mis)alignment table to determine
  841. // what placement of the buffer block elements (e.g. hdr, IRP, MDL,
  842. // and data buffer itself) we need to choose to compensate and
  843. // align data buffer on AfdBufferAlignment boundary.
  844. //
  845. ASSERT ((PtrToUlong(MemoryBlock)%AFD_MINIMUM_BUFFER_ALIGNMENT)==0);
  846. #ifdef _AFD_VARIABLE_STACK_
  847. if (PAGE_ALIGN (MemoryBlock)==MemoryBlock || StackSize!=AfdTdiStackSize) {
  848. ASSERT (StackSize>=AfdTdiStackSize && StackSize<=AfdMaxStackSize);
  849. #else // _AFD_VARIABLE_STACK
  850. if (PAGE_ALIGN (MemoryBlock)==MemoryBlock) {
  851. #endif // _AFD_VARIABLE_STACK
  852. //
  853. // For page-aligned blocks (which are >= page size),
  854. // we always place the buffer first.
  855. // Same thing for big IRP stacks - allocate more memory to
  856. // compensate for alignment.
  857. //
  858. placement = AFD_PLACEMENT_BUFFER;
  859. }
  860. else {
  861. placement = AfdAlignmentTable[
  862. (PtrToUlong(MemoryBlock)&(AfdBufferAlignment-1))/AFD_MINIMUM_BUFFER_ALIGNMENT];
  863. }
  864. #ifdef AFD_CHECK_ALIGNMENT
  865. InterlockedIncrement (&alignmentCounters[
  866. (PtrToUlong(MemoryBlock)&(AfdBufferAlignment-1))/AFD_MINIMUM_BUFFER_ALIGNMENT]);
  867. #endif
  868. switch (placement) {
  869. case AFD_PLACEMENT_BUFFER:
  870. //
  871. // Perfect case: the memory is aready aligned as we need it.
  872. //
  873. buf = ALIGN_UP_A_POINTER(MemoryBlock, AfdBufferAlignment);
  874. alignment = (PUCHAR)buf-(PUCHAR)MemoryBlock;
  875. #ifdef _AFD_VARIABLE_STACK_
  876. ASSERT (alignment<=AfdAlignmentOverhead || (StackSize!=AfdTdiStackSize));
  877. #else // _AFD_VARIABLE_STACK_
  878. ASSERT (alignment<=AfdAlignmentOverhead);
  879. #endif // _AFD_VARIABLE_STACK_
  880. hdr = ALIGN_UP_TO_TYPE_POINTER((PCHAR)buf+BufferDataSize, AFD_BUFFER);
  881. irp = ALIGN_UP_TO_TYPE_POINTER((PCHAR)hdr+hdrSize, IRP);
  882. mdl = ALIGN_UP_TO_TYPE_POINTER((PCHAR)irp+irpSize, MDL);
  883. addr = (PCHAR)mdl+mdlSize;
  884. break;
  885. //
  886. // Other cases, we use hdr, mdl, and IRP to try to compensate
  887. // and have the data buffer aligned at the AfdBufferAlignment
  888. // boundary.
  889. //
  890. case AFD_PLACEMENT_HDR:
  891. hdr = ALIGN_UP_TO_TYPE_POINTER(MemoryBlock, AFD_BUFFER);
  892. alignment = (PUCHAR)hdr-(PUCHAR)MemoryBlock;
  893. ASSERT (alignment<=AfdAlignmentOverhead);
  894. buf = ALIGN_UP_A_POINTER((PCHAR)hdr+hdrSize, AfdBufferAlignment);
  895. irp = ALIGN_UP_TO_TYPE_POINTER((PCHAR)buf+BufferDataSize, IRP);
  896. mdl = ALIGN_UP_TO_TYPE_POINTER((PCHAR)irp+irpSize, MDL);
  897. addr = (PCHAR)mdl+mdlSize;
  898. break;
  899. case AFD_PLACEMENT_MDL:
  900. mdl = ALIGN_UP_TO_TYPE_POINTER(MemoryBlock, MDL);
  901. alignment = (PUCHAR)mdl-(PUCHAR)MemoryBlock;
  902. ASSERT (alignment<=AfdAlignmentOverhead);
  903. buf = ALIGN_UP_A_POINTER((PCHAR)mdl+mdlSize, AfdBufferAlignment);
  904. hdr = ALIGN_UP_TO_TYPE_POINTER((PCHAR)buf+BufferDataSize, AFD_BUFFER);
  905. irp = ALIGN_UP_TO_TYPE_POINTER((PCHAR)hdr+hdrSize, IRP);
  906. addr = (PCHAR)irp+irpSize;
  907. break;
  908. case AFD_PLACEMENT_IRP:
  909. irp = ALIGN_UP_TO_TYPE_POINTER(MemoryBlock, IRP);
  910. alignment = (PUCHAR)irp-(PUCHAR)MemoryBlock;
  911. ASSERT (alignment<=AfdAlignmentOverhead);
  912. buf = ALIGN_UP_A_POINTER((PCHAR)irp+irpSize, AfdBufferAlignment);
  913. hdr = ALIGN_UP_TO_TYPE_POINTER((PCHAR)buf+BufferDataSize, AFD_BUFFER);
  914. mdl = ALIGN_UP_TO_TYPE_POINTER((PCHAR)hdr+hdrSize, MDL);
  915. addr = (PCHAR)mdl+mdlSize;
  916. break;
  917. case AFD_PLACEMENT_HDR_IRP:
  918. hdr = ALIGN_UP_TO_TYPE_POINTER(MemoryBlock, AFD_BUFFER);
  919. alignment = (PUCHAR)hdr-(PUCHAR)MemoryBlock;
  920. ASSERT (alignment<=AfdAlignmentOverhead);
  921. irp = ALIGN_UP_TO_TYPE_POINTER((PCHAR)hdr+hdrSize, IRP);
  922. buf = ALIGN_UP_A_POINTER((PCHAR)irp+irpSize, AfdBufferAlignment);
  923. mdl = ALIGN_UP_TO_TYPE_POINTER((PCHAR)buf+BufferDataSize, MDL);
  924. addr = (PCHAR)mdl+mdlSize;
  925. break;
  926. case AFD_PLACEMENT_HDR_MDL:
  927. hdr = ALIGN_UP_TO_TYPE_POINTER(MemoryBlock, AFD_BUFFER);
  928. alignment = (PUCHAR)hdr-(PUCHAR)MemoryBlock;
  929. ASSERT (alignment<=AfdAlignmentOverhead);
  930. mdl = ALIGN_UP_TO_TYPE_POINTER((PCHAR)hdr+hdrSize, MDL);
  931. buf = ALIGN_UP_A_POINTER((PCHAR)mdl+mdlSize, AfdBufferAlignment);
  932. irp = ALIGN_UP_TO_TYPE_POINTER((PCHAR)buf+BufferDataSize, IRP);
  933. addr = (PCHAR)irp+irpSize;
  934. break;
  935. case AFD_PLACEMENT_IRP_MDL:
  936. irp = ALIGN_UP_TO_TYPE_POINTER(MemoryBlock, IRP);
  937. alignment = (PUCHAR)irp-(PUCHAR)MemoryBlock;
  938. ASSERT (alignment<=AfdAlignmentOverhead);
  939. mdl = ALIGN_UP_TO_TYPE_POINTER((PCHAR)irp+irpSize, MDL);
  940. buf = ALIGN_UP_A_POINTER((PCHAR)mdl+mdlSize, AfdBufferAlignment);
  941. hdr = ALIGN_UP_TO_TYPE_POINTER((PCHAR)buf+BufferDataSize, AFD_BUFFER);
  942. addr = (PCHAR)hdr+hdrSize;
  943. break;
  944. case AFD_PLACEMENT_HDR_IRP_MDL:
  945. hdr = ALIGN_UP_TO_TYPE_POINTER(MemoryBlock, AFD_BUFFER);
  946. alignment = (PUCHAR)hdr-(PUCHAR)MemoryBlock;
  947. ASSERT (alignment<=AfdAlignmentOverhead);
  948. irp = ALIGN_UP_TO_TYPE_POINTER((PCHAR)hdr+hdrSize, IRP);
  949. mdl = ALIGN_UP_TO_TYPE_POINTER((PCHAR)irp+irpSize, MDL);
  950. buf = ALIGN_UP_A_POINTER((PCHAR)mdl+mdlSize, AfdBufferAlignment);
  951. addr = (PCHAR)buf+BufferDataSize;
  952. break;
  953. default:
  954. ASSERT (!"Unknown placement!");
  955. __assume (0);
  956. }
  957. //
  958. // Initialize the AfdBuffer - most fields need to be 0.
  959. //
  960. RtlZeroMemory( hdr, sizeof(*hdr) );
  961. //
  962. // Setup buffer
  963. //
  964. hdr->Buffer = buf;
  965. hdr->BufferLength = BufferDataSize;
  966. //
  967. // We just need to store first two bits of placement
  968. // so we know which part comes first to free it properly.
  969. //
  970. hdr->Placement = placement & 3;
  971. //
  972. // If we have to align the memory block to meet the requirement
  973. // store this information right below the first piece.
  974. //
  975. if (alignment!=0) {
  976. C_ASSERT (AFD_MINIMUM_BUFFER_ALIGNMENT>=sizeof (SIZE_T));
  977. C_ASSERT ((AFD_MINIMUM_BUFFER_ALIGNMENT & (sizeof(SIZE_T)-1))==0);
  978. ASSERT (alignment>=sizeof (SIZE_T));
  979. hdr->AlignmentAdjusted = TRUE;
  980. *(((PSIZE_T)(((PUCHAR)MemoryBlock)+alignment))-1) = alignment;
  981. }
  982. //
  983. // Initialize the IRP pointer.
  984. //
  985. hdr->Irp = irp;
  986. IoInitializeIrp( hdr->Irp, irpSize, StackSize );
  987. hdr->Irp->MdlAddress = mdl;
  988. //
  989. // Set up the MDL pointer.
  990. //
  991. hdr->Mdl = mdl;
  992. MmInitializeMdl( hdr->Mdl, buf, BufferDataSize );
  993. MmBuildMdlForNonPagedPool( hdr->Mdl );
  994. //
  995. // Set up the address buffer pointer.
  996. //
  997. if (AddressSize>0) {
  998. hdr->TdiInfo.RemoteAddress = ALIGN_UP_TO_TYPE_POINTER(addr, TRANSPORT_ADDRESS);;
  999. hdr->AllocatedAddressLength = (USHORT)AddressSize;
  1000. }
  1001. #if DBG
  1002. hdr->BufferListEntry.Flink = UIntToPtr( 0xE0E1E2E3 );
  1003. hdr->BufferListEntry.Blink = UIntToPtr( 0xE4E5E6E7 );
  1004. #endif
  1005. return hdr;
  1006. } // AfdInitializeBuffer
  1007. VOID
  1008. AfdInitializeBufferTag (
  1009. IN PAFD_BUFFER_TAG AfdBufferTag,
  1010. IN CLONG AddressSize
  1011. )
  1012. /*++
  1013. Routine Description:
  1014. Initializes an AFD buffer. Sets up fields in the actual AFD_BUFFER
  1015. structure and initializes the IRP and MDL associated with the
  1016. buffer. This routine assumes that the caller has properly allocated
  1017. sufficient space for all this.
  1018. Arguments:
  1019. AfdBuffer - points to the AFD_BUFFER structure to initialize.
  1020. BufferDataSize - the size of the data buffer that goes along with the
  1021. buffer structure.
  1022. AddressSize - the size of data allocated for the address buffer.
  1023. ListHead - the global list this buffer belongs to, or NULL if it
  1024. doesn't belong on any list. This routine does NOT place the
  1025. buffer structure on the list.
  1026. Return Value:
  1027. None.
  1028. --*/
  1029. {
  1030. AfdBufferTag->Mdl = NULL;
  1031. AfdBufferTag->BufferLength = AfdBufferTagSize;
  1032. AfdBufferTag->TdiInfo.RemoteAddress = AddressSize ? AfdBufferTag+1 : NULL;
  1033. AfdBufferTag->AllocatedAddressLength = (USHORT)AddressSize;
  1034. AfdBufferTag->Flags = 0;
  1035. #if DBG
  1036. AfdBufferTag->BufferListEntry.Flink = UIntToPtr( 0xE0E1E2E3 );
  1037. AfdBufferTag->BufferListEntry.Blink = UIntToPtr( 0xE4E5E6E7 );
  1038. AfdBufferTag->Caller = NULL;
  1039. AfdBufferTag->CallersCaller = NULL;
  1040. #endif
  1041. }
  1042. VOID
  1043. AfdInitializeBufferManager (
  1044. VOID
  1045. )
  1046. {
  1047. SIZE_T irpSize = ALIGN_UP_A(IoSizeOfIrp (AfdTdiStackSize), AFD_MINIMUM_BUFFER_ALIGNMENT);
  1048. SIZE_T hdrSize = ALIGN_UP_A(sizeof (AFD_BUFFER), AFD_MINIMUM_BUFFER_ALIGNMENT);
  1049. SIZE_T mdlSize = ALIGN_UP_A(MmSizeOfMdl (NULL, PAGE_SIZE),AFD_MINIMUM_BUFFER_ALIGNMENT);
  1050. UCHAR placement;
  1051. ULONG i;
  1052. ULONG currentOverhead;
  1053. //
  1054. // Initialize the alignment table.
  1055. // This table is used to determine what kind of element
  1056. // placement to use in AFD_BUFFER depending on the alignment
  1057. // of the memory block returned by the executive pool manager.
  1058. // The goal is to align the data buffer on the cache line
  1059. // boundary. However, since executive only guarantees alignment of
  1060. // it's blocks at the CPU alignment requirements, we need to
  1061. // adjust and potentially waste up to CACHE_LIST_SIZE-CPU_ALIGNMENT_SIZE.
  1062. // With some machines having cache line alignment at 128 such memory
  1063. // waste is prohibitive (small buffers with default size of 128 will double
  1064. // in size).
  1065. // The table below allows us to rearrange pieces in AFD_BUFFER structure,
  1066. // namely, the header, IRP, MDL, and data buffer, so that pieces with
  1067. // lower alignment requirement can be used to consume the space needed
  1068. // to adjust the memory block to the cache line boundary.
  1069. //
  1070. // AfdAlignmentTable has an entry for each possible case of memory block
  1071. // misaligned against cache line size. For example, in typical X86 system
  1072. // case executive pool manager always returns blocks aligned on 8 byte bounday,
  1073. // while cache lines are typically 64 bytes long, so memory manager can
  1074. // theoretically return blocks misaligned against cache by:
  1075. // 8, 16, 24, 32, 40, 48, 56.
  1076. // For each of these cases we will try to adjust the alignment by using
  1077. // any possible combination of header, IRP, and MDL. There will be some
  1078. // cases that cannot be adjusted exactly, and we will have to pad.
  1079. //
  1080. //
  1081. // First initialize the table assuming the data buffer is placed first.
  1082. //
  1083. RtlFillMemory (AfdAlignmentTable, AfdAlignmentTableSize, AFD_PLACEMENT_BUFFER);
  1084. #ifdef AFD_CHECK_ALIGNMENT
  1085. RtlZeroMemory (&AfdAlignmentTable[AfdAlignmentTableSize],
  1086. AfdAlignmentTableSize*sizeof(LONG));
  1087. #endif
  1088. //
  1089. // Now identify the entries that can be padded with some combination of
  1090. // header, IRP, and MDL:
  1091. // extract the bits that can be used for padding
  1092. // reverse to get corresponding memory block alignments
  1093. // divide by the step of the alignment table
  1094. // make sure we won't go past table size (last entry => 0 entry).
  1095. //
  1096. #define AfdInitAlignmentTableRow(_size,_plcmnt) \
  1097. AfdAlignmentTable[ \
  1098. ((AfdBufferAlignment-(_size&(AfdBufferAlignment-1))) \
  1099. /AFD_MINIMUM_BUFFER_ALIGNMENT) \
  1100. &(AfdAlignmentTableSize-1)] = _plcmnt
  1101. //
  1102. // We let placements beginning with header override others,
  1103. // since it is more natural and easier to debug (header has references
  1104. // to other pieces).
  1105. //
  1106. AfdInitAlignmentTableRow(mdlSize,AFD_PLACEMENT_MDL);
  1107. AfdInitAlignmentTableRow(irpSize,AFD_PLACEMENT_IRP);
  1108. AfdInitAlignmentTableRow((irpSize+mdlSize),AFD_PLACEMENT_IRP_MDL);
  1109. AfdInitAlignmentTableRow((hdrSize+mdlSize),AFD_PLACEMENT_HDR_MDL);
  1110. AfdInitAlignmentTableRow((hdrSize+irpSize),AFD_PLACEMENT_HDR_IRP);
  1111. AfdInitAlignmentTableRow((hdrSize+irpSize+mdlSize),AFD_PLACEMENT_HDR_IRP_MDL);
  1112. AfdInitAlignmentTableRow(hdrSize,AFD_PLACEMENT_HDR);
  1113. //
  1114. // Now scan the table from top to bottom and fill entries that do not have
  1115. // exact match using the above combinations. Use the closest entry above and
  1116. // in the process compute how much do we need to pad in addition to padding
  1117. // achieved via placement.
  1118. //
  1119. AfdAlignmentOverhead = 0;
  1120. currentOverhead = 0;
  1121. //
  1122. // By default use the placement of aligned block.
  1123. //
  1124. placement = AfdAlignmentTable[0];
  1125. for (i=AfdAlignmentTableSize-1; i>0; i--) {
  1126. if (AfdAlignmentTable[i]==AFD_PLACEMENT_BUFFER) {
  1127. AfdAlignmentTable[i] = placement;
  1128. currentOverhead += AFD_MINIMUM_BUFFER_ALIGNMENT;
  1129. }
  1130. else {
  1131. placement = AfdAlignmentTable[i];
  1132. if (AfdAlignmentOverhead<currentOverhead) {
  1133. AfdAlignmentOverhead = currentOverhead;
  1134. }
  1135. currentOverhead = 0;
  1136. }
  1137. }
  1138. if (AfdAlignmentOverhead<currentOverhead) {
  1139. AfdAlignmentOverhead = currentOverhead;
  1140. }
  1141. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  1142. "AfdInitializeBufferManager: Alignment requirements: MM-%d, cache-%d, overhead-%d\n",
  1143. AFD_MINIMUM_BUFFER_ALIGNMENT,
  1144. AfdBufferAlignment,
  1145. AfdAlignmentOverhead));
  1146. {
  1147. CLONG oldBufferLengthForOnePage = AfdBufferLengthForOnePage;
  1148. AfdBufferOverhead = AfdCalculateBufferSize(
  1149. PAGE_SIZE,
  1150. AfdStandardAddressLength,
  1151. AfdTdiStackSize) - PAGE_SIZE;
  1152. AfdBufferLengthForOnePage = ALIGN_DOWN_A(
  1153. PAGE_SIZE-AfdBufferOverhead,
  1154. AFD_MINIMUM_BUFFER_ALIGNMENT);
  1155. if (AfdLargeBufferSize==oldBufferLengthForOnePage) {
  1156. AfdLargeBufferSize = AfdBufferLengthForOnePage;
  1157. }
  1158. }
  1159. }