use function 68

git-svn-id: svn://kolibrios.org@8179 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
IgorA 2020-11-12 16:00:31 +00:00
parent fa5c356928
commit 212fed2d24
5 changed files with 88 additions and 1004 deletions

View File

@ -8,271 +8,88 @@
namespace Kolibri // All kolibri functions, types and data are nested in the (Kolibri) namespace.
{
struct _FileDataStruct;
typedef _FileDataStruct *TFileData;
TFileData FileOpen(const char *name, unsigned int buffer_length = 1024);
int FileClose(TFileData file_data);
bool FileEof(TFileData file_data);
unsigned int FileGetPosition(TFileData file_data);
void FileSetPosition(TFileData file_data, unsigned int pos);
void FileReset(TFileData file_data);
unsigned int FileGetLength(TFileData file_data);
int FileTestRead(TFileData file_data);
int FileRead(TFileData file_data, void *mem, int size);
}
#ifdef __KOLIBRI__
namespace Kolibri
{
// Define the file data structure.
struct _FileDataStruct
{
unsigned int length;
unsigned int position;
unsigned int *buffer;
unsigned int access_param[5];
enum {PosName = (unsigned int)(((_FileDataStruct*)0)->access_param + 5)};
struct FileDateTime{
unsigned long int time;
unsigned long int date;
};
// Inline functions.
inline bool FileEof(TFileData file_data)
struct FileInfoBlock
{
return file_data && file_data->position >= file_data->length;
}
inline unsigned int FileGetPosition(TFileData file_data)
unsigned long int Function;
unsigned long int Position;
unsigned long int Flags;
unsigned long int Count;
char *Buffer;
char *FileName1;
char *FileName2;
};
struct FileInfoA
{
return file_data ? file_data->position : 0;
}
inline void FileReset(TFileData file_data)
{
if (!file_data) return;
file_data->length = -1;
file_data->position = 0;
if (file_data->buffer) file_data->buffer[1] = 0;
}
unsigned long int Attributes;
unsigned long int Flags;
FileDateTime DateCreate;
FileDateTime DateAccess;
FileDateTime DateModify;
unsigned long int FileSizeLow;
unsigned long int FileSizeHigh;
char FileName[520];
};
// Functions.
int _FileAccess(void *file_access_param);
int _FileAccess(FileInfoBlock *file_access);
TFileData FileOpen(const char *name, unsigned int buffer_length)
FileInfoBlock* FileOpen(const char *name)
{
if (!name || !name[0]) return 0;
unsigned int name_len = StrLen(name) + 1;
unsigned int data_len = (_FileDataStruct::PosName + name_len + 3) & ~3;
buffer_length = (buffer_length / KOLIBRI_FILE_BLOCK_SIZE) * KOLIBRI_FILE_BLOCK_SIZE;
if (buffer_length) data_len += buffer_length + 2*sizeof(unsigned int);
TFileData file = (TFileData)Alloc(_FileDataStruct::PosName + data_len);
if (!file) return 0;
file->length = -1;
file->position = 0;
if (buffer_length)
{
file->buffer = (unsigned int*)((char*)file + data_len) - 2;
file->buffer[0] = buffer_length;
file->buffer[1] = 0;
if (!name || !name[0]){
//DebugPutString("name is 0");
return 0;
}
MemCopy(file->access_param + 5, name, name_len);
unsigned int attr[40/4];
file->access_param[0] = 5;
file->access_param[1] = 0;
file->access_param[2] = 0;
file->access_param[3] = 0;
file->access_param[4] = (int)attr;
_FileAccess(file->access_param);
file->length = attr[32/4];
FileInfoBlock* file = (FileInfoBlock*)Alloc(sizeof(FileInfoBlock)+sizeof(FileInfoA));
if (!file){
//DebugPutString("mem_Alloc -> 0");
return 0;
}
file->Function = 5; //SSF_GET_INFO
file->Position = 0;
file->Flags = 0;
file->Count = 0;
file->Buffer = (char*)file+sizeof(FileInfoBlock);
file->FileName1 = (char*)name;
file->FileName2 = (char*)name;
file->FileName1 = (char*)((long)file->FileName1 << 8);
file->FileName2 = (char*)((long)file->FileName2 >> 24);
_FileAccess(file);
return file;
}
int FileClose(TFileData file_data)
int FileClose(FileInfoBlock* file_data)
{
if (!file_data) return -1;
Free(file_data);
return 0;
}
void FileSetPosition(TFileData file_data, unsigned int pos)
unsigned long int FileRead(FileInfoBlock* file_data, void *mem, int size)
{
if (!file_data) return;
if (file_data->buffer && file_data->buffer[1])
{
if (pos >= file_data->position && pos < file_data->position + file_data->buffer[1])
{
file_data->buffer[1] -= pos - file_data->position;
}
else file_data->buffer[1] = 0;
}
file_data->position = pos;
}
file_data->Function = 0; //SSF_READ_FILE
file_data->Position = 0;
file_data->Flags = 0;
file_data->Count = size;
file_data->Buffer = (char*)mem;
int _FileReadBuffer(TFileData file_data, void *mem, int size, void *temp_mem = 0)
{
unsigned int *buffer;
if (!file_data || !mem || size <= 0) return -1;
if (file_data->buffer) buffer = file_data->buffer;
else if (temp_mem)
{
buffer = (unsigned int*)((char*)temp_mem + KOLIBRI_FILE_BLOCK_SIZE);
}
if(!_FileAccess(file_data)) return file_data->Function;
else return 0;
if (!buffer[1]) return 0;
if (file_data->position >= file_data->length)
{
buffer[1] = 0;
return 0;
}
unsigned int buf_size = file_data->length - file_data->position;
if (buf_size > buffer[1]) buf_size = buffer[1];
if ((unsigned int)size >= buf_size) size = buf_size;
MemCopy(mem, (char*)buffer - buffer[1], size);
file_data->position += size;
if ((unsigned int)size >= buf_size) buffer[1] = 0;
else buffer[1] -= size;
return size;
}
int _FileReadSystem(TFileData file_data, void *mem, int size)
{
int res;
unsigned int len0, len1;
size /= KOLIBRI_FILE_BLOCK_SIZE;
if (!file_data || !mem || size <= 0) return -1;
file_data->access_param[0] = 0;
file_data->access_param[1] = (file_data->position / KOLIBRI_FILE_BLOCK_SIZE) * KOLIBRI_FILE_BLOCK_SIZE;
file_data->access_param[2] = 0;
file_data->access_param[3] = size * KOLIBRI_FILE_BLOCK_SIZE;
file_data->access_param[4] = (unsigned int)mem;
res = _FileAccess(file_data->access_param);
if (res != 0 && res != 6) return (res & 255) - 1024;
if (file_data->length <= file_data->position) return 0;
len0 = file_data->length - file_data->position;
len1 = size * KOLIBRI_FILE_BLOCK_SIZE - (file_data->position % KOLIBRI_FILE_BLOCK_SIZE);
return (len0 <= len1) ? len0 : len1;
}
int _FileBufferSystem(TFileData file_data, void *&temp_mem)
{
int res;
unsigned int *buffer;
if (!file_data) return -1;
if (file_data->buffer) buffer = file_data->buffer;
else
{
if (!temp_mem)
{
temp_mem = Alloc(KOLIBRI_FILE_BLOCK_SIZE + 2*sizeof(unsigned int));
if (!temp_mem) return -10;
}
buffer = (unsigned int*)((char*)temp_mem + KOLIBRI_FILE_BLOCK_SIZE);
buffer[0] = KOLIBRI_FILE_BLOCK_SIZE;
}
buffer[1] = buffer[0];
res = _FileReadSystem(file_data, (char*)buffer - buffer[1], buffer[1]);
if (res < 0) buffer[1] = 0;
else buffer[1] -= file_data->position % KOLIBRI_FILE_BLOCK_SIZE;
return res;
}
int FileTestRead(TFileData file_data)
{
int res;
void *temp_mem = 0;
if (!file_data) return -1;
if (file_data->buffer && file_data->buffer[1]) return 0;
res = _FileBufferSystem(file_data, temp_mem);
if (temp_mem) Free(temp_mem);
return (res < 0) ? res : 0;
}
int FileRead(TFileData file_data, void *mem, int size)
{
int tlen, res, read_len;
void *temp_mem = 0;
res = _FileReadBuffer(file_data, mem, size);
if (res < 0 || res >= size) return res;
read_len = res;
mem = (char*)mem + res;
size -= res;
tlen = file_data->position % KOLIBRI_FILE_BLOCK_SIZE;
if (tlen)
{
res = _FileBufferSystem(file_data, temp_mem);
if (res < 0)
{
if (temp_mem) Free(temp_mem);
return read_len ? read_len : res;
}
res = _FileReadBuffer(file_data, mem, size);
read_len += res;
if (res >= size || file_data->length <= file_data->position ||
file_data->length - file_data->position <= res)
{
if (temp_mem) Free(temp_mem);
return read_len;
}
mem = (char*)mem + res;
size -= res;
}
if (size >= (file_data->buffer ? file_data->buffer[0] : KOLIBRI_FILE_BLOCK_SIZE))
{
res = _FileReadSystem(file_data, mem, size);
if (res < 0)
{
if (temp_mem) Free(temp_mem);
return read_len ? read_len : res;
}
file_data->position += res;
read_len += res;
if (res < (size / KOLIBRI_FILE_BLOCK_SIZE) * KOLIBRI_FILE_BLOCK_SIZE)
{
if (temp_mem) Free(temp_mem);
return read_len;
}
mem = (char*)mem + res;
size -= res;
}
if (size)
{
res = _FileBufferSystem(file_data, temp_mem);
if (res < 0)
{
if (temp_mem) Free(temp_mem);
return read_len ? read_len : res;
}
read_len += _FileReadBuffer(file_data, mem, size, temp_mem);
}
if (temp_mem) Free(temp_mem);
return read_len;
}
// Inline functions.
inline unsigned int FileGetLength(TFileData file_data)
inline unsigned long int FileGetLength(FileInfoBlock* file_data)
{
if (!file_data) return -1;
if (file_data->length == -1) FileTestRead(file_data);
return file_data->length;
return (unsigned long int)*(long*)((char*)file_data+sizeof(FileInfoBlock)+32);
}
}
#else // def __KOLIBRI__
namespace Kolibri
{
struct _FileDataStruct
{
unsigned int data;
};
}
#endif // else: def __KOLIBRI__
#endif // ndef __KOLIBRI_FILE_H_INCLUDED_

