Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. // memman.cpp : Defines the entry point for the console application.
  2. //
  3.  
  4. #include "kosSyst.h"
  5. #include "mcsmemm.h"
  6.  
  7.  
  8. void * __cdecl operator new ( size_t count, size_t element_size )
  9. {
  10.         return allocmem( (Dword)(count * element_size) );
  11. }
  12.  
  13. void * __cdecl operator new [] ( size_t amount )
  14. {
  15.         return allocmem( (Dword)amount );
  16. }
  17.  
  18. void * __cdecl operator new ( size_t amount )
  19. {
  20.         return allocmem( (Dword)amount );
  21. }
  22.  
  23. void __cdecl operator delete ( void *pointer )
  24. {
  25.         if ( pointer != NULL ) freemem( pointer );
  26. }
  27.  
  28. void __cdecl operator delete [] ( void *pointer )
  29. {
  30.         if ( pointer != NULL ) freemem( pointer );
  31. }
  32.  
  33.  
  34. //
  35. Dword mmMutex = FALSE;
  36. MemBlock *rootfree = NULL;
  37. MemBlock *rootuser = NULL;
  38. bool mmInitialized = false;
  39. Byte *mmHeapTop = NULL;
  40.  
  41.  
  42. //
  43. Byte * AllocMemFromSystem( Dword reqSize )
  44. {
  45.         Byte *result;
  46.         sProcessInfo pInfo;
  47.        
  48.         //
  49.         if ( mmInitialized )
  50.         {
  51.                 result = mmHeapTop;
  52.         }
  53.         else
  54.         {
  55.                 //
  56.                 kos_ProcessInfo( &pInfo );
  57.                 //
  58.                 result = (Byte *)(pInfo.processInfo.used_memory + 1);
  59.                 //
  60.                 mmInitialized = true;
  61.         }
  62.         //
  63.         if ( ! kos_ApplicationMemoryResize( ((Dword)result) + reqSize ) )
  64.         {
  65.                 result = NULL;
  66.         }
  67.         //
  68.         mmHeapTop = result + reqSize;
  69.         //
  70.         return result;
  71. }
  72.  
  73.  
  74. //
  75. Byte *allocmem( Dword reqsize )
  76. {
  77.   MemBlock *BlockForCheck;
  78.   MemBlock *LastKnownGood;
  79.   Dword tail;
  80.   Byte *address;
  81.  
  82.   //ïîäðîâíÿåì ðàçìåð
  83.   if( ( tail = reqsize % SIZE_ALIGN ) != 0 )
  84.   {
  85.     reqsize += SIZE_ALIGN - tail;
  86.   }
  87.  
  88.   LastKnownGood = NULL;
  89.  
  90.   // æä¸ì îñâîáîæäåíèÿ ìüþòåêñà
  91.   while ( rtlInterlockedExchange( &mmMutex, TRUE ) )
  92.   {
  93.           //
  94.           kos_Pause( 1 );
  95.   }
  96.  
  97.   //èùåì ïîäõîäÿùèé ñâîáîäíûé áëîê
  98.   if( rootfree != NULL )
  99.   {
  100.     for ( BlockForCheck = rootfree; ; BlockForCheck = BlockForCheck->Next )
  101.     {
  102.       if ( BlockForCheck->Size >= reqsize )
  103.       {
  104.         //íàøëè
  105.         if ( LastKnownGood != NULL )
  106.         {
  107.           if ( LastKnownGood->Size >= BlockForCheck->Size )
  108.             LastKnownGood = BlockForCheck;
  109.         }
  110.         else
  111.           LastKnownGood = BlockForCheck;
  112.         if ( LastKnownGood->Size == reqsize )
  113.           break;
  114.       }
  115.       if ( BlockForCheck->Next == NULL )
  116.         break;
  117.     }
  118.   }
  119.  
  120.   if ( LastKnownGood != NULL )
  121.   {
  122.     //ïðîâåðèì íàéäåííûé áëîê íà âîçìîæíîñòü äåëåíèÿ
  123.     tail = LastKnownGood->Size - reqsize;
  124.     if ( tail >= ( sizeof(MemBlock) + SIZE_ALIGN ) )
  125.     {
  126.       //áóäåì ðàçáèâàòü
  127.       BlockForCheck = (MemBlock *)( ( (Byte *)LastKnownGood ) + tail );
  128.       BlockForCheck->Size = reqsize;
  129.       //âñòàâèì çàíÿòûé áëîê â íà÷àëî ñïèñêà çàíàòûõ áëîêîâ
  130.       if( rootuser != NULL )
  131.       {
  132.         BlockForCheck->Next = rootuser;
  133.         rootuser->Previous = BlockForCheck;
  134.         BlockForCheck->Previous = NULL;
  135.         rootuser = BlockForCheck;
  136.       }
  137.       else
  138.       {
  139.         rootuser = BlockForCheck;
  140.         BlockForCheck->Next = NULL;
  141.         BlockForCheck->Previous = NULL;
  142.       }
  143.  
  144.       //èçìåíèì ðàçìåð îñòàâøåéñÿ ÷àñòè
  145.       LastKnownGood->Size = tail - sizeof(MemBlock);
  146.       address = ( (Byte *)BlockForCheck ) + sizeof(MemBlock);
  147.  
  148.           // îòïóñòèì ìüþòåêñ
  149.       rtlInterlockedExchange( &mmMutex, FALSE );
  150.  
  151.       return address;
  152.     }
  153.     else
  154.     {
  155.       //ïåðåìåñòè áëîê èç î÷åðåäè ñâîáîäíûõ â íà÷àëî î÷åðåäè çàíÿòûõ
  156.       //ñíà÷àëà âûêèíåì åãî èç î÷åðåäè ñâîáîäíûõ
  157.       if ( LastKnownGood->Previous != NULL )
  158.       {
  159.         LastKnownGood->Previous->Next = LastKnownGood->Next;
  160.       }
  161.       else
  162.       {
  163.         //áëîê ñòîèò â íà÷àëå î÷åðåäè
  164.         rootfree = LastKnownGood->Next;
  165.       }
  166.       if( LastKnownGood->Next != NULL )
  167.       {
  168.         LastKnownGood->Next->Previous = LastKnownGood->Previous;
  169.       }
  170.       //òåïåðü âñòàâèì åãî â î÷åðåäü çàíÿòûõ
  171.       if( rootuser != NULL )
  172.       {
  173.         LastKnownGood->Next = rootuser;
  174.         rootuser->Previous = LastKnownGood;
  175.         LastKnownGood->Previous = NULL;
  176.         rootuser = LastKnownGood;
  177.       }
  178.       else
  179.       {
  180.         rootuser = LastKnownGood;
  181.         LastKnownGood->Next = NULL;
  182.         LastKnownGood->Previous = NULL;
  183.       }
  184.           //
  185.       address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock);
  186.  
  187.           // îòïóñòèì ìüþòåêñ
  188.       rtlInterlockedExchange( &mmMutex, FALSE );
  189.  
  190.       return address;
  191.     }
  192.   }
  193.   else
  194.   {
  195.     //íàäî ïîëó÷èòü åù¸ êóñî÷åê ïàìÿòè
  196.     LastKnownGood = (MemBlock *)AllocMemFromSystem( reqsize + sizeof(MemBlock) );
  197.         //
  198.     if( LastKnownGood != NULL )
  199.     {
  200.       LastKnownGood->Size = reqsize;
  201.       //òåïåðü âñòàâèì åãî â î÷åðåäü çàíÿòûõ
  202.       if( rootuser != NULL )
  203.       {
  204.         LastKnownGood->Next = rootuser;
  205.         rootuser->Previous = LastKnownGood;
  206.         LastKnownGood->Previous = NULL;
  207.         rootuser = LastKnownGood;
  208.       }
  209.       else
  210.       {
  211.         rootuser = LastKnownGood;
  212.         LastKnownGood->Next = NULL;
  213.         LastKnownGood->Previous = NULL;
  214.       }
  215.       address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock);
  216.  
  217.           // îòïóñòèì ìüþòåêñ
  218.       rtlInterlockedExchange( &mmMutex, FALSE );
  219.  
  220.       return address;
  221.     }
  222.   }
  223.  
  224.   // îòïóñòèì ìüþòåêñ
  225.   rtlInterlockedExchange( &mmMutex, FALSE );
  226.  
  227.   //
  228.   rtlDebugOutString( "allocmem failed." );
  229.   kos_ExitApp();
  230.   //
  231.   return NULL;
  232. }
  233.  
  234. //
  235. Dword freemem( void *vaddress )
  236. {
  237.   Dword result;
  238.  
  239.   Byte *checknext, *address = (Byte *)vaddress;
  240.                                
  241.   // æä¸ì îñâîáîæäåíèÿ ìüþòåêñà
  242.   while ( rtlInterlockedExchange( &mmMutex, TRUE ) )
  243.   {
  244.           //
  245.           kos_Pause( 1 );
  246.   }
  247.  
  248.   MemBlock *released = (MemBlock *)( address - sizeof(MemBlock) );
  249.  
  250.   result = released->Size;
  251.  
  252.   //óáèðàåì áëîê èç ñïèñêà çàíÿòûõ
  253.   if ( released->Previous != NULL )
  254.   {
  255.     released->Previous->Next = released->Next;
  256.   }
  257.   else
  258.   {
  259.     rootuser = released->Next;
  260.   }
  261.   if ( released->Next != NULL )
  262.   {
  263.     released->Next->Previous = released->Previous;
  264.   }
  265.   //çàêèíåì òåïåðü ýòîò áëîê â ñïèñîê ñâîáîäíûõ
  266.   released->Next = rootfree;
  267.   released->Previous = NULL;
  268.   rootfree = released;
  269.   if ( released->Next != NULL )
  270.   {
  271.     released->Next->Previous = released;
  272.   }
  273.  
  274.   //òåïåðü ïîèùåì ñìåæíûå ñâîáîäíûå áëîêè
  275.   checknext = (Byte *)(rootfree) + ( rootfree->Size + sizeof(MemBlock) );
  276.   //
  277.   for ( released = rootfree->Next; released != NULL; released = released->Next )
  278.   {
  279.     if ( checknext == (Byte *)released )
  280.     {
  281.       //ñîáèðàåì áëîêè âìåñòå
  282.       //ñíà÷àëà âûêèíåì èç î÷åðåäè ñâîáîäíûõ
  283.       released->Previous->Next = released->Next;
  284.       if( released->Next != NULL )
  285.       {
  286.         released->Next->Previous = released->Previous;
  287.       }
  288.       //òåïåðü óâåëè÷èì ðàçìåð êîðíåâîãî áëîêà
  289.       rootfree->Size += released->Size + sizeof(MemBlock);
  290.       break;
  291.     }
  292.   }
  293.   //åñëè íàäî, ïîèùåì áëîêè ïåðåä òåêùèì.
  294.   checknext = (Byte *)(rootfree);
  295.   //
  296.   if ( released == NULL )
  297.   {
  298.     for ( released = rootfree->Next; released != NULL; released = released->Next )
  299.     {
  300.       if ( checknext == (Byte *)released + ( released->Size + sizeof(MemBlock) ) )
  301.       {
  302.         //ñîáèðàåì áëîêè âìåñòå
  303.         //óâåëè÷èì ðàçìåð áëîêà
  304.         released->Size += rootfree->Size + sizeof(MemBlock);
  305.         //òåïåðü âûêèíåì èç î÷åðåäè ñâîáîäíûõ
  306.         released->Previous->Next = released->Next;
  307.         if ( released->Next != NULL )
  308.         {
  309.           released->Next->Previous = released->Previous;
  310.         }
  311.         //è çàêèíåì åãî â íà÷àëî î÷åðåäè âìåñòî ïðèñîåäèí¸ííîãî áëîêà èç êîðíÿ ñïèñêà
  312.         if ( rootfree->Next != NULL )
  313.         {
  314.           rootfree->Next->Previous = released;
  315.         }
  316.         released->Next = rootfree->Next;
  317.         released->Previous = NULL;
  318.         rootfree = released;
  319.         break;
  320.       }
  321.     }
  322.   }
  323.  
  324.   // îòïóñòèì ìüþòåêñ
  325.   rtlInterlockedExchange( &mmMutex, FALSE );
  326.  
  327.   return result;
  328. }
  329.  
  330.