// GHEAP.SR MALLOY ATTEMPT TO FIX BUGS get "HEAP.DF"; // Incoming Procedures external [ errhlt; errck; ult; ugt; enphp; enphpd; move; adjustphpd; ckspecs // ** ]; // Incoming Statics external [ dcb; fdebug // ** ]; // Outgoing Procedures external [ hptoff; hpfree; hpalloc; hpcompact; hpinit; hpadjustphp; hppreparemove; inheap; ckhp; // ** ]; // Outgoing Statics external [ vpzone; vsncompact; hdebug // ** ]; // Local Statics static [ vpzone; vsncompact; hdebug // ** ]; // Local Structures structure [ blank bit 15; odd bit 1; ]; // H P T O F F let hptoff(php) be [ (php >> HP.fp) >> HP.bp = php >> HP.bp; (php >> HP.bp) >> HP.fp = php >> HP.fp; vpzone >> ZONE.free = php >> HP.fp; vpzone >> ZONE.cfree = (vpzone >> ZONE.cfree)-(php >> HP.siz); ] // End hptoff // H P F R E E and hpfree(p,newzone; numargs N) be [ let tphp = p-((offset HP.use)/16); if N gr 1 then vpzone = newzone; vpzone >> ZONE.cfree = (vpzone >> ZONE.cfree)+(tphp >> HP.siz); let hpfrlst = vpzone >> ZONE.free; test tphp >> HP.fp eq prevfree ifso [ let tpbkprev = tphp-rv(tphp-bsiz); tpbkprev >> HP.siz = tpbkprev >> HP.siz+(tphp >> HP.siz); tphp = tpbkprev; ] ifnot [ tphp >> HP.fp = hpfrlst >> HP.fp; tphp >> HP.bp = hpfrlst; (hpfrlst >> HP.fp) >> HP.bp = tphp; hpfrlst >> HP.fp = tphp; ]; let nxphp = tphp+(tphp >> HP.siz); if nxphp ne vpzone >> ZONE.max then test not ult(nxphp >> HP.fp,minlink) ifso [ vpzone >> ZONE.cfree = vpzone >> ZONE.cfree+nxphp >> HP.siz; tphp >> HP.siz = tphp >> HP.siz+(nxphp >> HP.siz); hptoff(nxphp); ] ifnot nxphp >> HP.fp = prevfree; // Used block, prev block free rv(tphp-bsiz+tphp >> HP.siz) = tphp >> HP.siz; ] // end hpfree // H P A L L O C and hpalloc(siz,newzone; numargs N) = valof [ let hpovd,hpfrlst = vpzone >> ZONE.ovh,vpzone >> ZONE.free; let tphp = vpzone >> ZONE.free; siz = siz+hpovd; if siz << odd then siz = siz+1; while tphp >> HP.siz ls siz do [ tphp = tphp >> HP.fp; if (tphp eq 0) then errhlt("HWU"); // Used blk on free list if (tphp eq hpfrlst) then resultis 0; ]; hptoff(tphp); // remove from the free list test tphp >> HP.siz ge siz+hpovhf ifso [ let tsiz = tphp >> HP.siz; tphp >> HP.siz = siz; let tphp2nd = tphp+siz; tphp2nd >> HP.siz = tsiz-siz; rv(tphp+tsiz-bsiz) = tsiz-siz; tphp2nd >> HP.fp = 0; hpfree(lv(tphp2nd >> HP.use)); ] ifnot [ let nxphp = tphp+(tphp >> HP.siz); if nxphp ne vpzone >> ZONE.max & nxphp >> HP.fp eq prevfree then nxphp >> HP.fp = 0; // Turn off prevfree ]; rv(tphp-bsiz+tphp >> HP.siz) = tphp >> HP.siz; tphp >> HP.fp = 0; // Block now used. resultis lv(tphp >> HP.use); ] // end hpalloc // C K H P and ckhp(newzone; numargs N) be [ let unused,used = 0,0; if N gr 1 then vpzone = newzone; let minphp,maxphp = vpzone >> ZONE.min,vpzone >> ZONE.max; let hpovd,dummy = vpzone >> ZONE.ovh,lv(vpzone >> ZONE.dummy); let hpfrlst = vpzone >> ZONE.free; let tphp = minphp; let lastfree = false; [ let tblksiz = tphp >> HP.siz; if tblksiz eq 0 then errck("HBZ"); test (tphp >> HP.fp eq 0) % (tphp >> HP.fp eq prevfree) ifso [ used = used+tblksiz; lastfree = false; ] ifnot [ unused = unused+tblksiz; if lastfree then errck("HLF"); lastfree = true; ]; tphp = tphp+tblksiz; if ugt(tphp,maxphp) then errck("HSL"); ] repeatuntil tphp eq maxphp; if minphp+used+unused ne maxphp then errck("HSW"); let tpfree = dummy >> HP.fp; let bhpfrlst,free = false,0; while tpfree ne dummy do [ if not ult(tpfree,maxphp) then errck("HAF"); if tpfree eq hpfrlst then test bhpfrlst ifso errck("HMF"); ifnot bhpfrlst = true; if (tpfree >> HP.fp) >> HP.fp eq 0 then errck("HNF"); free = free+(tpfree >> HP.siz); tpfree = tpfree >> HP.fp; ] if free ne unused then errck("HSF"); if hpovd eq 4 then [ tpfree = dummy >> HP.bp; bhpfrlst = false; free = 0; while tpfree ne dummy do [ if not ult(tpfree,maxphp) then errck("HAB"); if tpfree eq hpfrlst then test bhpfrlst ifso errck("HMB"); ifnot bhpfrlst = true; free = free+(tpfree >> HP.siz); tpfree = tpfree >> HP.bp; ] if free ne unused then errck("HSB"); if unused ne vpzone >> ZONE.cfree then errck("HSC"); ]; // end 4 word overhead checks ] // end ckhp // H P C O M P A C T and hpcompact(up,minphpnew,maxphpnew,newzone; numargs N) be [ if hdebug then ckhp(); // ** if fdebug then ckspecs(); // ** let sum,curadr,endadr,tsiz = 0,nil,nil,0; let newadr = nil; if N eq 0 then up = false; if N gr 3 then vpzone = newzone; if N ls 2 then minphpnew = vpzone >> ZONE.min; if N ls 3 then maxphpnew = vpzone >> ZONE.max; if ult(vpzone >> ZONE.cfree,4) then return; vsncompact = vsncompact+1; if vpzone >> ZONE.ovh eq 2 & up then errhlt("HCU"); // Not allowed test up ifnot [ curadr = vpzone >> ZONE.min; while ult(curadr,vpzone >> ZONE.max) do [ test curadr >> HP.fp eq 0 % curadr >> HP.fp eq prevfree ifso [ curadr >> HP.fp = minphpnew+sum; sum = sum+(curadr >> HP.siz); ] ifnot curadr >> HP.fp = -1; // Mark as Free curadr = curadr+(curadr >> HP.siz); ] ] ifso [ curadr = vpzone >> ZONE.max-(rv (vpzone >> ZONE.max-bsiz)); [ test curadr >> HP.fp eq 0 % curadr >> HP.fp eq prevfree ifso [ sum = sum+(curadr >> HP.siz); curadr >> HP.fp = maxphpnew-sum; ] ifnot curadr >> HP.fp = -1; // Mark as Free if not ugt(curadr,vpzone >> ZONE.min) then break; curadr = curadr-rv(curadr-bsiz); ] repeat; ]; hpcomp1: enphp(hpadjustphp); enphpd(hppreparemove); hpcomp2: sum = 0; test up ifnot [ curadr = vpzone >> ZONE.min; while ult(curadr,vpzone >> ZONE.max) do [ tsiz = curadr >> HP.siz; if curadr >> HP.fp ne -1 then [ newadr = minphpnew+sum; move(curadr,newadr,tsiz); if ult(newadr >> HP.fp,minlink) then adjustphpd(newadr >> HP.fp, newadr); newadr >> HP.fp = 0; // Mark as used sum = sum+tsiz; ] curadr = curadr+tsiz; ]; ] ifso [ curadr = vpzone >> ZONE.max-(rv (vpzone >> ZONE.max-bsiz)); [ tsiz = curadr >> HP.siz; if curadr >> HP.fp ne -1 then [ sum = sum+tsiz; newadr = maxphpnew-sum; test not ult(curadr+tsiz-1,newadr) ifso [ for i = tsiz-1 to 0 by -1 do newadr ! i = curadr ! i; ] ifnot move(curadr,newadr,tsiz); if ult(newadr >> HP.fp,minlink) then adjustphpd(newadr >> HP.fp, newadr); newadr >> HP.fp = 0; ] if not ugt(curadr,vpzone >> ZONE.min) then break; curadr = curadr-rv(curadr-bsiz); ] repeat; ]; tsiz = maxphpnew-minphpnew-sum; // Total of unused storage if up then (minphpnew+tsiz) >> HP.fp = prevfree; test up ifnot hpinit(maxphpnew-tsiz,maxphpnew,vpzone >> ZONE.ovh) ifso hpinit(minphpnew,minphpnew+tsiz,vpzone >> ZONE.ovh); vpzone >> ZONE.min = minphpnew; vpzone >> ZONE.max = maxphpnew; if hdebug then ckhp(); // ** if fdebug then ckspecs(); // ** ] // end hpcompact // H P I N I T // Hpinit sets the sizes for the big initial core block and hpinit(min,max,ovh,newzone; numargs N) be [ if N gr 3 then vpzone = newzone; let dummy = lv(vpzone >> ZONE.dummy); if min << odd then min = min+1; if max << odd then max = max-1; vpzone >> ZONE.free = dummy; vpzone >> ZONE.min = min; vpzone >> ZONE.max = max; vpzone >> ZONE.ovh = ovh; vpzone >> ZONE.cfree = max-min; dummy >> HP.fp = min; dummy >> HP.bp = min; dummy >> HP.siz = hpovhf; rv(dummy+hpovhf-bsiz) = hpovhf; min >> HP.siz = max-min; min >> HP.fp = dummy; min >> HP.bp = dummy; rv(max-1) = max-min; ] // end hpinit // H P A D J U S T P H P // SPE catalogue no. and hpadjustphp(pphp) be rv pphp = (((rv pphp)-(offset HP.use)/16) >> HP.fp)+((offset HP.use)/16); // H P P R E P A R E M O V E // catalogue no. and hppreparemove(id,php) be (php-(offset HP.use)/16) >> HP.fp = id; // I N H E A P // and inheap(php) = valof [ test not ult(php,vpzone >> ZONE.min) & not ugt(php,vpzone >> ZONE.max) ifso resultis true ifnot resultis false ]