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>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 (numnext; 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->pagespages==num) { m->next=result->next; SetFlags(old_flags); return result; } else { result->pages-=num; result+=result->pages<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 (pages512next=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->pagespages==num) { m->next=result->next; goto done; } else { result->pages-=num; result+=result->pages<pages=num; goto done; } } } while (TRUE); m=&mem_free_list; do { if (!(result=m->next)) { SysOutOfMem; SetFlags(old_flags); return NULL; } if (result->pagespages==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->pagespages==num+j) { result->pages-=num; result+=result->pages<pages=num; goto done; } else { m1=result; result+=j<pages=num; m=result+num<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<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;isignature=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 (numfree_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->pagespages==num) { m->next=result->next; result->signature=MBS_USED_SIGNATURE; SetFlags(old_flags); return result; } else { result->pages-=num; result+=result->pages<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 (pages512next=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->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); }