
#define MBS_USED_SIGNATURE 0x1020304
#define MBS_UNUSED_SIGNATURE 0x4030201
class MemBlk
{
MemBlk *next,*last;
U4 signature;
U4 pages;
};
#define HEAP_DBG FALSE
#if HEAP_DBG
//See $LK,"Redundant Struct","PF:D:/LT/OSMain/OSDefs.ASZ,UUM_SIZE"$
class UnusedAllocatedMem
{
U8 size;
HeapCtrl *hc;
U1 *caller1,*caller2;
UnusedAllocatedMem *next;
};
class UsedAllocatedMem
{
U8 size;
HeapCtrl *hc;
U1 *caller1,*caller2;
UsedAllocatedMem *next,*last;
U0 start;
};
#else
class UnusedAllocatedMem
{
U8 size;
U0 hc;
U0 caller1,caller2;
UnusedAllocatedMem *next;
};
class UsedAllocatedMem
{
U8 size;
HeapCtrl *hc;
U0 caller1,caller2;
U0 next,last;
U0 start;
};
#endif
//MEM RELATED
#define PAGE_SIZE 0x200
#define PAGE_BITS 9
#define DEFAULT_STACK (PAGE_SIZE*256)
#define FREE_PAGE_HASH_SIZE 0x100
#define MAXIO 0x10000
#define HEAP_HASH_SIZE 1024
#define BPf_LOCKED 0
class BlkPool
{
U8 size;
U8 flags;
MemBlk *mem_free_list;
MemBlk *mem_free_2meg_list;
MemBlk *free_page_hash[FREE_PAGE_HASH_SIZE];
MemBlk *free_page_hash2[64];
};
#define HCf_LOCKED 0
#define HCf_NON_TASK_QUEUE 1
class HeapCtrl
{
U8 flags;
BlkPool *bp;
TssStruct *mem_tss;
MemBlk *next_mem_blk,*last_mem_blk;
UnusedAllocatedMem *malloc_free_list;
UsedAllocatedMem *next_um,*last_um;
UnusedAllocatedMem *heap_hash[HEAP_HASH_SIZE/sizeof(void *)];
};
$PJ,"Project: OSMain","/LT/OSMain/OS.SPZ"$
asm {
//The heap cache technique I first saw at Ticketmaster.
//I don't know who owns it.
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*0x700
MOV ECX,0x800-0x700
@@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 U4 [SYS_CODE_BP],SYS_BP_SIZE
MOV U4 [SYS_CODE_BP+4],0
MOV U4 [SYS_DATA_BP],0
MOV U4 [SYS_DATA_BP+4],0
MOV U4 [SYS_BP_SIZE],0
MOV U4 [SYS_BP_SIZE+4],0
MOV U4 [SYS_BP_FLAGS],0
MOV U4 [SYS_BP_FLAGS+4],0
MOV EDI,U4 SYS_BP_FREE_PAGE_HASH
MOV ECX,FREE_PAGE_HASH_SIZE*2
XOR EAX,EAX
REP_STOSD
MOV EDI,U4 SYS_BP_FREE_PAGE_HASH2
MOV ECX,64*2
REP_STOSD
MOV U4 [SYS_BP_MEM_FREE_LIST],0
MOV U4 [SYS_BP_MEM_FREE_LIST+4],0
MOV U4 [SYS_BP_MEM_FREE_2MEG_LIST],0
MOV U4 [SYS_BP_MEM_FREE_2MEG_LIST+4],0
MOV EBX,U4 [SYS_HEAP_BASE]
MOV EAX,U4 [SYS_MEMBLKS]
CMP EAX,CODE_HEAP_LIMIT
JB @@8
MOV EAX,CODE_HEAP_LIMIT
@@8: DEC EAX
MOV U4 [SYS_HEAP_LIMIT],EAX
INC EAX
TEST U1 [SYS_MEM_INIT_FLAG],1
JZ @@100
PUSH EAX
MOV EDI,EBX
MOV ECX,EAX
SUB ECX,EDI
MOV AL,U1 [SYS_MEM_INIT_VAL]
REP_STOSB
POP EAX
@@100: SUB EAX,EBX
SHR EAX,PAGE_BITS
MOV EDI,U4 [SYS_BP_MEM_FREE_LIST]
MOV U4 MB_NEXT[EBX],EDI
MOV U4 MB_NEXT+4[EBX],0
MOV U4 [SYS_BP_MEM_FREE_LIST],EBX
MOV U4 [SYS_BP_MEM_FREE_LIST+4],0
MOV U4 MB_SIGNATURE[EBX],MBS_UNUSED_SIGNATURE
MOV U4 MB_SIZE[EBX],EAX
RET
};
void SysOutOfMem()
{
Debugger("Out Of Mem\r\nCPU:",Gs->num);
}
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 *AllocNonTaskMemBlks(U8 *pages512,BlkPool *bp=NULL)
//This will allocate a 512 byte pages from
//the code heap mem 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 ptr to a page count is passed.
{
MemBlk *result=NULL,*m;
U8 i,num=*pages512,old_flags=GetFlags;
if (!bp) bp=sys_code_bp;
Cli;
while (LBts(&bp->flags,BPf_LOCKED));
if (num<FREE_PAGE_HASH_SIZE) {
if (result=bp->free_page_hash[num]) {
bp->free_page_hash[num]=result->next;
LBtr(&bp->flags,BPf_LOCKED);
SetFlags(old_flags);
return result;
}
} else {
num-=2;
i=Bsr(num)+1;
num=0;
Bts(&num,i);
num+=2;
*pages512=num;
if (result=bp->free_page_hash2[i]) {
bp->free_page_hash2[i]=result->next;
LBtr(&bp->flags,BPf_LOCKED);
SetFlags(old_flags);
return result;
}
}
m=&bp->mem_free_list;
do {
if (!(result=m->next)) {
SysOutOfMem;
LBtr(&bp->flags,BPf_LOCKED);
SetFlags(old_flags);
return NULL;
}
if (result->pages<num)
m=result;
else {
if (result->pages==num) {
m->next=result->next;
LBtr(&bp->flags,BPf_LOCKED);
SetFlags(old_flags);
return result;
} else {
result->pages-=num;
result><(U1 *)+=result->pages<<PAGE_BITS;
result->pages=num;
LBtr(&bp->flags,BPf_LOCKED);
SetFlags(old_flags);
return result;
}
}
} while (TRUE);
}
void FreeNonTaskMemBlks(MemBlk *m,U8 pages512,BlkPool *bp=NULL)
{
U8 i,old_flags;
if (m) {
if (!bp) bp=sys_code_bp;
old_flags=GetFlags;
Cli;
while (LBts(&bp->flags,BPf_LOCKED));
m->signature=MBS_UNUSED_SIGNATURE;
m->pages=pages512;
if (pages512<FREE_PAGE_HASH_SIZE) {
m->next=bp->free_page_hash[pages512];
bp->free_page_hash[pages512]=m;
} else {
pages512-=2;
i=Bsr(pages512);
m->next=bp->free_page_hash2[i];
bp->free_page_hash2[i]=m;
}
LBtr(&bp->flags,BPf_LOCKED);
SetFlags(old_flags);
}
}
void *Alloc2MegMemBlks(U8 *pages2Meg,BlkPool *bp=NULL)
//This will allocate 2Meg pages from
//the code heap mem 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 ptr to a page count is passed.
{
U8 *pte;
MemBlk *result=NULL,*m,*m1;
U8 i,j,num=*pages2Meg,old_flags=GetFlags;
if (!bp) bp=sys_code_bp;
Cli;
while (LBts(&bp->flags,BPf_LOCKED));
num<<=12;
m=&bp->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><(U1 *)+=result->pages<<PAGE_BITS;
result->pages=num;
goto done;
}
}
} while (TRUE);
m=&bp->mem_free_list;
do {
if (!(result=m->next)) {
SysOutOfMem;
LBtr(&bp->flags,BPf_LOCKED);
SetFlags(old_flags);
return NULL;
}
if (result->pages<num)
m=result;
else {
if (result->pages==num) {
if (result><(U1 *)&0x1FFFFF)
m=result;
else {
m->next=result->next;
goto done;
}
} else {
if (i=(result><(U1 *)&0x1FFFFF)>>PAGE_BITS) {
j=1<<12-i;
if (result->pages<num+j)
m=result;
else if (result->pages==num+j) {
result->pages-=num;
result><(U1 *)+=result->pages<<PAGE_BITS;
result->pages=num;
goto done;
} else {
m1=result;
result><(U1 *)+=j<<PAGE_BITS;
result->pages=num;
m=result><(U1 *)+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><(U1 *)+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 &= ~0x18;
m><(U1 *)+=0x200000;
}
LBtr(&bp->flags,BPf_LOCKED);
SetFlags(old_flags);
return result;
}
void *AllocUncachedMemBlks(U8 *pages2Meg,BlkPool *bp=NULL)
//This will allocate 2Meg pages from
//the code heap mem 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 ptr to a page count is passed.
{
MemBlk *result,*m;
U8 i,num=*pages2Meg,*pte;
result=Alloc2MegMemBlks(pages2Meg,bp);
m=result;
num=*pages2Meg;
for (i=0;i<num;i++) {
pte=MemPointAtPageTableEntry(m);
*pte= *pte& ~0x18 |0x10;
m><(U1 *)+=0x200000;
}
return result;
}
void *AllocWriteThroughMemBlks(U8 *pages2Meg,BlkPool *bp=NULL)
//This will allocate 2Meg pages from
//the code heap mem 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 ptr to a page count is passed.
{
MemBlk *result,*m;
U8 i,num=*pages2Meg,*pte;
result=Alloc2MegMemBlks(pages2Meg,bp);
m=result;
num=*pages2Meg;
for (i=0;i<num;i++) {
pte=MemPointAtPageTableEntry(m);
*pte= *pte& ~0x18 |8;
m><(U1 *)+=0x200000;
}
return result;
}
void Free2MegMemBlks(MemBlk *m,U8 pages2Meg,BlkPool *bp=NULL)
{
U8 old_flags,*pte;
MemBlk *m1;
U8 i;
if (m) {
if (!bp) bp=sys_code_bp;
m1=m;
for (i=0;i<pages2Meg;i++) {
pte=MemPointAtPageTableEntry(m1);
*pte=*pte & ~0x18;
m1><(U1 *)+=0x200000;
}
old_flags=GetFlags;
Cli;
while (LBts(&bp->flags,BPf_LOCKED));
m->signature=MBS_UNUSED_SIGNATURE;
m->pages=pages2Meg<<12;
m->next=bp->mem_free_2meg_list;
bp->mem_free_2meg_list=m;
LBtr(&bp->flags,BPf_LOCKED);
SetFlags(old_flags);
}
}
asm {ALLOCATE_MEM_BLKS::};
MemBlk *AllocMemBlks(U8 *num_,HeapCtrl *hc)
{
MemBlk *result;
U8 old_flags=GetFlags;
Cli;
result=AllocNonTaskMemBlks(num_,hc->bp);
if (!Bt(&hc->flags,HCf_NON_TASK_QUEUE))
InsQue(result,hc->last_mem_blk);
result->signature=MBS_USED_SIGNATURE;
SetFlags(old_flags);
return result;
}
asm {FREE_MEM_BLKS::};
void FreeMemBlks(MemBlk *m,HeapCtrl *hc)
{
U8 old_flags;
if (m) {
old_flags=GetFlags;
Cli;
if (m->signature!=MBS_USED_SIGNATURE) {
SysBadMemFree(m);
goto done;
}
if (!Bt(&hc->flags,HCf_NON_TASK_QUEUE))
RemQue(m);
FreeNonTaskMemBlks(m,m->pages,hc->bp);
done:
SetFlags(old_flags);
}
}
void FreeMemBlkList(HeapCtrl *hc)
{
U8 old_flags=GetFlags;
MemBlk *m,*m1;
Cli;
while (LBts(&hc->flags,HCf_LOCKED));
m=hc->next_mem_blk;
while (m!=&hc->next_mem_blk) {
m1=m->next;
FreeMemBlks(m,hc);
m=m1;
}
LBtr(&hc->flags,HCf_LOCKED);
SetFlags(old_flags);
}
asm {
////**************************PROCEDURE*************************
// OUT: RAX=BASE ADDRESS
//
CP_MALLOC_HC::
PUSH EBP
MOV RBP,RSP
PUSH ESI
PUSH EDI
MOV RDX,U8 SF_ARG2[RBP]
MALLOC_HC_JOIN::
MOV RAX,U8 SF_ARG1[RBP]
PUSHFD
ADD RAX,UM_START+7 //round-up to U8
AND RAX,~7
#assert UM_START>=UUM_STRUCT_SIZE
CMP RAX,UM_START
JAE @@4
MOV RAX,UM_START
@@4:
//Multicore issues: structure must be uncached, like $LK,"mp_heap","MN:mp_heap"$
CLI
@@32: LOCK
BTS U4 HC_FLAGS[RDX],HCf_LOCKED
JC @@32
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 I4 @@5
@@10: ADD RAX,MB_STRUCT_SIZE+PAGE_SIZE-1
SHR RAX,PAGE_BITS
PUSH EDX
PUSH EAX
MOV RAX,RSP
PUSH EDX
PUSH EAX
CALL ALLOCATE_MEM_BLKS
MOV RSI,RAX
ADD RSP,16
POP EAX
POP EDX
SHL RAX,PAGE_BITS
SUB RAX,MB_STRUCT_SIZE
ADD RSI,MB_STRUCT_SIZE
JMP @@5
@@13: LEA RSI,U8 HC_MALLOC_FREE_LIST-UUM_NEXT[RDX]
@@1: MOV RBX,RSI
MOV RSI,U8 UUM_NEXT[RBX]
OR RSI,RSI
JNZ @@2
PUSH EAX //-****
ADD RAX,16*PAGE_SIZE-1
SHR RAX,PAGE_BITS
PUSH EDX
PUSH EAX //num blks
MOV RAX,RSP
PUSH EDX
PUSH EAX //address of num blks out
CALL ALLOCATE_MEM_BLKS
MOV RSI,RAX
ADD RSP,16
POP EAX
POP EDX
LEA RSI,U8 MB_STRUCT_SIZE[RSI]
SHL RAX,PAGE_BITS
SUB RAX,MB_STRUCT_SIZE
LEA RBX,U8 HC_MALLOC_FREE_LIST-UUM_NEXT[RDX]
MOV RDI,U8 UUM_NEXT[RBX]
MOV U8 UUM_NEXT[RSI],RDI
MOV U8 UUM_SIZE[RSI],RAX
MOV U8 UUM_NEXT[RBX],RSI
POP EAX //+****
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
MOV RAX,U8 UUM_SIZE[RSI]
JMP @@8
@@7: ADD RSI,U8 UUM_SIZE[RSI] //SET ESI TO @ALLOCATED
PAGES
@@5:
#if HEAP_DBG
//InsQue
MOV RDI,U8 HC_LAST_UM[RDX]
MOV U8 UM_NEXT[RDI],RSI
MOV U8 HC_LAST_UM[RDX],RSI
MOV U8 UM_LAST[RSI],RDI
LEA RDI,U8 HC_NEXT_UM-UM_NEXT[RDX]
MOV U8 UM_NEXT[RSI],RDI
//Caller1/Caller2
PUSH RDX
MOV RDX,U8 [SYS_HEAP_LIMIT]
MOV RDI,U8 SF_RIP[RBP]
CMP RDI,RDX
JB @@46
XOR EDI,EDI
MOV U8 UM_CALLER1[RSI],RDI
JMP @@48
@@46: MOV U8 UM_CALLER1[RSI],RDI
MOV RDI,U8 SF_RBP[RBP]
CMP RDI,RDX
JB @@47
XOR EDI,EDI
JMP @@48
@@47: MOV RDI,U8 SF_RIP[RDI]
CMP RDI,RDX
JB @@48
XOR EDI,EDI
@@48: MOV U8 UM_CALLER2[RSI],RDI
POP RDX
#endif
LOCK
BTR U4 HC_FLAGS[RDX],HCf_LOCKED
POPFD
MOV U8 UM_SIZE[RSI],RAX
MOV U8 UM_HEAP_CTRL[RSI],RDX
LEA RAX,U8 UM_START[RSI]
BT U4 [SYS_SEMAS+SYS_SEMA_HEAPLOG*SEMA_STRUCT_SIZE],0
JNC @@200
PUSH_C_REGS
PUSH EDX
PUSH EAX
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: TEST U1 [SYS_HEAP_INIT_FLAG],1
JZ @@210
PUSH EAX
PUSH ECX
MOV RCX,U8 UM_SIZE-UM_START[RAX]
SUB RCX,UM_START
MOV RDI,RAX
MOV AL,U1 [SYS_HEAP_INIT_VAL]
REP_STOSB
POP ECX
POP EAX
@@210: POP EDI
POP ESI
POP EBP
RET
////**************************PROCEDURE*************************
CP_FREE_HC::
PUSH EBP
MOV RBP,RSP
PUSH ESI
PUSH EDI
BT U4 [SYS_SEMAS+SYS_SEMA_HEAPLOG*SEMA_STRUCT_SIZE],0
JNC @@1
PUSH_C_REGS
PUSH U8 SF_ARG1[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_ARG1[RBP]
OR RSI,RSI
#if HEAP_DBG
JZ I4 FREE_HC_DONE
#else
JZ FREE_HC_DONE
#endif
FREE_HC_JOIN::
PUSHFD
SUB RSI,UM_START
MOV RDX,U8 UM_HEAP_CTRL[RSI]
MOV RAX,U8 UM_SIZE[RSI]
//Multicore issues: structure must be uncached, like $LK,"mp_heap","MN:mp_heap"$
CLI
@@32: LOCK
BTS U4 HC_FLAGS[RDX],HCf_LOCKED
JC @@32
#if HEAP_DBG
//RemQue
MOV RDX,U8 UM_NEXT[RSI]
MOV RDI,U8 UM_LAST[RSI]
MOV U8 UM_LAST[RDX],RDI
MOV U8 UM_NEXT[RDI],RDX
//Caller1/Caller2
MOV RDX,U8 [SYS_HEAP_LIMIT]
MOV RDI,U8 SF_RIP[RBP]
CMP RDI,RDX
JB @@46
XOR EDI,EDI
MOV U8 UUM_CALLER1[RSI],RDI
JMP @@48
@@46: MOV U8 UUM_CALLER1[RSI],RDI
MOV RDI,U8 SF_RBP[RBP]
CMP RDI,RDX
JB @@47
XOR EDI,EDI
JMP @@48
@@47: MOV RDI,U8 SF_RIP[RDI]
CMP RDI,RDX
JB @@48
XOR EDI,EDI
@@48: MOV U8 UUM_CALLER2[RSI],RDI
MOV RDX,U8 UM_HEAP_CTRL[RSI]
#endif
CMP RAX,HEAP_HASH_SIZE
JAE @@5
#assert UUM_SIZE==UM_SIZE
// 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 EDX
PUSH ESI
CALL FREE_MEM_BLKS
ADD RSP,8
POP EDX
@@101: LOCK
BTR U4 HC_FLAGS[RDX],HCf_LOCKED
POPFD
FREE_HC_DONE:
POP EDI
POP ESI
POP EBP
RET
////**************************PROCEDURE*************************
// OUT: RAX=BASE ADDRESS
//
CP_MALLOC::
PUSH EBP
MOV RBP,RSP
PUSH ESI
PUSH EDI
XOR EBX,EBX
MOV RDX,U8 SF_ARG2[RBP]
OR RDX,RDX
JNZ @@30
MOV RDX,U8 FS:TSS_ADDRESS[RBX]
@@30: MOV RDX,U8 TSS_DATA_HEAP[RDX]
JMP I4 MALLOC_HC_JOIN
////**************************PROCEDURE*************************
CP_MSIZE::
PUSH EBP
MOV RBP,RSP
MOV RBX,U8 SF_ARG1[RBP]
XOR EAX,EAX
OR RBX,RBX
JZ @@100
MOV RAX,U8 UM_SIZE-UM_START[RBX]
SUB RAX,UM_START
@@100: POP EBP
RET
////**************************PROCEDURE*************************
CP_MSIZE2::
PUSH EBP
MOV RBP,RSP
MOV RBX,U8 SF_ARG1[RBP]
XOR EAX,EAX
OR RBX,RBX
JZ @@100
MOV RAX,U8 UM_SIZE-UM_START[RBX]
@@100: POP EBP
RET
////**************************PROCEDURE*************************
CP_MHEAP_CTRL::
PUSH EBP
MOV RBP,RSP
MOV RBX,U8 SF_ARG1[RBP]
XOR EAX,EAX
OR RBX,RBX
JZ @@100
MOV RAX,U8 UM_HEAP_CTRL-UM_START[RBX]
@@100: POP EBP
RET
};
LTextern CP_MALLOC void *MAlloc(U8 size,TssStruct *tss=NULL);
LTextern CP_FREE_HC void Free(void *add);
LTextern CP_MSIZE U8 MSize(void *src); //size of heap object
LTextern CP_MSIZE2 U8 MSize2(void *src); //Internal size
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 *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 *StrNew(I1 *buf,TssStruct *tss=NULL)
{
U8 size;
I1 *result;
if (buf) {
size=StrLen(buf)+1;
result=MAlloc(size,tss);
MemCpy(result,buf,size);
} else {
result=MAlloc(1);
*result=0;
}
return result;
}
I1 *AStrNew(I1 *buf)
{
return StrNew(buf,adam_tss);
}
void *AMAllocZ(U8 size)
{
return MAllocZ(size,adam_tss);
}
void LinkedListDel(void **list)
{
void **d;
while (list) {
d=*list;
Free(list);
list=d;
}
}
U8 LinkedListSize(void **list)
{
U8 result=0;
while (list) {
result+=MSize2(list);
list=*list;
}
return result;
}
void InitBlkPool(BlkPool *bp,U8 pages512)
{
MemBlk *m;
MemSet(bp,0,sizeof(BlkPool));
bp->size=pages512;
m=(bp><(U1 *)+sizeof(BlkPool)+PAGE_SIZE-1)&~(PAGE_SIZE-1);
bp->mem_free_list=m;
m->next=NULL;
m->pages=(bp><(U1 *)+pages512<<PAGE_BITS-m><(U1 *))>>PAGE_BITS;
m->signature=MBS_UNUSED_SIGNATURE;
}
LTextern CP_MALLOC_HC void *MAllocHC(U8 size,HeapCtrl *hc);
LTextern CP_MSIZE U8 MSizeHC(void *src); //size of heap object
LTextern CP_MHEAP_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 *StrNewHC(I1 *buf,HeapCtrl *hc)
{
U8 size;
I1 *result;
if (buf) {
size=StrLen(buf)+1;
result=MAllocHC(size,hc);
MemCpy(result,buf,size);
} else {
result=MAllocHC(1,hc);
*result=0;
}
return result;
}
HeapCtrl *InitTssHeapCtrl(TssStruct *tss,BlkPool *bp,HeapCtrl *hc_original)
{
void *b;
HeapCtrl *hc;
//$LK,"Adam Tss","FF:::/LT/OSMain/OSStartUp.ASZ,HC_BP"$
hc=MAllocHCZ(sizeof(HeapCtrl),hc_original);
hc->bp=bp;
hc->mem_tss=tss;
b=&hc->next_mem_blk;
hc->next_mem_blk=hc->last_mem_blk=b;
hc->next_um=hc->last_um=(&hc->next_um)><(U1 *)-offset(UsedAllocatedMem.next);
return hc;
}
HeapCtrl *InitIndependentHeapCtrl(BlkPool *bp,U8 pages512)
{
HeapCtrl *hc=bp><(U1 *)+sizeof(BlkPool);
MemBlk *m;
MemSet(bp,0,sizeof(BlkPool)+sizeof(HeapCtrl));
Bts(&hc->flags,HCf_NON_TASK_QUEUE);
hc->bp=bp;
hc->next_um=hc->last_um=(&hc->next_um)><(U1 *)-offset(UsedAllocatedMem.next);
bp->size=pages512;
m=(bp><(U1 *)+sizeof(BlkPool)+sizeof(HeapCtrl)+PAGE_SIZE-1)&~(PAGE_SIZE-1);
bp->mem_free_list=m;
m->next=NULL;
m->pages=(bp><(U1 *)+pages512<<PAGE_BITS-m><(U1 *))>>PAGE_BITS;
m->signature=MBS_UNUSED_SIGNATURE;
return hc;
}
Memory Manager