hschumann2/TempleOS-Source-Code
0847
1 2U0 SysBadFree(I64 *ptr)3{4 Panic("Bad Free:",ptr);5}6 7U0 SysBadMAlloc(I64 *ptr)8{9 Panic("Bad MAlloc:",ptr);10}11 12U8 *MemPagAlloc(I64 pags,CBlkPool *bp=NULL)13{/*Alloc pags from BlkPool. Don't link to task.14(Linking to a task means they will be freed when the task dies.)15It might give you more than you asked for.16 17Return: NULL if out of memory.18*/19 CMemBlk *res=NULL,*m;20 I64 i;21 if (!bp) bp=sys_code_bp;22 PUSHFD23 CLI24 while (LBts(&bp->locked_flags,BPlf_LOCKED))25 PAUSE26 if (pags<MEM_FREE_PAG_HASH_SIZE) {27 if (res=bp->free_pag_hash[pags]) {28 bp->free_pag_hash[pags]=res->next;29 goto at_done;30 }31 i=Bsr(MEM_FREE_PAG_HASH_SIZE)+1;32 } else {33//We'll now round-up to a power of two.34 //There is some overhead on allocations and35 //we wouldn't want to round to the next36 //power of two if a power of two was requested.37 //So we use a little more than a power of two.38 pags-=MEM_EXTRA_HASH2_PAGS;39 i=Bsr(pags)+1;40 pags=1<<i+MEM_EXTRA_HASH2_PAGS;41 if (res=bp->free_pag_hash2[i]) {42 bp->free_pag_hash2[i]=res->next;43 goto at_done;44 }45 }46 m=&bp->mem_free_lst;47 while (TRUE) {48 if (!(res=m->next)) {49//We're probably out of luck, but lets search for a50 //freed larger size block... and, screw-it, return the whole thing.51 do {52 if (res=bp->free_pag_hash2[++i]) {53 pags=1<<i+MEM_EXTRA_HASH2_PAGS;54 bp->free_pag_hash2[i]=res->next;55 goto at_done;56 }57 } while (i<64-MEM_PAG_BITS-1);58 pags=0;59 res=NULL; //Out of memory60 goto at_done2;61 }62 if (res->pags<pags)63 m=res;64 else {65 if (res->pags==pags) {66 m->next=res->next;67 goto at_done;68 } else {69 res->pags-=pags;70 res(U8 *)+=res->pags<<MEM_PAG_BITS;71 res->pags=pags;72 goto at_done;73 }74 }75 }76at_done:77 bp->used_u8s+=res->pags<<MEM_PAG_BITS;78at_done2:79 LBtr(&bp->locked_flags,BPlf_LOCKED);80 POPFD81 return res;82}83 84U0 MemPagFree(CMemBlk *m,CBlkPool *bp=NULL)85{//Return non-task pags to BlkPool.86 I64 i,pags;87 if (m) {88 if (!bp) bp=sys_code_bp;89 PUSHFD90 CLI91 while (LBts(&bp->locked_flags,BPlf_LOCKED))92 PAUSE93 pags=m->pags;94 m->mb_signature=MBS_UNUSED_SIGNATURE_VAL;95 bp->used_u8s-=pags<<MEM_PAG_BITS;96 if (pags<MEM_FREE_PAG_HASH_SIZE) {97 m->next=bp->free_pag_hash[pags];98 bp->free_pag_hash[pags]=m;99 } else {100//We'll now round-up to a power of two.101 //There is some overhead on allocations and102 //we wouldn't want to round to the next103 //power of two if a power of two was requested.104 //So we use a little more than a power of two.105 pags-=MEM_EXTRA_HASH2_PAGS;106 i=Bsr(pags);107 m->next=bp->free_pag_hash2[i];108 bp->free_pag_hash2[i]=m;109 }110 LBtr(&bp->locked_flags,BPlf_LOCKED);111 POPFD112 }113}114 115CMemBlk *MemPagTaskAlloc(I64 pags,CHeapCtrl *hc)116{/*hc must be locked. Don't preempt this routine.117Currently, this is only called from MAlloc().118Return: NULL if out of memory.119*/120 CMemBlk *res;121 I64 threshold,cnt,size;122 CMemUnused *uum,**_uum,**_ptr;123 if (res=MemPagAlloc(pags,hc->bp)) {124 QueIns(res,hc->last_mem_blk);125 res->mb_signature=MBS_USED_SIGNATURE_VAL;126 hc->alloced_u8s+=res->pags<<MEM_PAG_BITS;127 128 //Tidy-up free lst (Move into heap hash)129 //because if free lst gets long, delay causes crash.130 threshold=MEM_HEAP_HASH_SIZE>>4;131#assert MEM_HEAP_HASH_SIZE>>4>=sizeof(U8 *)132 do {133 cnt=0;134 _uum=&hc->malloc_free_lst;135 while (uum=*_uum) {136#assert !offset(CMemUnused.next)137 size=uum->size;138 if (size<threshold) {139 *_uum=uum->next;140 _ptr=(&hc->heap_hash)(U8 *)+size;141 uum->next=*_ptr;142 *_ptr=uum;143 } else {144 cnt++;145 _uum=uum;146 }147 }148 threshold<<=1;149 } while (cnt>8 && threshold<=MEM_HEAP_HASH_SIZE);150 }151 return res;152}153 154U0 MemPagTaskFree(CMemBlk *m,CHeapCtrl *hc)155{//hc must be locked156 if (m) {157 PUSHFD158 CLI159 if (m->mb_signature!=MBS_USED_SIGNATURE_VAL)160 SysBadFree(m);161 else {162 QueRem(m);163 hc->alloced_u8s-=m->pags<<MEM_PAG_BITS;164 MemPagFree(m,hc->bp);165 }166 POPFD167 }168}169 