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.

144 lines
3.1 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. bsfixalloc.cpp
  5. Abstract:
  6. Adapted from MFC 6 SR 1 release of fixalloc.cpp. Removed all MFC stuff.
  7. Author:
  8. Stefan R. Steiner [ssteiner] 4-10-2000
  9. Revision History:
  10. --*/
  11. // fixalloc.cpp - implementation of fixed block allocator
  12. #include "stdafx.h"
  13. #include "bsfixalloc.h"
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. // #define new DEBUG_NEW
  18. #endif
  19. /////////////////////////////////////////////////////////////////////////////
  20. // CBsFixedAlloc
  21. CBsFixedAlloc::CBsFixedAlloc(UINT nAllocSize, UINT nBlockSize)
  22. {
  23. ASSERT(nAllocSize >= sizeof(CNode));
  24. ASSERT(nBlockSize > 1);
  25. //wprintf( L"CBsFixedAlloc called, nAllocSize: %d, nBlockSize: %d\n", nAllocSize, nBlockSize );
  26. m_nAllocSize = nAllocSize;
  27. m_nBlockSize = nBlockSize;
  28. m_pNodeFree = NULL;
  29. m_pBlocks = NULL;
  30. InitializeCriticalSection(&m_protect);
  31. }
  32. CBsFixedAlloc::~CBsFixedAlloc()
  33. {
  34. FreeAll();
  35. DeleteCriticalSection(&m_protect);
  36. }
  37. void CBsFixedAlloc::FreeAll()
  38. {
  39. EnterCriticalSection(&m_protect);
  40. m_pBlocks->FreeDataChain();
  41. m_pBlocks = NULL;
  42. m_pNodeFree = NULL;
  43. LeaveCriticalSection(&m_protect);
  44. }
  45. void* CBsFixedAlloc::Alloc()
  46. {
  47. EnterCriticalSection(&m_protect);
  48. if (m_pNodeFree == NULL)
  49. {
  50. CBsPlex* pNewBlock = NULL;
  51. try
  52. {
  53. // add another block
  54. pNewBlock = CBsPlex::Create(m_pBlocks, m_nBlockSize, m_nAllocSize);
  55. //wprintf( L"Alloc getting more core, nAllocSize: %d\n", m_nAllocSize );
  56. }
  57. catch( ... )
  58. {
  59. LeaveCriticalSection(&m_protect);
  60. throw;
  61. }
  62. // chain them into free list
  63. CNode* pNode = (CNode*)pNewBlock->data();
  64. // free in reverse order to make it easier to debug
  65. (BYTE*&)pNode += (m_nAllocSize * m_nBlockSize) - m_nAllocSize;
  66. for (int i = m_nBlockSize-1; i >= 0; i--, (BYTE*&)pNode -= m_nAllocSize)
  67. {
  68. pNode->pNext = m_pNodeFree;
  69. m_pNodeFree = pNode;
  70. }
  71. }
  72. ASSERT(m_pNodeFree != NULL); // we must have something
  73. // remove the first available node from the free list
  74. void* pNode = m_pNodeFree;
  75. m_pNodeFree = m_pNodeFree->pNext;
  76. LeaveCriticalSection(&m_protect);
  77. return pNode;
  78. }
  79. void CBsFixedAlloc::Free(void* p)
  80. {
  81. if (p != NULL)
  82. {
  83. EnterCriticalSection(&m_protect);
  84. // simply return the node to the free list
  85. CNode* pNode = (CNode*)p;
  86. pNode->pNext = m_pNodeFree;
  87. m_pNodeFree = pNode;
  88. LeaveCriticalSection(&m_protect);
  89. }
  90. }
  91. /////////////////////////////////////////////////////////////////////////////
  92. // CBsPlex
  93. // throws E_OUTOFMEMORY
  94. CBsPlex* PASCAL CBsPlex::Create(CBsPlex*& pHead, UINT nMax, UINT cbElement)
  95. {
  96. ASSERT(nMax > 0 && cbElement > 0);
  97. CBsPlex* p = (CBsPlex*) new BYTE[sizeof(CBsPlex) + nMax * cbElement];
  98. if ( p == NULL ) // prefix #118827
  99. throw E_OUTOFMEMORY;
  100. p->pNext = pHead;
  101. pHead = p; // change head (adds in reverse order for simplicity)
  102. return p;
  103. }
  104. void CBsPlex::FreeDataChain() // free this one and links
  105. {
  106. CBsPlex* p = this;
  107. while (p != NULL)
  108. {
  109. BYTE* bytes = (BYTE*) p;
  110. CBsPlex* pNext = p->pNext;
  111. delete[] bytes;
  112. p = pNext;
  113. }
  114. }