View File

@ -41,12 +41,6 @@ KOLIBRI_THREAD_DATA_LEN = 16;
;const int
KOLIBRI_MUTEX_MAX_TIME_WAIT = 20;
;const int
KOLIBRI_FILE_BLOCK_SIZE = 512;
;const int
KOLIBRI_FILE_MEMORY_OS_NEED = 4096;
;/***
macro segment name
@ -1093,7 +1087,7 @@ end if
jmp .create_thread_fill_stack
endp
proc @Kolibri@_FileAccess$qpv uses ebx
proc @Kolibri@_FileAccess$qp21Kolibri@FileInfoBlock uses ebx
mov eax,SF_FILE
mov ebx,[esp+8]
int 0x40

View File

@ -8,83 +8,25 @@
namespace Kolibri // All kolibri functions, types and data are nested in the (Kolibri) namespace.
{
void *Alloc(unsigned int size);
void *ReAlloc(void *mem, unsigned int size);
void Free(void *mem);
}
#ifdef __KOLIBRI__
namespace Kolibri
long _HeapInit()
{
// Global variables
MemoryHeap::TFreeSpace _KolibriFreeSpace;
MemoryHeap::TMemBlock _KolibriMemBlock;
TMutex _MemHeapMutex = KOLIBRI_MUTEX_INIT;
// Functions
void *_HeapInit(void *begin, void *use_end, void *end)
{
MemoryHeap::InitFreeSpace(_KolibriFreeSpace);
_KolibriMemBlock = MemoryHeap::CreateBlock(begin, end, _KolibriFreeSpace);
unsigned int use_beg = (unsigned int)MemoryHeap::BlockBegin(_KolibriMemBlock) +
MemoryHeap::BlockAddSize - MemoryHeap::BlockEndSize;
unsigned int use_size = (unsigned int)use_end;
if (use_size <= use_beg) return 0;
else use_size -= use_beg;
return MemoryHeap::Alloc(_KolibriFreeSpace, use_size);
return MemoryHeap::mem_Init();
}
bool _SetUseMemory(unsigned int use_mem);
int _RecalculateUseMemory(unsigned int use_mem);
void *Alloc(unsigned int size)
{
if (!size) return 0;
Lock(&_MemHeapMutex);
void *res = MemoryHeap::Alloc(_KolibriFreeSpace, size);
if (!res)
{
unsigned use_mem = (unsigned int)MemoryHeap::BlockEndFor(_KolibriMemBlock, size);
if (_SetUseMemory(_RecalculateUseMemory(use_mem)))
{
res = MemoryHeap::Alloc(_KolibriFreeSpace, size);
}
}
UnLock(&_MemHeapMutex);
return res;
return MemoryHeap::mem_Alloc(size);
}
void *ReAlloc(void *mem, unsigned int size)
{
Lock(&_MemHeapMutex);
void *res = MemoryHeap::ReAlloc(_KolibriFreeSpace, mem, size);
if (!res && size)
{
unsigned use_mem = (unsigned int)MemoryHeap::BlockEndFor(_KolibriMemBlock, size);
if (_SetUseMemory(_RecalculateUseMemory(use_mem)))
{
res = MemoryHeap::ReAlloc(_KolibriFreeSpace, mem, size);
}
}
UnLock(&_MemHeapMutex);
return res;
return MemoryHeap::mem_ReAlloc(size, mem);
}
void Free(void *mem)
{
Lock(&_MemHeapMutex);
MemoryHeap::Free(_KolibriFreeSpace, mem);
UnLock(&_MemHeapMutex);
MemoryHeap::mem_Free(mem);
}
void _FreeAndThreadFinish(void *mem, int *exit_proc_now);
}
#endif // def __KOLIBRI__
#endif // ndef __KOLIBRI_HEAP_H_INCLUDED_

View File

@ -1,6 +1,6 @@
;/***
KolibriHeapInit = @@Kolibri@_HeapInit$qpvt1t1
KolibriHeapInit = @@Kolibri@_HeapInit$qv
KolibriHeapAlloc = @@Kolibri@Alloc$qui
@ -8,90 +8,34 @@ KolibriHeapReAlloc = @@Kolibri@ReAlloc$qpvui
KolibriHeapFree = @@Kolibri@Free$qpv
KolibriHeapFreeAndThreadFinish = @Kolibri@_FreeAndThreadFinish$qpvpi
proc @Kolibri@_SetUseMemory$qui
push ebx
mov eax,64
mov ebx,1
mov ecx,[esp+8]
proc @MemoryHeap@mem_Init$qv uses ebx
mov eax,SF_SYS_MISC
mov ebx,SSF_HEAP_INIT
int 0x40
pop ebx
test eax,eax
jnz .set_use_memory_nomem
push ecx
push dword [@Kolibri@_KolibriMemBlock]
call @@MemoryHeap@ResizeBlock$q20MemoryHeap@TMemBlockpv
add esp,8
mov al,1
ret
.set_use_memory_nomem:
xor al,al
ret
endp
proc @Kolibri@_RecalculateUseMemory$qui
mov eax,dword [esp+4]
mov ecx,(U_END + 3) and not 3
cmp eax,ecx
jna .recalculate_use_memory_min
push ebx
sub eax,ecx
mov ebx,6
mul ebx
dec ebx
div ebx
add eax,((U_END + 3) and not 3) + 3
and eax,not 3
pop ebx
ret
.recalculate_use_memory_min:
mov eax,ecx
proc @MemoryHeap@mem_Alloc$qul uses ebx
mov eax,SF_SYS_MISC
mov ebx,SSF_MEM_ALLOC
int 0x40
ret
endp
proc @Kolibri@_FreeAndThreadFinish$qpvpi
mov ebx,1
proc @MemoryHeap@mem_ReAlloc$qulpv uses ebx
mov eax,SF_SYS_MISC
mov ebx,SSF_MEM_REALLOC
mov ecx,[esp+8]
jmp .heap_free_tf_wait
.heap_free_tf_wait_loop:
mov eax,5
int 0x40
shl ebx,1
cmp ebx,KOLIBRI_MUTEX_MAX_TIME_WAIT
jna .heap_free_tf_wait
mov ebx,KOLIBRI_MUTEX_MAX_TIME_WAIT
.heap_free_tf_wait:
cmp dword [ecx],0
jnz @Kolibri@ExitProcess$qv
lock bts dword [@Kolibri@_MemHeapMutex],0
jc .heap_free_tf_wait_loop
push dword [esp+4]
push @Kolibri@_KolibriFreeSpace
call @@MemoryHeap@Free$qr21MemoryHeap@TFreeSpacepv
add esp,8
mov byte [@Kolibri@_MemHeapMutex],0x40
or eax,-1
mov edx,[esp+12]
int 0x40
ret
endp
macro call func
{
if func eq @MemoryHeap@_FirstNotZeroBit$qui
bsf eax,[esp]
else if func eq @MemoryHeap@_CopyMemItemArray$quiuiui
xchg edi,[esp]
xchg esi,[esp+4]
mov ecx,[esp+8]
cld
sub ecx,esi
shr ecx,2
rep movs dword [edi],[esi]
xchg edi,[esp]
xchg esi,[esp+4]
else
call func
end if
}
proc @MemoryHeap@mem_Free$qpv uses ebx
mov eax,SF_SYS_MISC
mov ebx,SSF_MEM_FREE
int 0x40
ret
endp
;/**/

