forked from KolibriOS/kolibrios
c2fbdf929c
git-svn-id: svn://kolibrios.org@1805 a494cfbc-eb01-0410-851d-a64ba20cac60
299 lines
7.4 KiB
C++
299 lines
7.4 KiB
C++
// memman.cpp : Defines the entry point for the console application.
|
|
//
|
|
|
|
#include "kosSyst.h"
|
|
#include "mcsmemm.h"
|
|
|
|
|
|
void * __cdecl operator new ( size_t count, size_t element_size )
|
|
{
|
|
return allocmem( (Dword)(count * element_size) );
|
|
}
|
|
|
|
void * __cdecl operator new [] ( size_t amount )
|
|
{
|
|
return allocmem( (Dword)amount );
|
|
}
|
|
|
|
void * __cdecl operator new ( size_t amount )
|
|
{
|
|
return allocmem( (Dword)amount );
|
|
}
|
|
|
|
void __cdecl operator delete ( void *pointer )
|
|
{
|
|
if ( pointer != NULL ) freemem( pointer );
|
|
}
|
|
|
|
void __cdecl operator delete [] ( void *pointer )
|
|
{
|
|
if ( pointer != NULL ) freemem( pointer );
|
|
}
|
|
|
|
|
|
//
|
|
Dword mmMutex = FALSE;
|
|
MemBlock *rootfree = NULL;
|
|
MemBlock *rootuser = NULL;
|
|
bool mmInitialized = false;
|
|
Byte *mmHeapTop = NULL;
|
|
|
|
|
|
//
|
|
Byte *allocmem( Dword reqsize )
|
|
{
|
|
MemBlock *BlockForCheck;
|
|
MemBlock *LastKnownGood;
|
|
Dword tail;
|
|
Byte *address;
|
|
|
|
//ïîäðîâíÿåì ðàçìåð
|
|
if( ( tail = reqsize % SIZE_ALIGN ) != 0 )
|
|
{
|
|
reqsize += SIZE_ALIGN - tail;
|
|
}
|
|
|
|
LastKnownGood = NULL;
|
|
|
|
// æä¸ì îñâîáîæäåíèÿ ìüþòåêñà
|
|
while ( rtlInterlockedExchange( &mmMutex, TRUE ) )
|
|
{
|
|
//
|
|
kos_Pause( 1 );
|
|
}
|
|
|
|
//èùåì ïîäõîäÿùèé ñâîáîäíûé áëîê
|
|
if( rootfree != NULL )
|
|
{
|
|
for ( BlockForCheck = rootfree; ; BlockForCheck = BlockForCheck->Next )
|
|
{
|
|
if ( BlockForCheck->Size >= reqsize )
|
|
{
|
|
//íàøëè
|
|
if ( LastKnownGood != NULL )
|
|
{
|
|
if ( LastKnownGood->Size >= BlockForCheck->Size )
|
|
LastKnownGood = BlockForCheck;
|
|
}
|
|
else
|
|
LastKnownGood = BlockForCheck;
|
|
if ( LastKnownGood->Size == reqsize )
|
|
break;
|
|
}
|
|
if ( BlockForCheck->Next == NULL )
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( LastKnownGood != NULL )
|
|
{
|
|
//ïðîâåðèì íàéäåííûé áëîê íà âîçìîæíîñòü äåëåíèÿ
|
|
tail = LastKnownGood->Size - reqsize;
|
|
if ( tail >= ( sizeof(MemBlock) + SIZE_ALIGN ) )
|
|
{
|
|
//áóäåì ðàçáèâàòü
|
|
BlockForCheck = (MemBlock *)( ( (Byte *)LastKnownGood ) + tail );
|
|
BlockForCheck->Size = reqsize;
|
|
//âñòàâèì çàíÿòûé áëîê â íà÷àëî ñïèñêà çàíàòûõ áëîêîâ
|
|
if( rootuser != NULL )
|
|
{
|
|
BlockForCheck->Next = rootuser;
|
|
rootuser->Previous = BlockForCheck;
|
|
BlockForCheck->Previous = NULL;
|
|
rootuser = BlockForCheck;
|
|
}
|
|
else
|
|
{
|
|
rootuser = BlockForCheck;
|
|
BlockForCheck->Next = NULL;
|
|
BlockForCheck->Previous = NULL;
|
|
}
|
|
|
|
//èçìåíèì ðàçìåð îñòàâøåéñÿ ÷àñòè
|
|
LastKnownGood->Size = tail - sizeof(MemBlock);
|
|
address = ( (Byte *)BlockForCheck ) + sizeof(MemBlock);
|
|
|
|
// îòïóñòèì ìüþòåêñ
|
|
rtlInterlockedExchange( &mmMutex, FALSE );
|
|
|
|
return address;
|
|
}
|
|
else
|
|
{
|
|
//ïåðåìåñòè áëîê èç î÷åðåäè ñâîáîäíûõ â íà÷àëî î÷åðåäè çàíÿòûõ
|
|
//ñíà÷àëà âûêèíåì åãî èç î÷åðåäè ñâîáîäíûõ
|
|
if ( LastKnownGood->Previous != NULL )
|
|
{
|
|
LastKnownGood->Previous->Next = LastKnownGood->Next;
|
|
}
|
|
else
|
|
{
|
|
//áëîê ñòîèò â íà÷àëå î÷åðåäè
|
|
rootfree = LastKnownGood->Next;
|
|
}
|
|
if( LastKnownGood->Next != NULL )
|
|
{
|
|
LastKnownGood->Next->Previous = LastKnownGood->Previous;
|
|
}
|
|
//òåïåðü âñòàâèì åãî â î÷åðåäü çàíÿòûõ
|
|
if( rootuser != NULL )
|
|
{
|
|
LastKnownGood->Next = rootuser;
|
|
rootuser->Previous = LastKnownGood;
|
|
LastKnownGood->Previous = NULL;
|
|
rootuser = LastKnownGood;
|
|
}
|
|
else
|
|
{
|
|
rootuser = LastKnownGood;
|
|
LastKnownGood->Next = NULL;
|
|
LastKnownGood->Previous = NULL;
|
|
}
|
|
//
|
|
address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock);
|
|
|
|
// îòïóñòèì ìüþòåêñ
|
|
rtlInterlockedExchange( &mmMutex, FALSE );
|
|
|
|
return address;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// íàäî ïîëó÷èòü åù¸ áëîê ïàìÿòè
|
|
LastKnownGood = (MemBlock *)kos_malloc(
|
|
(reqsize > 0x10000 - sizeof(MemBlock)) ? (reqsize + sizeof(MemBlock)) : 0x10000);
|
|
if (LastKnownGood != NULL)
|
|
{
|
|
LastKnownGood->Size = reqsize;
|
|
// òåïåðü âñòàâèì åãî â î÷åðåäü çàíÿòûõ
|
|
LastKnownGood->Next = rootuser;
|
|
LastKnownGood->Previous = NULL;
|
|
if (rootuser != NULL)
|
|
rootuser->Previous = LastKnownGood;
|
|
rootuser = LastKnownGood;
|
|
// à òàêæå äîáàâèì õâîñò ñâåæåâûäåëåííîãî áîëüøîãî áëîêà â ñïèñîê ñâîáîäíûõ
|
|
if (reqsize < 0x10000 - sizeof(MemBlock))
|
|
{
|
|
MemBlock* free = (MemBlock*)((Byte*)LastKnownGood + sizeof(MemBlock) + reqsize);
|
|
free->Next = rootfree;
|
|
free->Previous = NULL;
|
|
if (rootfree != NULL)
|
|
rootfree->Previous = free;
|
|
rootfree = free;
|
|
}
|
|
address = (Byte*)LastKnownGood + sizeof(MemBlock);
|
|
// îòïóñòèì ìüþòåêñ
|
|
rtlInterlockedExchange(&mmMutex, FALSE);
|
|
|
|
return address;
|
|
}
|
|
}
|
|
|
|
// îòïóñòèì ìüþòåêñ
|
|
rtlInterlockedExchange( &mmMutex, FALSE );
|
|
|
|
//
|
|
rtlDebugOutString( "allocmem failed." );
|
|
kos_ExitApp();
|
|
//
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
Dword freemem( void *vaddress )
|
|
{
|
|
Dword result;
|
|
|
|
Byte *checknext, *address = (Byte *)vaddress;
|
|
|
|
// æä¸ì îñâîáîæäåíèÿ ìüþòåêñà
|
|
while ( rtlInterlockedExchange( &mmMutex, TRUE ) )
|
|
{
|
|
//
|
|
kos_Pause( 1 );
|
|
}
|
|
|
|
MemBlock *released = (MemBlock *)( address - sizeof(MemBlock) );
|
|
|
|
result = released->Size;
|
|
|
|
//óáèðàåì áëîê èç ñïèñêà çàíÿòûõ
|
|
if ( released->Previous != NULL )
|
|
{
|
|
released->Previous->Next = released->Next;
|
|
}
|
|
else
|
|
{
|
|
rootuser = released->Next;
|
|
}
|
|
if ( released->Next != NULL )
|
|
{
|
|
released->Next->Previous = released->Previous;
|
|
}
|
|
//çàêèíåì òåïåðü ýòîò áëîê â ñïèñîê ñâîáîäíûõ
|
|
released->Next = rootfree;
|
|
released->Previous = NULL;
|
|
rootfree = released;
|
|
if ( released->Next != NULL )
|
|
{
|
|
released->Next->Previous = released;
|
|
}
|
|
|
|
//òåïåðü ïîèùåì ñìåæíûå ñâîáîäíûå áëîêè
|
|
checknext = (Byte *)(rootfree) + ( rootfree->Size + sizeof(MemBlock) );
|
|
//
|
|
for ( released = rootfree->Next; released != NULL; released = released->Next )
|
|
{
|
|
if ( checknext == (Byte *)released )
|
|
{
|
|
//ñîáèðàåì áëîêè âìåñòå
|
|
//ñíà÷àëà âûêèíåì èç î÷åðåäè ñâîáîäíûõ
|
|
released->Previous->Next = released->Next;
|
|
if( released->Next != NULL )
|
|
{
|
|
released->Next->Previous = released->Previous;
|
|
}
|
|
//òåïåðü óâåëè÷èì ðàçìåð êîðíåâîãî áëîêà
|
|
rootfree->Size += released->Size + sizeof(MemBlock);
|
|
break;
|
|
}
|
|
}
|
|
//åñëè íàäî, ïîèùåì áëîêè ïåðåä òåêùèì.
|
|
checknext = (Byte *)(rootfree);
|
|
//
|
|
if ( released == NULL )
|
|
{
|
|
for ( released = rootfree->Next; released != NULL; released = released->Next )
|
|
{
|
|
if ( checknext == (Byte *)released + ( released->Size + sizeof(MemBlock) ) )
|
|
{
|
|
//ñîáèðàåì áëîêè âìåñòå
|
|
//óâåëè÷èì ðàçìåð áëîêà
|
|
released->Size += rootfree->Size + sizeof(MemBlock);
|
|
//òåïåðü âûêèíåì èç î÷åðåäè ñâîáîäíûõ
|
|
released->Previous->Next = released->Next;
|
|
if ( released->Next != NULL )
|
|
{
|
|
released->Next->Previous = released->Previous;
|
|
}
|
|
//è çàêèíåì åãî â íà÷àëî î÷åðåäè âìåñòî ïðèñîåäèí¸ííîãî áëîêà èç êîðíÿ ñïèñêà
|
|
if ( rootfree->Next != NULL )
|
|
{
|
|
rootfree->Next->Previous = released;
|
|
}
|
|
released->Next = rootfree->Next;
|
|
released->Previous = NULL;
|
|
rootfree = released;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// îòïóñòèì ìüþòåêñ
|
|
rtlInterlockedExchange( &mmMutex, FALSE );
|
|
|
|
return result;
|
|
}
|
|
|