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.

516 lines
9.8 KiB

  1. /*++
  2. packet.cpp
  3. This file contains the code which implements the CPacket derived classes.
  4. A CPacket derived object describes the most basic IO operation that is performed.
  5. --*/
  6. #include "stdinc.h"
  7. #ifdef CIO_DEBUG
  8. #include <stdlib.h> // For Rand() function
  9. #endif
  10. #ifdef _NO_TEMPLATES_
  11. DECLARE_ORDEREDLISTFUNC( CPacket )
  12. #endif
  13. //
  14. // Module globals
  15. //
  16. CPool CBufferAllocator::rgPool[ MAX_BUFFER_SIZES ] ;//!!!How do you give this a signature?
  17. DWORD CBufferAllocator::rgPoolSizes[ MAX_BUFFER_SIZES ] ;
  18. CBufferAllocator CBuffer::gAllocator ;
  19. CBufferAllocator* CSmallBufferCache::BufferAllocator = 0 ;
  20. CBufferAllocator* CMediumBufferCache::BufferAllocator = 0 ;
  21. CSmallBufferCache* CBuffer::gpDefaultSmallCache = 0 ;
  22. CMediumBufferCache* CBuffer::gpDefaultMediumCache = 0 ;
  23. //
  24. // Control what size buffers the server uses
  25. //
  26. DWORD cbLargeBufferSize = 33 * 1024 ;
  27. DWORD cbMediumBufferSize = 4 * 1024 ;
  28. DWORD cbSmallBufferSize = 512 ;
  29. BOOL
  30. CBufferAllocator::InitClass( ) {
  31. /*++
  32. Routine Description :
  33. This function initializes the CBufferAllocator class which handles all
  34. memory management of CBuffer objects.
  35. We will use three different CPools to produce CBuffers of different sizes.
  36. Arguments :
  37. None.
  38. Return Value :
  39. TRUE if successfull false otherwise !
  40. --*/
  41. rgPoolSizes[0] = cbSmallBufferSize ;
  42. rgPoolSizes[1] = cbMediumBufferSize ;
  43. rgPoolSizes[2] = cbLargeBufferSize ;
  44. for( int i=0; i< sizeof( rgPoolSizes ) / sizeof( rgPoolSizes[0] ); i++ ) {
  45. if( !rgPool[i].ReserveMemory( MAX_BUFFERS / ((i+1)*(i+1)), rgPoolSizes[i] ) ) break ;
  46. }
  47. if( i != sizeof( rgPoolSizes ) / sizeof( rgPoolSizes[0] ) ) {
  48. for( i--; i!=0; i-- ) {
  49. rgPool[i].ReleaseMemory() ;
  50. }
  51. return FALSE ;
  52. }
  53. return TRUE ;
  54. }
  55. BOOL
  56. CBufferAllocator::TermClass() {
  57. /*++
  58. Routine Description :
  59. Clean up all the CPool objects we use to manage CBuffer memory
  60. Arguments :
  61. None.
  62. Return Value ;
  63. TRUE if successfull FALSE otherwise.
  64. --*/
  65. BOOL fSuccess = TRUE ;
  66. for( int i=0; i< sizeof( rgPoolSizes ) / sizeof( rgPoolSizes[0] ); i++ ) {
  67. _ASSERT( rgPool[i].GetAllocCount() == 0 ) ;
  68. fSuccess &= rgPool[i].ReleaseMemory() ;
  69. }
  70. return fSuccess ;
  71. }
  72. LPVOID
  73. CBufferAllocator::Allocate(
  74. DWORD cb,
  75. DWORD& cbOut
  76. ) {
  77. /*++
  78. Routine description :
  79. Allocate the memory required for a CBuffer object from the CPool which
  80. will provide a large enough block of memory.
  81. We will use a portion of the allocated memory to hold a pointer back to
  82. the particular CPool from which this memory was allocated
  83. Arguments :
  84. cb - Number of bytes required
  85. cbOut - Number of bytes allocated for the CBuffer
  86. Return Value :
  87. Pointer to the allocated block of memory - NULL on failure
  88. --*/
  89. //cb += sizeof( CBuffer ) ;
  90. cb += sizeof( CPool* ) ;
  91. //_ASSERT( size == sizeof( CBuffer ) ) ;
  92. cbOut = 0 ;
  93. for( int i=0; i<sizeof(rgPoolSizes)/sizeof(rgPoolSizes[0]); i++ ) {
  94. if( cb < rgPoolSizes[i] ) {
  95. cbOut = rgPoolSizes[i] - sizeof( CPool * ) ;
  96. void *pv = rgPool[i].Alloc() ;
  97. if( pv == 0 ) {
  98. return 0 ;
  99. }
  100. ((CPool **)pv)[0] = &rgPool[i] ;
  101. return (void *)&(((CPool **)pv)[1]) ;
  102. }
  103. }
  104. _ASSERT( 1==0 ) ;
  105. return 0 ;
  106. }
  107. void
  108. CBufferAllocator::Release(
  109. void* pv
  110. ) {
  111. /*++
  112. Routine description :
  113. Release memory that was used for a CBuffer object back to its CPool
  114. examine the DWORD before the allocated memory to figure out which CPool
  115. to release this too.
  116. Arguments :
  117. pv - the memory being released
  118. Return Value :
  119. None.
  120. --*/
  121. CPool** pPool = (CPool**)pv ;
  122. pPool[-1]->Free( (void*)&(pPool[-1]) ) ;
  123. }
  124. #ifdef DEBUG
  125. //
  126. // Debug functions - the following functions all do various forms of validation
  127. // to ensure that memory is being properly manipulated
  128. //
  129. int
  130. CBufferAllocator::GetPoolIndex(
  131. void* lpv
  132. ) {
  133. /*++
  134. Routine Description :
  135. figure out which pool this block of memory was allocated out of.
  136. Agruments :
  137. lpv - pointer to a block of memory allocated by CBufferAllocator
  138. when it was allocated we stuck a pointer to the CPool we used
  139. ahead of the pointer
  140. Return Value :
  141. index of the pool used to allocate the buffer
  142. --*/
  143. CPool** pPool = (CPool**)lpv ;
  144. CPool* pool = pPool[-1] ;
  145. for( int i=0; i < sizeof(rgPoolSizes)/sizeof(rgPoolSizes[0]); i++ ) {
  146. if( pool == &rgPool[i] ) {
  147. return i ;
  148. }
  149. }
  150. return -1 ;
  151. }
  152. void
  153. CBufferAllocator::Erase(
  154. void* lpv
  155. ) {
  156. /*++
  157. Routine Description :
  158. Fill a block of released memory so it is easy to spot during debug.
  159. Arguments :
  160. lpv - released memory
  161. Returns :
  162. Nothing
  163. --*/
  164. int i = GetPoolIndex( lpv ) ;
  165. _ASSERT( i >= 0 ) ;
  166. DWORD cb = rgPoolSizes[i] - sizeof( CPool*) ;
  167. FillMemory( (BYTE*)lpv, cb, 0xCC ) ;
  168. }
  169. BOOL
  170. CBufferAllocator::EraseCheck(
  171. void* lpv
  172. ) {
  173. /*++
  174. Routine Description :
  175. Verify that a block of memory has been erased using CBufferAllocator::Erase()
  176. Arguments :
  177. lpv - released memory
  178. Returns :
  179. TRUE if correctly erased
  180. FALSE otherwise
  181. --*/
  182. int i = GetPoolIndex( lpv ) ;
  183. _ASSERT( i>=0 ) ;
  184. DWORD cb = rgPoolSizes[i] - sizeof( CPool* ) ;
  185. for( DWORD j=sizeof(CPool*); j < cb; j++ ) {
  186. if( ((BYTE*)lpv)[j] != 0xCC )
  187. return FALSE ;
  188. }
  189. return TRUE ;
  190. }
  191. BOOL
  192. CBufferAllocator::RangeCheck(
  193. void* lpv
  194. ) {
  195. /*++
  196. Routine Description :
  197. Check that a block of memory is actually something that
  198. we would allocate. Unfortunately, this is hard to do
  199. with the current CPool interface.
  200. Arguments :
  201. lpv - block of memory
  202. Return Value :
  203. Always TRUE
  204. --*/
  205. //
  206. // Need to modify CPool so we can examine the address range into which objects fall !
  207. //
  208. return TRUE ;
  209. }
  210. BOOL
  211. CBufferAllocator::SizeCheck(
  212. DWORD cb
  213. ) {
  214. /*++
  215. Routine Description :
  216. Check that we are trying to allocate a size which is legal
  217. for this allocater.
  218. Arguments :
  219. cb - the requested size
  220. Return Value :
  221. TRUE if legit, FALSE otherwise.
  222. --*/
  223. return (cb + sizeof( CPool* )) < rgPoolSizes[2] ;
  224. }
  225. #endif // DEBUG
  226. BOOL CBuffer::gTerminate = FALSE ;
  227. BOOL
  228. CBuffer::InitClass() {
  229. /*++
  230. Routine Description :
  231. This class initializes the CBufferClass.
  232. Arguemtns :
  233. None.
  234. Return Value :
  235. TRUE if successfull.
  236. --*/
  237. gTerminate = FALSE ;
  238. if( CBufferAllocator::InitClass() ) {
  239. CSmallBufferCache::InitClass( &gAllocator ) ;
  240. CMediumBufferCache::InitClass( &gAllocator ) ;
  241. gpDefaultSmallCache = XNEW CSmallBufferCache() ;
  242. gpDefaultMediumCache = XNEW CMediumBufferCache() ;
  243. if( gpDefaultSmallCache == 0 ||
  244. gpDefaultMediumCache == 0 ) {
  245. if( gpDefaultMediumCache != 0 ) {
  246. XDELETE gpDefaultMediumCache ;
  247. gpDefaultMediumCache = 0 ;
  248. }
  249. if( gpDefaultSmallCache != 0 ) {
  250. XDELETE gpDefaultSmallCache ;
  251. gpDefaultSmallCache = 0 ;
  252. }
  253. CBufferAllocator::TermClass() ;
  254. return gTerminate ;
  255. } else {
  256. gTerminate = TRUE ;
  257. }
  258. }
  259. return gTerminate ;
  260. }
  261. BOOL
  262. CBuffer::TermClass() {
  263. /*++
  264. Routine Description :
  265. Terminate the CBuffer class - release everything ever allocated
  266. through this class.
  267. Arguments :
  268. None.
  269. Return Value :
  270. TRUE if successfull.
  271. --*/
  272. if( gpDefaultMediumCache != 0 ) {
  273. XDELETE gpDefaultMediumCache ;
  274. gpDefaultMediumCache = 0 ;
  275. }
  276. if( gpDefaultSmallCache != 0 ) {
  277. XDELETE gpDefaultSmallCache ;
  278. gpDefaultSmallCache = 0 ;
  279. }
  280. if( !gTerminate ) {
  281. return TRUE ;
  282. } else {
  283. return CBufferAllocator::TermClass() ;
  284. }
  285. }
  286. void*
  287. CBuffer::operator new(
  288. size_t size,
  289. DWORD cb,
  290. DWORD &cbOut,
  291. CSmallBufferCache* pCache,
  292. CMediumBufferCache* pMediumCache
  293. ) {
  294. /*++
  295. Routine Description :
  296. Allocate a buffer of a specified size, if possible from a Cache.
  297. Arguments :
  298. size - size being requested - this will be the size of CBuffer itself as
  299. generated by the compiler. not so usefull as we intend m_rgbBuff to
  300. be variable sized.
  301. cb - Caller provided size - this indicates how big we want the buffer
  302. to be and tells us we need to allocate a block big support a
  303. m_rgbBuff of that size
  304. cbOut - Out parameter - get the exact sizeof m_rgbBuff that can be
  305. accommodated
  306. pCache - Cache from which to allocate small buffers
  307. pMediumCache - Cache from which to allocate medium sized buffers
  308. Return Value :
  309. pointer to allocated block (NULL on failure).
  310. --*/
  311. //
  312. // Validate args - default args for pCache and pMediumCache
  313. // should ensure these are never NULL
  314. //
  315. _ASSERT( pCache != 0 ) ;
  316. _ASSERT( pMediumCache != 0 ) ;
  317. cb += sizeof( CBuffer ) ;
  318. _ASSERT( size == sizeof( CBuffer ) ) ;
  319. void* pv = 0 ;
  320. if( cb <= CBufferAllocator::rgPoolSizes[0] ) {
  321. pv = pCache->Alloc( cb, cbOut ) ;
  322. } else if( cb <= CBufferAllocator::rgPoolSizes[1] ) {
  323. pv = pMediumCache->Alloc( cb, cbOut ) ;
  324. } else {
  325. pv = gAllocator.Allocate( cb, cbOut ) ;
  326. }
  327. if( pv != 0 ) {
  328. cbOut -= sizeof( CBuffer ) ;
  329. }
  330. _ASSERT( cbOut >= (cb - sizeof(CBuffer)) ) ;
  331. return pv ;
  332. }
  333. void
  334. CBuffer::operator delete(
  335. void* pv
  336. ) {
  337. /*++
  338. Routine Description :
  339. Release a block of memory allocated to hold a CBuffer object to
  340. some place.
  341. Arguments :
  342. pv - block of memory being released.
  343. Return Value :
  344. none.
  345. --*/
  346. CPool** pPool = (CPool**)pv ;
  347. if( pPool[-1] == &CBufferAllocator::rgPool[0] )
  348. gpDefaultSmallCache->Free( pv ) ;
  349. else if (pPool[-1] == &CBufferAllocator::rgPool[1] )
  350. gpDefaultMediumCache->Free( pv ) ;
  351. else
  352. gAllocator.Release( pv ) ;
  353. }
  354. void
  355. CBuffer::Destroy(
  356. CBuffer* pbuffer,
  357. CSmallBufferCache* pCache
  358. ) {
  359. if( pCache == 0 ) {
  360. delete pbuffer ;
  361. } else {
  362. pCache->Free( (void*)pbuffer ) ;
  363. }
  364. }