View File

@ -1,626 +1,13 @@
#ifndef __MEMORY_HEAP_RBTREE_H_INCLUDED_
#define __MEMORY_HEAP_RBTREE_H_INCLUDED_
#ifndef __MEMORY_HEAP_H_INCLUDED_
#define __MEMORY_HEAP_H_INCLUDED_
namespace MemoryHeap
{
typedef unsigned int TMemItem;
enum {NumTreeSmall = 8 * sizeof(TMemItem)};
// Memory heap interface.
struct TFreeSpace
{
TMemItem Small[NumTreeSmall], Min, SmallMask;
};
struct TMemBlock
{
TMemItem *Begin;
};
bool BlockValid(const TMemBlock &block); // Is the given memory block valid?
void *BlockBegin(const TMemBlock &block); // Return the beginning address of the block.
void *BlockEnd(const TMemBlock &block); // Return the ending address of the block.
TFreeSpace &BlockFreeSpace(const TMemBlock &block); // Return the free space of the block.
void InitFreeSpace(TFreeSpace &fs); // Initialize the free space.
TMemBlock NullBlock(); // Return null invalid block.
TMemBlock CreateBlock(void *begin, void *end, TFreeSpace &fs);
// Create a memory block with the given begin and end and add free space of it to (fs),
//_ give (BlockAddSize) bytes of the block for it's data.
//_ (Program can alloc (end - begin - BlockAddSize) bytes after it,
//_ that must be not less than (MemMinSize) ).
TMemBlock CreateBlock(void *begin, void *end);
// Create a memory block with the given begin and end and new free space for it,
//_ give (BlockAddSizeFS) bytes of the block for it's data.
//_ (Program can alloc (end - begin - BlockAddSizeFS) bytes after it,
//_ that must be not less than (MemMinSize) ).
void ResizeBlock(TMemBlock block, void *new_end); // Resize the memory block to the given new end.
void RemoveBlock(TMemBlock block); // Remove the given memory block.
void *BlockEndFor(TMemBlock block, unsigned int size);
// Return the new end of the block needed for (ResizeBlock) to alloc the given size of memory.
unsigned int BlockSize(TMemBlock block); // Return the size of the given block.
unsigned int MemSize(void *mem); // Return the size of the allocced memory.
void *Alloc(TFreeSpace &fs, unsigned int size);
// Alloc a memory in the given free space, give (MemAddSize) bytes for it's data.
void *ReAlloc(TFreeSpace &fs, unsigned int size, void *mem);
// ReAlloc the given memory, it must lie in the block with the given free space.
void Free(TFreeSpace &fs, void *mem);
// Free the given memory, it must lie in the block with the given free space.
// Macro definitions.
#define MEMORY_HEAP_ALIGN_DOWN(s) (MemoryHeap::TMemItem(s) & ~(MemoryHeap::MemAlign - 1))
#define MEMORY_HEAP_ALIGN_UP(s) ((MemoryHeap::TMemItem(s) + (MemoryHeap::MemAlign - 1)) & ~(MemoryHeap::MemAlign - 1))
#define MEMORY_HEAP_ITEM(s,k) ( ((MemoryHeap::TMemItem*)(s))[(k)] )
#define MEMORY_HEAP_NEXT(s) (MEMORY_HEAP_ITEM((s),-1))
#define MEMORY_HEAP_PREV(s) (MEMORY_HEAP_ITEM((s),-2))
#define MEMORY_HEAP_FREE(s) (MEMORY_HEAP_ITEM((s),-1) & 1)
// Constants.
enum {MemAlign = sizeof(TMemItem)};
enum {MemAddSize = MEMORY_HEAP_ALIGN_UP(2 * sizeof(TMemItem))};
enum {BlockEndSize = MemAddSize};
enum {BlockAddSize = MEMORY_HEAP_ALIGN_UP(4 * sizeof(TMemItem)) + BlockEndSize};
enum {BlockAddSizeFS = BlockAddSize + BlockEndSize + MEMORY_HEAP_ALIGN_UP(sizeof(TFreeSpace))};
enum {MemMinSize = MEMORY_HEAP_ALIGN_UP(2 * sizeof(TMemItem))};
// Inline functions.
inline bool BlockValid(const TMemBlock &block) {return block.Begin != 0;}
inline void *BlockBegin(const TMemBlock &block) {return (void*)block.Begin;}
inline void *BlockEnd(const TMemBlock &block) {return block.Begin ? (void*)block.Begin[1] : 0;}
inline TFreeSpace &BlockFreeSpace(const TMemBlock &block) {return *(TFreeSpace*)block.Begin[0];}
inline TMemBlock NullBlock() {TMemBlock block; block.Begin = 0; return block;}
inline void *BlockEndFor(TMemBlock block, unsigned int size)
{
TMemItem last = (TMemItem)block.Begin[1];
TMemItem prevlast = MEMORY_HEAP_PREV(last);
return (void*)( (MEMORY_HEAP_FREE(prevlast) ? prevlast : last) + MemAddSize +
((size <= MemMinSize) ? MemMinSize : MEMORY_HEAP_ALIGN_UP(size)) );
long mem_Init();
void *mem_Alloc(unsigned long size);
void *mem_ReAlloc(unsigned long size, void *mem);
bool mem_Free(void *mem);
}
inline unsigned int BlockSize(TMemBlock block)
{
if (!block.Begin) return 0;
return (unsigned int)(block.Begin[1] - (TMemItem)block.Begin);
}
inline unsigned int MemSize(void *mem)
{
if (!mem) return 0;
TMemItem c = (TMemItem)mem;
return MEMORY_HEAP_NEXT(c) - c - MemAddSize;
}
// Free space item functions.
TMemItem _FirstNotZeroBit(TMemItem i)
{
TMemItem r = 0;
while ((i >>= 1) != 0) r++;
return r;
}
void _RBTreeRotate(TMemItem parent, TMemItem item, int side)
{
TMemItem temp = MEMORY_HEAP_ITEM(parent,0);
MEMORY_HEAP_ITEM(item,0) = temp;
if (temp)
{
if (MEMORY_HEAP_ITEM(temp,2) == parent)
{
MEMORY_HEAP_ITEM(temp,2) = item;
}
else MEMORY_HEAP_ITEM(temp,3) = item;
}
temp = MEMORY_HEAP_ITEM(item,side^1);
if (temp) MEMORY_HEAP_ITEM(temp,0) = parent;
MEMORY_HEAP_ITEM(parent,side) = temp;
MEMORY_HEAP_ITEM(parent,0) = item;
MEMORY_HEAP_ITEM(item,side^1) = parent;
temp = MEMORY_HEAP_ITEM(parent,1);
MEMORY_HEAP_ITEM(parent,1) = MEMORY_HEAP_ITEM(item,1);
MEMORY_HEAP_ITEM(item,1) = temp;
}
void InitFreeSpace(TFreeSpace &fs)
{
TMemItem i;
for (i = 0; i <= NumTreeSmall; i++) fs.Small[i] = 0;
fs.Min = 0; fs.SmallMask = 0;
}
void _FreeAdd(TFreeSpace &fs, TMemItem item)
{
TMemItem size = MEMORY_HEAP_NEXT(item) - item;
if (size < MemAddSize + MemMinSize + MemAlign * NumTreeSmall)
{
TMemItem s = (size - (MemAddSize + MemMinSize)) / MemAlign;
TMemItem &addto = fs.Small[s];
MEMORY_HEAP_ITEM(item,1) = (TMemItem)(&addto);
MEMORY_HEAP_ITEM(item,0) = (TMemItem)addto;
if (addto) MEMORY_HEAP_ITEM(addto,1) = item;
addto = item;
fs.SmallMask |= TMemItem(1) << s;
return;
}
TMemItem addto = fs.Min, parent, temp;
MEMORY_HEAP_ITEM(item,2) = 0;
MEMORY_HEAP_ITEM(item,3) = 0;
if (!addto)
{
MEMORY_HEAP_ITEM(item,0) = 0;
MEMORY_HEAP_ITEM(item,1) = 1;
fs.Min = item;
return;
}
MEMORY_HEAP_ITEM(item,1) = 0;
TMemItem side = 2;
if (MEMORY_HEAP_NEXT(addto) - addto >= size) fs.Min = item;
else
{
for (;;)
{
parent = MEMORY_HEAP_ITEM(addto,0);
if (!parent) break;
if (MEMORY_HEAP_NEXT(parent) - parent < size) addto = parent;
else break;
}
for (;;)
{
if (MEMORY_HEAP_NEXT(addto) - addto < size)
{
temp = MEMORY_HEAP_ITEM(addto,3);
if (!temp) {side = 3; break;}
addto = temp;
}
else
{
temp = MEMORY_HEAP_ITEM(addto,2);
if (!temp) break;
addto = temp;
}
}
}
MEMORY_HEAP_ITEM(item,0) = addto;
MEMORY_HEAP_ITEM(addto,side) = item;
for (;;)
{
if (MEMORY_HEAP_ITEM(addto,1) != 0) return;
parent = MEMORY_HEAP_ITEM(addto,0);
temp = MEMORY_HEAP_ITEM(parent,2);
if (temp == addto)
{
temp = MEMORY_HEAP_ITEM(parent,3);
side = 2;
}
else side = 3;
if (!temp || MEMORY_HEAP_ITEM(temp,1) != 0) break;
MEMORY_HEAP_ITEM(addto,1) = 1;
MEMORY_HEAP_ITEM(temp,1) = 1;
item = parent;
addto = MEMORY_HEAP_ITEM(item,0);
if (!addto) return;
MEMORY_HEAP_ITEM(item,1) = 0;
}
if (MEMORY_HEAP_ITEM(addto,side) != item)
{
temp = MEMORY_HEAP_ITEM(item,side);
if (temp) MEMORY_HEAP_ITEM(temp,0) = addto;
MEMORY_HEAP_ITEM(addto,side^1) = temp;
MEMORY_HEAP_ITEM(addto,0) = item;
MEMORY_HEAP_ITEM(item,side) = addto;
MEMORY_HEAP_ITEM(item,0) = parent;
MEMORY_HEAP_ITEM(parent,side) = item;
}
else item = addto;
_RBTreeRotate(parent, item, side);
}
void _FreeDel(TFreeSpace &fs, TMemItem item)
{
TMemItem size = MEMORY_HEAP_NEXT(item) - item;
if (size < MemAddSize + MemMinSize + MemAlign * NumTreeSmall)
{
TMemItem prev = MEMORY_HEAP_ITEM(item,1);
TMemItem next = MEMORY_HEAP_ITEM(item,0);
MEMORY_HEAP_ITEM(prev,0) = next;
if (next) MEMORY_HEAP_ITEM(next,1) = prev;
else
{
TMemItem s = (size - (MemAddSize + MemMinSize)) / MemAlign;
if (!fs.Small[s]) fs.SmallMask &= ~(TMemItem(1) << s);
}
return;
}
TMemItem parent, temp, second, add;
TMemItem side = 2;
temp = MEMORY_HEAP_ITEM(item,3);
if (temp)
{
for (;;)
{
second = temp;
temp = MEMORY_HEAP_ITEM(temp,2);
if (!temp) break;
}
if (fs.Min == item) fs.Min = second;
add = MEMORY_HEAP_ITEM(second,3);
parent = MEMORY_HEAP_ITEM(second,0);
if (parent == item) {parent = second; side = 3;}
else
{
temp = MEMORY_HEAP_ITEM(item,3);
MEMORY_HEAP_ITEM(second,3) = temp;
MEMORY_HEAP_ITEM(temp,0) = second;
}
temp = MEMORY_HEAP_ITEM(item,2);
MEMORY_HEAP_ITEM(second,2) = temp;
if (temp) MEMORY_HEAP_ITEM(temp,0) = second;
temp = MEMORY_HEAP_ITEM(item,0);
MEMORY_HEAP_ITEM(second,0) = temp;
if (temp)
{
if (MEMORY_HEAP_ITEM(temp,2) == item)
{
MEMORY_HEAP_ITEM(temp,2) = second;
}
else MEMORY_HEAP_ITEM(temp,3) = second;
}
MEMORY_HEAP_ITEM(parent,side) = add;
if (add) MEMORY_HEAP_ITEM(add,0) = parent;
bool color = MEMORY_HEAP_ITEM(second,1);
MEMORY_HEAP_ITEM(second,1) = MEMORY_HEAP_ITEM(item,1);
if (!color) return;
}
else
{
if (fs.Min == item) fs.Min = MEMORY_HEAP_ITEM(item,0);
add = MEMORY_HEAP_ITEM(item,2);
parent = MEMORY_HEAP_ITEM(item,0);
if (add) MEMORY_HEAP_ITEM(add,0) = parent;
if (parent)
{
if (MEMORY_HEAP_ITEM(parent,2) == item)
{
MEMORY_HEAP_ITEM(parent,2) = add;
}
else
{
MEMORY_HEAP_ITEM(parent,3) = add;
side = 3;
}
}
else
{
if (add) MEMORY_HEAP_ITEM(add,1) = 1;
return;
}
if (!MEMORY_HEAP_ITEM(item,1)) return;
}
if (add && !MEMORY_HEAP_ITEM(add,1))
{
MEMORY_HEAP_ITEM(add,1) = 1;
return;
}
for (;;)
{
second = MEMORY_HEAP_ITEM(parent,side^1);
if (!MEMORY_HEAP_ITEM(second,1))
{
_RBTreeRotate(parent, second, side^1);
second = MEMORY_HEAP_ITEM(parent,side^1);
}
temp = MEMORY_HEAP_ITEM(second,side^1);
if (temp && !MEMORY_HEAP_ITEM(temp,1))
{
MEMORY_HEAP_ITEM(temp,1) = 1;
break;
}
temp = MEMORY_HEAP_ITEM(second,side);
if (temp && !MEMORY_HEAP_ITEM(temp,1))
{
_RBTreeRotate(second, temp, side);
MEMORY_HEAP_ITEM(second,1) = 1;
second = temp;
break;
}
MEMORY_HEAP_ITEM(second,1) = 0;
if (!MEMORY_HEAP_ITEM(parent,1))
{
MEMORY_HEAP_ITEM(parent,1) = 1;
return;
}
second = parent;
parent = MEMORY_HEAP_ITEM(second,0);
if (!parent) return;
if (MEMORY_HEAP_ITEM(parent,2) == second) side = 2;
else side = 3;
}
_RBTreeRotate(parent, second, side^1);
}
TMemItem _FreeFindAfter(TMemItem item, TMemItem size)
{
if (!item) return 0;
TMemItem paritem, s;
if (MEMORY_HEAP_NEXT(item) - item >= size) return item;
for (;;)
{
paritem = MEMORY_HEAP_ITEM(item,0);
if (!paritem) break;
s = MEMORY_HEAP_NEXT(paritem) - paritem;
if (s == size) return paritem;
if (s < size) item = paritem;
else break;
}
MEMORY_HEAP_ITEM(item,3);
for (;;)
{
if (!item) return paritem;
s = MEMORY_HEAP_NEXT(item) - item;
if (s == size) return item;
if (s < size) item = MEMORY_HEAP_ITEM(item,3);
else
{
paritem = item;
item = MEMORY_HEAP_ITEM(item,2);
}
}
}
TMemItem _FreeFind(TFreeSpace &fs, TMemItem size)
{
TMemItem item, nextitem, s;
if (size < MemAddSize + MemMinSize + MemAlign * NumTreeSmall)
{
TMemItem m, t;
s = (size - (MemAddSize + MemMinSize)) / MemAlign;
item = fs.Small[s];
if (item) return item;
if (size < MemAlign * NumTreeSmall)
{
t = size / MemAlign;
m = fs.SmallMask >> t;
if (m) return fs.Small[t + _FirstNotZeroBit(m)];
else if (fs.Min) return fs.Min;
}
else
{
item = _FreeFindAfter(fs.Min, size + 1 + MemAddSize + MemMinSize);
if (item) return item;
}
m = fs.SmallMask >> s;
if (m) return fs.Small[s + _FirstNotZeroBit(m)];
else return fs.Min;
}
item = _FreeFindAfter(fs.Min, ++size);
if (!item) return 0;
s = MEMORY_HEAP_NEXT(item) - item;
if (s == size) return item;
size += MemAddSize + MemMinSize;
if (s >= size) return item;
nextitem = _FreeFindAfter(item, size);
return nextitem ? nextitem : item;
}
// Block functions.
inline void _CreateBlockEnd(TMemBlock &block, TFreeSpace &fs, TMemItem c, TMemItem e)
{
block.Begin[0] = (TMemItem)(&fs);
if (e - c < TMemItem(MemAddSize + MemMinSize))
{
MEMORY_HEAP_NEXT(c) = 0;
block.Begin[1] = c;
}
else
{
MEMORY_HEAP_NEXT(c) = e + 1;
_FreeAdd(fs, c);
MEMORY_HEAP_PREV(e) = c;
MEMORY_HEAP_NEXT(e) = 0;
block.Begin[1] = e;
}
}
TMemBlock CreateBlock(void *begin, void *end, TFreeSpace &fs)
{
TMemBlock block = {0};
TMemItem b = MEMORY_HEAP_ALIGN_UP(begin);
TMemItem e = MEMORY_HEAP_ALIGN_DOWN(end);
if (e <= b || e - b < TMemItem(BlockAddSize - MemAddSize)) return block;
block.Begin = (TMemItem*)b;
b += MEMORY_HEAP_ALIGN_UP(4 * sizeof(TMemItem));
MEMORY_HEAP_PREV(b) = 0;
_CreateBlockEnd(block, fs, b, e);
return block;
}
TMemBlock CreateBlock(void *begin, void *end)
{
TMemBlock block = {0};
TMemItem b = MEMORY_HEAP_ALIGN_UP(begin);
TMemItem e = MEMORY_HEAP_ALIGN_DOWN(end);
if (e <= b || e - b < TMemItem(BlockAddSizeFS - MemAddSize)) return block;
block.Begin = (TMemItem*)b;
b += MEMORY_HEAP_ALIGN_UP(4 * sizeof(TMemItem));
TMemItem c = b + MemAddSize + MEMORY_HEAP_ALIGN_UP(sizeof(TFreeSpace));
MEMORY_HEAP_PREV(b) = 0;
MEMORY_HEAP_NEXT(b) = c;
MEMORY_HEAP_PREV(c) = b;
InitFreeSpace(*(TFreeSpace*)b);
_CreateBlockEnd(block, *(TFreeSpace*)b, c, e);
return block;
}
void ResizeBlock(TMemBlock block, void *new_end)
{
if (!BlockValid(block)) return;
TMemItem e = MEMORY_HEAP_ALIGN_DOWN(new_end);
TMemItem c = block.Begin[1];
TFreeSpace &fs = *(TFreeSpace*)block.Begin[0];
do
{
if (c == e) return;
else if (c > e)
{
while ((c = MEMORY_HEAP_PREV(c)) > e)
{
if (MEMORY_HEAP_FREE(c)) _FreeDel(fs, c);
}
if (!c) {block.Begin = 0; return;}
if (MEMORY_HEAP_FREE(c))
{
_FreeDel(fs, c);
if (e - c < TMemItem(MemAddSize + MemMinSize)) e = c;
else
{
MEMORY_HEAP_NEXT(c) = e + 1;
_FreeAdd(*(TFreeSpace*)block.Begin[0], c);
break;
}
}
else if (e - c >= TMemItem(MemAddSize + MemMinSize))
{
MEMORY_HEAP_NEXT(c) = e; break;
}
MEMORY_HEAP_NEXT(c) = 0;
block.Begin[1] = c;
if (c == e) return;
}
TMemItem pc = MEMORY_HEAP_PREV(c);
if (pc && MEMORY_HEAP_FREE(pc)) _FreeDel(fs, c = pc);
else if (e - c < TMemItem(MemAddSize + MemMinSize)) return;
MEMORY_HEAP_NEXT(c) = e + 1;
_FreeAdd(fs, c);
} while(false);
MEMORY_HEAP_PREV(e) = c;
MEMORY_HEAP_NEXT(e) = 0;
block.Begin[1] = e;
}
void RemoveBlock(TMemBlock block)
{
if (!BlockValid(block)) return;
TMemItem e = block.Begin[1];
TFreeSpace &fs = *(TFreeSpace*)block.Begin[0];
while ((e = MEMORY_HEAP_PREV(e)) != 0)
{
if (MEMORY_HEAP_FREE(e)) _FreeDel(fs, e);
}
block.Begin = 0;
}
// Free space functions.
void _CopyMemItemArray(TMemItem dest, TMemItem src, TMemItem end)
{
TMemItem k = (end - src) / sizeof(TMemItem);
TMemItem *d = (TMemItem*)dest;
TMemItem *s = (TMemItem*)src;
while (k--) *(d++) = *(s++);
}
void *Alloc(TFreeSpace &fs, unsigned int size)
{
if (!size) return 0;
TMemItem s = MEMORY_HEAP_ALIGN_UP(size) + MemAddSize;
if (s < MemAddSize + MemMinSize) s = MemAddSize + MemMinSize;
TMemItem c = _FreeFind(fs, s);
if (!c) return 0;
_FreeDel(fs, c);
TMemItem nc = --MEMORY_HEAP_NEXT(c);
TMemItem mc = c + s;
if (nc - (MemAddSize + MemMinSize) >= mc)
{
MEMORY_HEAP_NEXT(c) = mc;
MEMORY_HEAP_PREV(mc) = c;
MEMORY_HEAP_NEXT(mc) = nc + 1;
MEMORY_HEAP_PREV(nc) = mc;
_FreeAdd(fs, mc);
}
return (void*)c;
}
void *ReAlloc(TFreeSpace &fs, void *mem, unsigned int size)
{
if (!mem) return Alloc(fs, size);
if (!size) {Free(fs, mem); return 0;}
TMemItem s = MEMORY_HEAP_ALIGN_UP(size) + MemAddSize;
TMemItem c = (TMemItem)mem;
TMemItem mc = MEMORY_HEAP_NEXT(c);
TMemItem nc = MEMORY_HEAP_NEXT(mc);
if (--nc & 1) nc = mc;
if (s < MemAddSize + MemMinSize) s = MemAddSize + MemMinSize;
if (nc - c < s)
{
mem = Alloc(fs, size);
if (mem)
{
_CopyMemItemArray((TMemItem)mem, c, mc - MemAddSize);
Free(fs, (void*)c);
return mem;
}
else
{
TMemItem pc = MEMORY_HEAP_PREV(c);
if (pc && MEMORY_HEAP_FREE(pc) && nc - pc >= s)
{
_FreeDel(fs, pc);
_CopyMemItemArray(pc, c, mc - MemAddSize);
c = pc;
}
else return 0;
}
}
if (mc < nc) _FreeDel(fs, mc);
mc = c + s;
if (nc - (MemAddSize + MemMinSize) >= mc)
{
MEMORY_HEAP_NEXT(c) = mc;
MEMORY_HEAP_PREV(mc) = c;
MEMORY_HEAP_NEXT(mc) = nc + 1;
MEMORY_HEAP_PREV(nc) = mc;
_FreeAdd(fs, mc);
}
else
{
MEMORY_HEAP_NEXT(c) = nc;
MEMORY_HEAP_PREV(nc) = c;
}
return (void*)c;
}
int free_a = 0;
void Free(TFreeSpace &fs, void *mem)
{
TMemItem c = (TMemItem)mem;
if (!c) return;
TMemItem pc = MEMORY_HEAP_PREV(c);
TMemItem mc = MEMORY_HEAP_NEXT(c);
TMemItem nc = MEMORY_HEAP_NEXT(mc);
if (--nc & 1) nc = mc;
else _FreeDel(fs, mc);
if (free_a == 1) return;
if (pc && MEMORY_HEAP_FREE(pc)) _FreeDel(fs, c = pc);
MEMORY_HEAP_NEXT(c) = nc + 1;
MEMORY_HEAP_PREV(nc) = c;
if (free_a == 2) return;
_FreeAdd(fs, c);
}
}
#endif // ndef __MEMORY_HEAP_RBTREE_H_INCLUDED_
#endif // ndef __MEMORY_HEAP_H_INCLUDED_