Files
TempleOS-Rijn/LT/OSMain/Memory.CPZ
T
2018-09-08 21:45:20 +02:00

1130 lines
22 KiB
Plaintext

asm {
//The heap cache technique I first saw at Ticketmaster.
//I don't know who owns it.
STRUC 0
MB_NEXT: DU8 ?;
MB_LAST: DU8 ?;
MB_SIGNATURE: DU4 ?;
MB_SIZE: DU4 ?;
MB_STRUCT_SIZE:
ENDS
STRUC 0 //AVAILABLE TO MALLOC MEM
UUM_NEXT: DU8 ?;
UUM_SIZE: DU8 ?;
UUM_STRUCT_SIZE:
ENDS
STRUC 0
UM_HEAP_CTRL:
UM_TSS: DU8 ?;
UM_SIZE: DU8 ?;
UM_START: DU4 ?;
ENDS
ALIGN 8,OC_NOP
USE32
INIT_MEM::
//Set-up Page Tables
MOV EDI,0x100000
XOR EAX,EAX
MOV ECX,0x1000*(NUM_PML1+NUM_PML2+NUM_PML3+NUM_PML4)/4
REP_STOSD
//PML1
MOV EAX,0x103
XOR EDX,EDX
MOV EDI,0x100000
MOV ECX,0x200*NUM_PML1
@@1: MOV U4 [EDI],EAX
ADD EDI,4
MOV U4 [EDI],EDX
ADD EDI,4
ADD EAX,0x1000
ADC EDX,0
LOOP @@1
//video ram=write through
MOV EAX,8
XOR EDX,EDX
MOV EDI,0x100000+0xA0*8
MOV ECX,0xC0-0xA0
@@2: OR U4 [EDI],EAX
ADD EDI,4
OR U4 [EDI],EDX
ADD EDI,4
LOOP @@2
//PML2
MOV EAX,0x100000+3
XOR EDX,EDX
MOV EDI,0x100000+0x1000*NUM_PML1
MOV ECX,NUM_PML1
@@3: MOV U4 [EDI],EAX
ADD EDI,4
MOV U4 [EDI],EDX
ADD EDI,4
ADD EAX,0x1000
ADC EDX,0
LOOP @@3
MOV EAX,0x83+NUM_PML1*0x200000
XOR EDX,EDX
MOV EDI,0x100000+0x1000*NUM_PML1+8*NUM_PML1
MOV ECX,NUM_PML2*0x200-NUM_PML1
@@4: MOV U4 [EDI],EAX
ADD EDI,4
MOV U4 [EDI],EDX
ADD EDI,4
ADD EAX,0x200000
ADC EDX,0
LOOP @@4
//APIC=No Cache
MOV EAX,0x10
XOR EDX,EDX
MOV EDI,0x100000+0x1000*NUM_PML1+8*0x780
MOV ECX,0x800-0x780
@@5: OR U4 [EDI],EAX
ADD EDI,4
OR U4 [EDI],EDX
ADD EDI,4
LOOP @@5
//PML3
MOV EAX,3+0x100000+NUM_PML1*0x1000
XOR EDX,EDX
MOV EDI,0x100000+0x1000*(NUM_PML1+NUM_PML2)
MOV ECX,NUM_PML2
@@6: MOV U4 [EDI],EAX
ADD EDI,4
MOV U4 [EDI],EDX
ADD EDI,4
ADD EAX,0x1000
ADC EDX,0
LOOP @@6
//PML4
MOV EAX,3+0x100000+(NUM_PML1+NUM_PML2)*0x1000
XOR EDX,EDX
MOV EDI,0x100000+0x1000*(NUM_PML1+NUM_PML2+NUM_PML3)
MOV ECX,1
@@7: MOV U4 [EDI],EAX
ADD EDI,4
MOV U4 [EDI],EDX
ADD EDI,4
ADD EAX,0x1000
ADC EDX,0
LOOP @@7
MOV EDI,U4 SYS_FREE_PAGE_HASH
MOV ECX,FREE_PAGE_HASH_SIZE*2
XOR EAX,EAX
REP_STOSD
MOV EDI,U4 SYS_FREE_PAGE_HASH2
MOV ECX,64*2
REP_STOSD
MOV U4 [SYS_MEM_FREE_LIST],0
MOV U4 [SYS_MEM_FREE_LIST+4],0
MOV U4 [SYS_MEM_FREE_2MEG_LIST],0
MOV U4 [SYS_MEM_FREE_2MEG_LIST+4],0
MOV EBX,U4 [SYS_HEAP_BASE]
MOV EAX,U4 [SYS_MEMBLKS] //TODO: check if subtracts 0x100000
DEC EAX
CMP EAX,MAX_I4+1-0x100000
JB @@8
MOV EAX,MAX_I4+1-0x100000 //TODO: max 2 Gig
@@8: MOV U4 [SYS_HEAP_LIMIT],EAX
INC EAX
SUB EAX,EBX
SHR EAX,PAGE_BITS
MOV EDI,U4 [SYS_MEM_FREE_LIST]
MOV U4 MB_NEXT[EBX],EDI
MOV U4 MB_NEXT+4[EBX],0
MOV U4 [SYS_MEM_FREE_LIST],EBX
MOV U4 [SYS_MEM_FREE_LIST+4],0
MOV U4 MB_SIGNATURE[EBX],MBS_UNUSED_SIGNATURE
MOV U4 MB_SIZE[EBX],EAX
RET
}
void SysOutOfMem()
{
Debugger;
}
asm {CP_BAD_MEM_FREE::}
void SysBadMemFree(U8 *ptr)
{
Debugger("Bad Mem Free:",ptr);
}
U8 *MemPointAtPageTableEntry(void *a)
{
if (a<NUM_PML1*0x1000*0x200)
return 0x100000+(a>>12)*8;
else
return 0x100000+NUM_PML1*0x1000+
(a>>(12+9))*8;
}
void *AllocNonTskMemBlks(U8 *pages512)
//This will allocate a 512 byte pages from
//the code heap memory range and not
//link them to any task. (Linking to a task
//means it will be freed when the task
//dies.)
//It might give you more than you asked for
//so a pointer to a page count is passed.
{
MemBlk *result=NULL,*m;
U8 i,num=*pages512,old_flags=GetFlags;
Cli;
if (num<FREE_PAGE_HASH_SIZE) {
if (result=free_page_hash[num]) {
free_page_hash[num]=result->next;
SetFlags(old_flags);
return result;
}
} else {
num-=2;
i=Bsr(num)+1;
num=0;
Bts(&num,i);
num+=2;
*pages512=num;
if (result=free_page_hash2[i]) {
free_page_hash2[i]=result->next;
SetFlags(old_flags);
return result;
}
}
m=&mem_free_list;
do {
if (!(result=m->next)) {
SysOutOfMem;
SetFlags(old_flags);
return NULL;
}
if (result->pages<num)
m=result;
else {
if (result->pages==num) {
m->next=result->next;
SetFlags(old_flags);
return result;
} else {
result->pages-=num;
result+=result->pages<<PAGE_BITS;
result->pages=num;
SetFlags(old_flags);
return result;
}
}
} while (TRUE);
}
void FreeNonTskMemBlks(MemBlk *m,U8 pages512)
{
U8 i,old_flags;
if (m) {
old_flags=GetFlags;
Cli;
m->signature=MBS_UNUSED_SIGNATURE;
m->pages=pages512;
if (pages512<FREE_PAGE_HASH_SIZE) {
m->next=free_page_hash[pages512];
free_page_hash[pages512]=m;
} else {
pages512-=2;
i=Bsr(pages512);
m->next=free_page_hash2[i];
free_page_hash2[i]=m;
}
SetFlags(old_flags);
}
}
void *Alloc2MegMemBlks(U8 *pages2Meg)
//This will allocate 2Meg pages from
//the code heap memory range and not
//link it to any task. (Linking to a task
//means they will be freed when the task
//dies.)
//It might give you more than you asked for
//so a pointer to a page count is passed.
{
U8 *pte;
MemBlk *result=NULL,*m,*m1;
U8 i,j,num=*pages2Meg,old_flags=GetFlags;
Cli;
num<<=12;
m=&mem_free_2Meg_list;
do {
if (!(result=m->next))
break;
if (result->pages<num)
m=result;
else {
if (result->pages==num) {
m->next=result->next;
goto done;
} else {
result->pages-=num;
result+=result->pages<<PAGE_BITS;
result->pages=num;
goto done;
}
}
} while (TRUE);
m=&mem_free_list;
do {
if (!(result=m->next)) {
SysOutOfMem;
SetFlags(old_flags);
return NULL;
}
if (result->pages<num)
m=result;
else {
if (result->pages==num) {
if (result&0x1FFFFF)
m=result;
else {
m->next=result->next;
goto done;
}
} else {
if (i=(result&0x1FFFFF)>>PAGE_BITS) {
j=(1<<12)-i;
if (result->pages<num+j)
m=result;
else if (result->pages==num+j) {
result->pages-=num;
result+=result->pages<<PAGE_BITS;
result->pages=num;
goto done;
} else {
m1=result;
result+=j<<PAGE_BITS;
result->pages=num;
m=result+num<<PAGE_BITS;
m->pages=m1->pages-num-j;
m1->pages=j;
m->next=m1->next;
m1->next=m;
m->signature=MBS_UNUSED_SIGNATURE;
goto done;
}
} else {
m=m->next=result+num<<PAGE_BITS;
m->next=result->next;
m->pages=result->pages-num;
m->signature=MBS_UNUSED_SIGNATURE;
result->pages=num;
goto done;
}
}
}
} while (TRUE);
done:
m=result;
num=*pages2Meg;
for (i=0;i<num;i++) {
pte=MemPointAtPageTableEntry(m);
*pte=*pte & ~0x18;
m+=0x200000;
}
SetFlags(old_flags);
return result;
}
void *AllocUncachedMemBlks(U8 *pages2Meg)
//This will allocate 2Meg pages from
//the code heap memory range and not
//link them to any task. (Linking to a task
//means it will be freed when the task
//dies.) It will be marked uncached.
//It might give you more than you asked for
//so a pointer to a page count is passed.
{
MemBlk *result,*m;
U8 i,num=*pages2Meg,*pte;
result=Alloc2MegMemBlks(pages2Meg);
m=result;
num=*pages2Meg;
for (i=0;i<num;i++) {
pte=MemPointAtPageTableEntry(m);
*pte=(*pte & ~0x18)|0x10;
m+=0x200000;
}
return result;
}
void *AllocWriteThroughMemBlks(U8 *pages2Meg)
//This will allocate 2Meg pages from
//the code heap memory range and not
//link them to any task. (Linking to a task
//means they will be freed when the task
//dies.) It will be marked write-through.
//It might give you more than you asked for
//so a pointer to a page count is passed.
{
MemBlk *result,*m;
U8 i,num=*pages2Meg,*pte;
result=Alloc2MegMemBlks(pages2Meg);
m=result;
num=*pages2Meg;
for (i=0;i<num;i++) {
pte=MemPointAtPageTableEntry(m);
*pte=(*pte & ~0x18)|8;
m+=0x200000;
}
return result;
}
void Free2MegMemBlks(MemBlk *m,U8 pages2Meg)
{
U8 old_flags,*pte;
MemBlk *m1;
U8 i;
if (m) {
m1=m;
for (i=0;i<pages2Meg;i++) {
pte=MemPointAtPageTableEntry(m1);
*pte=*pte & ~0x18;
m1+=0x200000;
}
old_flags=GetFlags;
Cli;
m->signature=MBS_UNUSED_SIGNATURE;
m->pages=pages2Meg<<12;
m->next=mem_free_2Meg_list;
mem_free_2Meg_list=m;
SetFlags(old_flags);
}
}
asm {ALLOCATE_MEM_BLKS::}
MemBlk *AllocMemBlks(U8 *num_,TssStruct *tss)
{
MemBlk *result;
U8 old_flags=GetFlags;
Cli;
result=AllocNonTskMemBlks(num_);
InsQue(result,tss->last_mem_blk);
result->signature=MBS_USED_SIGNATURE;
SetFlags(old_flags);
return result;
}
asm {FREE_MEM_BLKS::}
void FreeMemBlks(MemBlk *m)
{
U8 old_flags;
if (m) {
old_flags=GetFlags;
Cli;
if (m->signature!=MBS_USED_SIGNATURE) {
SysBadMemFree(m);
goto done;
}
RemQue(m);
FreeNonTskMemBlks(m,m->pages);
done:
SetFlags(old_flags);
}
}
void FreeMemBlkList(TssStruct *tss)
{
U8 old_flags=GetFlags;
MemBlk *m,*m1;
Cli;
m=tss->next_mem_blk;
while (m!=&tss->next_mem_blk) {
m1=m->next;
FreeMemBlks(m);
m=m1;
}
SetFlags(old_flags);
}
asm {
////**************************PROCEDURE*************************
// OUT: RAX=BASE ADDRESS
//
ALIGN 8,OC_NOP
CP_MALLOC::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
XOR EBX,EBX
MOV RDX,U8 SF_PARAM2[RBP]
OR RDX,RDX
JNZ @@30
MOV RDX,FS:TSS_ABSOLUTE_ADDRESS[RBX]
@@30: MOV RAX,GS:CPU_ABSOLUTE_ADDRESS[RBX]
MOV RAX,U8 CPU_HEAP[RAX]
OR RAX,RAX
JZ @@32
MOV RDX,RAX
JMP U4 MALLOC_HC_JOIN
@@32: MOV RAX,U8 SF_PARAM1[RBP]
PUSHFD
CLI
@@31: LOCK
BTS U4 [SYS_SEMAS+SYS_SEMA_MEM_BUSY*SEMA_STRUCT_SIZE],0
JC @@31
ADD RAX,UM_START+8-1 //round-up to U8
AND RAX,~7
CMP RAX,UUM_STRUCT_SIZE
JAE @@4
MOV RAX,UUM_STRUCT_SIZE
@@4: CMP RAX,HEAP_HASH_SIZE
JAE @@10
MOV RSI,U8 TSS_HEAP_HASH[RAX+RDX]
OR RSI,RSI
JZ @@13
MOV RCX,U8 UUM_NEXT[RSI]
MOV U8 TSS_HEAP_HASH[RAX+RDX],RCX
JMP U4 @@5
@@10: ADD RAX,MB_STRUCT_SIZE+PAGE_SIZE-1
SHR RAX,PAGE_BITS
PUSH RDX
PUSH RAX
MOV RAX,RSP
PUSH RDX
PUSH RAX
CALL ALLOCATE_MEM_BLKS
MOV RSI,RAX
ADD RSP,16
POP RAX
POP RDX
SHL RAX,PAGE_BITS
SUB RAX,MB_STRUCT_SIZE
ADD RSI,MB_STRUCT_SIZE
JMP U4 @@5
@@13: MOV RSI,RDX
ADD RSI,TSS_MALLOC_FREE_LIST
@@1: LEA RBX,U8 UUM_NEXT[RSI]
MOV RSI,U8 [RBX]
OR RSI,RSI
JNZ @@2
PUSH RAX //-****
ADD RAX,16*PAGE_SIZE-1
SHR RAX,PAGE_BITS
PUSH RDX
PUSH RAX
MOV RAX,RSP
PUSH RDX
PUSH RAX
CALL ALLOCATE_MEM_BLKS
MOV RSI,RAX
ADD RSP,16
POP RAX
POP RDX
LEA RSI,U8 MB_STRUCT_SIZE[RSI]
SHL RAX,PAGE_BITS
SUB RAX,MB_STRUCT_SIZE
MOV RDI,U8 TSS_MALLOC_FREE_LIST[RDX]
MOV U8 UUM_NEXT[RSI],RDI
MOV U8 UUM_SIZE[RSI],RAX
MOV U8 TSS_MALLOC_FREE_LIST[RDX],RSI
MOV RBX,RDX
ADD RBX,TSS_MALLOC_FREE_LIST
POP RAX //+****
JMP @@3
@@2: CMP U8 UUM_SIZE[RSI],RAX
JB @@1
JNE @@3
@@8: MOV RDI,U8 UUM_NEXT[RSI]
MOV U8 UUM_NEXT[RBX],RDI
JMP @@5
@@3: SUB U8 UUM_SIZE[RSI],RAX //UPDATE FREE ENTRY
CMP U8 UUM_SIZE[RSI],UUM_STRUCT_SIZE
JAE @@7
ADD U8 UUM_SIZE[RSI],RAX
XOR EAX,EAX
MOV RAX,U8 UUM_SIZE[RSI]
JMP @@8
@@7: MOV RDI,U8 UUM_SIZE[RSI]
ADD RSI,RDI //SET ESI TO @ALLOCATED PAGES
@@5: MOV U8 UM_SIZE[RSI],RAX
MOV U8 UM_TSS[RSI],RDX
ADD RSI,UM_START
@@100: LOCK
BTR U4 [SYS_SEMAS+SYS_SEMA_MEM_BUSY*SEMA_STRUCT_SIZE],0
POPFD
MOV RAX,RSI
BT U4 [SYS_SEMAS+SYS_SEMA_HEAPLOG*SEMA_STRUCT_SIZE],0
JNC @@200
PUSH_C_REGS
PUSH RDX
PUSH RAX
MOV RAX,U8 [SYS_EXTERN_TABLE]
MOV RAX,U8 EXT_HEAPLOG_MALLOC*8[RAX]
OR RAX,RAX
JZ @@202
CALL RAX
@@202: ADD RSP,16
POP_C_REGS
@@200:
/*************
This will initialize memory to some value
for debugging.
PUSH RAX
PUSH RCX
MOV RCX,U8 UM_SIZE-UM_START[RAX]
SUB RCX,UM_START
MOV RDI,RAX
MOV RAX,0x12345678
REP_STOSB
POP RCX
POP RAX
**********/
POP RDI
POP RSI
POP RBP
RET
////**************************PROCEDURE*************************
ALIGN 8,OC_NOP
CP_FREE::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
BT U4 [SYS_SEMAS+SYS_SEMA_HEAPLOG*SEMA_STRUCT_SIZE],0
JNC @@1
PUSH_C_REGS
PUSH U8 SF_PARAM1[RBP]
MOV RAX,U8 [SYS_EXTERN_TABLE]
MOV RAX,U8 EXT_HEAPLOG_FREE*8[RAX]
OR RAX,RAX
JZ @@2
CALL RAX
@@2: ADD RSP,8
POP_C_REGS
@@1: MOV RSI,U8 SF_PARAM1[RBP]
OR RSI,RSI
JZ U4 @@100
XOR EBX,EBX
MOV RDX,U8 SF_PARAM2[RBP]
OR RDX,RDX
JNZ @@30
MOV RDX,U8 FS:TSS_ABSOLUTE_ADDRESS[RBX]
@@30: MOV RAX,GS:CPU_ABSOLUTE_ADDRESS[RBX]
MOV RAX,U8 CPU_HEAP[RAX]
OR RAX,RAX
JZ @@32
MOV RDX,RAX
JMP U4 FREE_HC_JOIN
@@32: PUSHFD
CLI
@@31: LOCK
BTS U4 [SYS_SEMAS+SYS_SEMA_MEM_BUSY*SEMA_STRUCT_SIZE],0
JC @@31
SUB RSI,UM_START
CMP RDX,U8 UM_TSS[RSI]
JE @@10
PUSH_C_REGS
PUSH RSI
CALL CP_BAD_MEM_FREE
ADD RSP,8
POP_C_REGS
JMP @@101
@@10: XOR EAX,EAX
MOV RAX,U8 UM_SIZE[RSI]
CMP RAX,HEAP_HASH_SIZE
JAE @@5
MOV U8 UUM_SIZE[RSI],RAX
MOV RBX,U8 TSS_HEAP_HASH[RAX+RDX]
MOV U8 UUM_NEXT[RSI],RBX
MOV U8 TSS_HEAP_HASH[RAX+RDX],RSI
JMP @@101
@@5: SUB RSI,MB_STRUCT_SIZE
PUSH RSI
CALL FREE_MEM_BLKS
ADD RSP,8
@@101: LOCK
BTR U4 [SYS_SEMAS+SYS_SEMA_MEM_BUSY*SEMA_STRUCT_SIZE],0
POPFD
@@100: POP RDI
POP RSI
POP RBP
RET
////**************************PROCEDURE*************************
ALIGN 8,OC_NOP
CP_MSIZE::
PUSH RBP
MOV RBP,RSP
MOV RBX,U8 SF_PARAM1[RBP]
XOR EAX,EAX
OR RBX,RBX
JZ @@100
MOV RAX,U8 UM_SIZE-UM_START[RBX]
SUB RAX,UM_START
@@100: POP RBP
RET
////**************************PROCEDURE*************************
ALIGN 8,OC_NOP
CP_MTSS::
PUSH RBP
MOV RBP,RSP
MOV RBX,U8 SF_PARAM1[RBP]
XOR EAX,EAX
OR RBX,RBX
JZ @@100
MOV RAX,U8 UM_TSS-UM_START[RBX]
@@100: POP RBP
RET
}
LTextern CP_MALLOC void *MAlloc(U8 size,TssStruct *tss=NULL);
LTextern CP_FREE void Free(void *add,TssStruct *tss=NULL);
LTextern CP_MSIZE U8 MSize(void *src); //size of heap object
LTextern CP_MTSS TssStruct *MTss(void *src); //tss of heap object
void *MAllocZ(U8 size,TssStruct *tss=NULL)
{
void *result=MAlloc(size,tss);
MemSet(result,0,size);
return result;
}
void *AMAlloc(U8 size)
{
return MAlloc(size,adam_tss);
}
void AFree(void *add)
{
Free(add,adam_tss);
}
void *MAllocIdentical(void *src,TssStruct *tss=NULL)
{
U8 size=MSize(src);
void *result=MAlloc(size,tss);
MemCpy(result,src,size);
}
void *AMAllocIdentical(void *src)
{
return MAllocIdentical(src,adam_tss);
}
I1 *NewStr(I1 *buf,TssStruct *tss=NULL)
{
U8 size=StrLen(buf)+1;
I1 *result=MAlloc(size,tss);
MemCpy(result,buf,size);
}
I1 *ANewStr(I1 *buf)
{
return NewStr(buf,adam_tss);
}
void *AMAllocZ(U8 size)
{
return MAllocZ(size,adam_tss);
}
void DelLinkedList(void **list)
{
void **d;
while (list) {
d=*list;
Free(list);
list=d;
}
}
////**************************PROCEDURE*************************
asm {ALLOCATE_HC_MEM_BLKS::}
void *AllocHCMemBlks(U8 *pages512,HeapCtrl *hc)
{
MemBlk *result=NULL,*m;
U8 i,num=*pages512,old_flags=GetFlags;
Cli;
if (num<FREE_PAGE_HASH_SIZE) {
if (result=hc->free_page_hash[num]) {
hc->free_page_hash[num]=result->next;
result->signature=MBS_USED_SIGNATURE;
SetFlags(old_flags);
return result;
}
} else {
num-=2;
i=Bsr(num)+1;
num=0;
Bts(&num,i);
num+=2;
*pages512=num;
if (result=hc->free_page_hash2[i]) {
hc->free_page_hash2[i]=result->next;
result->signature=MBS_USED_SIGNATURE;
SetFlags(old_flags);
return result;
}
}
m=&hc->mem_free_list;
do {
if (!(result=m->next)) {
SysOutOfMem;
SetFlags(old_flags);
return NULL;
}
if (result->pages<num)
m=result;
else {
if (result->pages==num) {
m->next=result->next;
result->signature=MBS_USED_SIGNATURE;
SetFlags(old_flags);
return result;
} else {
result->pages-=num;
result+=result->pages<<PAGE_BITS;
result->pages=num;
result->signature=MBS_USED_SIGNATURE;
SetFlags(old_flags);
return result;
}
}
} while (TRUE);
}
asm {FREE_HC_MEM_BLKS::}
void FreeHCMemBlks(MemBlk *m,HeapCtrl *hc)
{
U8 i,old_flags,pages512;
if (m) {
old_flags=GetFlags;
pages512=m->pages;
Cli;
if (m->signature!=MBS_USED_SIGNATURE) {
SysBadMemFree(m);
goto done;
}
m->signature=MBS_UNUSED_SIGNATURE;
m->pages=pages512;
if (pages512<FREE_PAGE_HASH_SIZE) {
m->next=hc->free_page_hash[pages512];
hc->free_page_hash[pages512]=m;
} else {
pages512-=2;
i=Bsr(pages512);
m->next=hc->free_page_hash2[i];
hc->free_page_hash2[i]=m;
}
done:
SetFlags(old_flags);
}
}
void InitHeapCtrl(HeapCtrl *hc,U8 pages512)
{
MemBlk *m;
MemSet(hc,0,sizeof(HeapCtrl));
hc->size=pages512;
m=(hc+sizeof(HeapCtrl)+PAGE_SIZE-1)&~(PAGE_SIZE-1);
hc->mem_free_list=m;
m->next=NULL;
m->pages=(hc+pages512<<PAGE_BITS-m)>>PAGE_BITS;
m->signature=MBS_UNUSED_SIGNATURE;
}
asm {
STRUC 0
HC_SIZE: DU8 ?;
HC_FLAGS: DU8 ?;
HC_MALLOC_FREE_LIST: DU8 ?;
HC_MEM_FREE_LIST: DU8 ?;
HC_HEAP_HASH: DU1 HEAP_HASH_SIZE DUP(?);
HC_FREE_PAGE_HASH: DU8 FREE_PAGE_HASH_SIZE DUP(?);
HC_FREE_PAGE_HASH2: DU8 64 DUP(?);
HC_STRUCT_SIZE:
ENDS
////**************************PROCEDURE*************************
// OUT: RAX=BASE ADDRESS
//
ALIGN 8,OC_NOP
CP_MALLOC_HC::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
MOV RDX,U8 SF_PARAM2[RBP]
MALLOC_HC_JOIN::
MOV RAX,U8 SF_PARAM1[RBP]
PUSHFD
CLI
@@31: LOCK
BTS U4 HC_FLAGS[RDX],HCf_LOCKED
JC @@31
ADD RAX,UM_START+8-1 //round-up to U8
AND RAX,~7
CMP RAX,UUM_STRUCT_SIZE
JAE @@4
MOV RAX,UUM_STRUCT_SIZE
@@4: CMP RAX,HEAP_HASH_SIZE
JAE @@10
MOV RSI,U8 HC_HEAP_HASH[RAX+RDX]
OR RSI,RSI
JZ @@13
MOV RCX,U8 UUM_NEXT[RSI]
MOV U8 HC_HEAP_HASH[RAX+RDX],RCX
JMP U4 @@5
@@10: ADD RAX,MB_STRUCT_SIZE+PAGE_SIZE-1
SHR RAX,PAGE_BITS
PUSH RDX
PUSH RAX
MOV RAX,RSP
PUSH RDX
PUSH RAX
CALL ALLOCATE_HC_MEM_BLKS
MOV RSI,RAX
ADD RSP,16
POP RAX
POP RDX
SHL RAX,PAGE_BITS
SUB RAX,MB_STRUCT_SIZE
ADD RSI,MB_STRUCT_SIZE
JMP U4 @@5
@@13: MOV RSI,RDX
ADD RSI,HC_MALLOC_FREE_LIST
@@1: LEA RBX,U8 UUM_NEXT[RSI]
MOV RSI,U8 [RBX]
OR RSI,RSI
JNZ @@2
PUSH RAX //-****
ADD RAX,16*PAGE_SIZE-1
SHR RAX,PAGE_BITS
PUSH RDX
PUSH RAX
MOV RAX,RSP
PUSH RDX
PUSH RAX
CALL ALLOCATE_HC_MEM_BLKS
MOV RSI,RAX
ADD RSP,16
POP RAX
POP RDX
LEA RSI,U8 MB_STRUCT_SIZE[RSI]
SHL RAX,PAGE_BITS
SUB RAX,MB_STRUCT_SIZE
MOV RDI,U8 HC_MALLOC_FREE_LIST[RDX]
MOV U8 UUM_NEXT[RSI],RDI
MOV U8 UUM_SIZE[RSI],RAX
MOV U8 HC_MALLOC_FREE_LIST[RDX],RSI
MOV RBX,RDX
ADD RBX,HC_MALLOC_FREE_LIST
POP RAX //+****
JMP @@3
@@2: CMP U8 UUM_SIZE[RSI],RAX
JB @@1
JNE @@3
@@8: MOV RDI,U8 UUM_NEXT[RSI]
MOV U8 UUM_NEXT[RBX],RDI
JMP @@5
@@3: SUB U8 UUM_SIZE[RSI],RAX //UPDATE FREE ENTRY
CMP U8 UUM_SIZE[RSI],UUM_STRUCT_SIZE
JAE @@7
ADD U8 UUM_SIZE[RSI],RAX
XOR EAX,EAX
MOV RAX,U8 UUM_SIZE[RSI]
JMP @@8
@@7: MOV RDI,U8 UUM_SIZE[RSI]
ADD RSI,RDI //SET ESI TO @ALLOCATED PAGES
@@5: MOV U8 UM_SIZE[RSI],RAX
MOV U8 UM_HEAP_CTRL[RSI],RDX
ADD RSI,UM_START
@@100: LOCK
BTR U4 HC_FLAGS[RDX],HCf_LOCKED
POPFD
MOV RAX,RSI
BT U4 [SYS_SEMAS+SYS_SEMA_HEAPLOG*SEMA_STRUCT_SIZE],0
JNC @@200
PUSH_C_REGS
PUSH RDX
PUSH RAX
MOV RAX,U8 [SYS_EXTERN_TABLE]
MOV RAX,U8 EXT_HEAPLOG_MALLOC*8[RAX]
OR RAX,RAX
JZ @@202
CALL RAX
@@202: ADD RSP,16
POP_C_REGS
@@200:
/*************
This will initialize memory to some value
for debugging.
PUSH RAX
PUSH RCX
MOV RCX,U8 UM_SIZE-UM_START[RAX]
SUB RCX,UM_START
MOV RDI,RAX
MOV RAX,0x12345678
REP_STOSB
POP RCX
POP RAX
**********/
POP RDI
POP RSI
POP RBP
RET
////**************************PROCEDURE*************************
ALIGN 8,OC_NOP
CP_FREE_HC::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
BT U4 [SYS_SEMAS+SYS_SEMA_HEAPLOG*SEMA_STRUCT_SIZE],0
JNC @@1
PUSH_C_REGS
PUSH U8 SF_PARAM1[RBP]
MOV RAX,U8 [SYS_EXTERN_TABLE]
MOV RAX,U8 EXT_HEAPLOG_FREE*8[RAX]
OR RAX,RAX
JZ @@2
CALL RAX
@@2: ADD RSP,8
POP_C_REGS
@@1: MOV RSI,U8 SF_PARAM1[RBP]
OR RSI,RSI
JZ U4 FREE_HC_DONE
MOV RDX,U8 SF_PARAM2[RBP]
FREE_HC_JOIN::
PUSHFD
CLI
@@31: LOCK
BTS U4 HC_FLAGS[RDX],HCf_LOCKED
JC @@31
SUB RSI,UM_START
CMP RDX,U8 UM_HEAP_CTRL[RSI]
JE @@10
PUSH_C_REGS
PUSH RSI
CALL CP_BAD_MEM_FREE
ADD RSP,8
POP_C_REGS
JMP @@101
@@10: XOR EAX,EAX
MOV RAX,U8 UM_SIZE[RSI]
CMP RAX,HEAP_HASH_SIZE
JAE @@5
MOV U8 UUM_SIZE[RSI],RAX
MOV RBX,U8 HC_HEAP_HASH[RAX+RDX]
MOV U8 UUM_NEXT[RSI],RBX
MOV U8 HC_HEAP_HASH[RAX+RDX],RSI
JMP @@101
@@5: SUB RSI,MB_STRUCT_SIZE
PUSH RDX
PUSH RSI
CALL FREE_HC_MEM_BLKS
ADD RSP,8
POP RDX
@@101: LOCK
BTR U4 HC_FLAGS[RDX],HCf_LOCKED
POPFD
FREE_HC_DONE:
POP RDI
POP RSI
POP RBP
RET
////**************************PROCEDURE*************************
ALIGN 8,OC_NOP
CP_MEM_HEAP_CTRL::
PUSH RBP
MOV RBP,RSP
MOV RBX,U8 SF_PARAM1[RBP]
XOR EAX,EAX
OR RBX,RBX
JZ @@100
MOV RAX,U8 UM_HEAP_CTRL-UM_START[RBX]
@@100: POP RBP
RET
}
LTextern CP_MALLOC_HC void *MAllocHC(U8 size,HeapCtrl *hc);
LTextern CP_FREE_HC void FreeHC(void *add,HeapCtrl *hc);
LTextern CP_MSIZE U8 MSizeHC(void *src); //size of heap object
LTextern CP_MEM_HEAP_CTRL HeapCtrl *MHeapCtrl(void *src); //HC of heap object
void *MAllocHCZ(U8 size,HeapCtrl *hc)
{
void *result=MAllocHC(size,hc);
MemSet(result,0,size);
return result;
}
void *MAllocIdenticalHC(void *src,HeapCtrl *hc)
{
U8 size=MSize(src);
void *result=MAllocHC(size,hc);
MemCpy(result,src,size);
}
I1 *NewStrHC(I1 *buf,HeapCtrl *hc)
{
U8 size=StrLen(buf)+1;
I1 *result=MAllocHC(size,hc);
MemCpy(result,buf,size);
}