📄 sbm.c
字号:
*/}/* SBM_MMRG(sm) - Merge a memory area with the area following it. * The node (and memory area) following the SM pointed to are * merged in and the successor node freed up. The flags * and smuse of the current SM (which is not moved or anything) * remain the same. */sbm_mmrg(smp)struct smblk *smp;{ register struct smblk *sm, *sm2; sm = smp; sm->smlen += (sm2 = sm->smforw)->smlen; /* Add succ's len */ if(sm->smforw = sm2->smforw) /* and fix linkages */ sm->smforw->smback = sm; sbm_nfre(sm2); /* now can flush succ node */}/* SBM_SPLIT - Split up an area (gets a new smblk to point to split-off * portion.) * Note returned value is ptr to 2nd smblk, since this is a new one. * Ptr to 1st remains valid since original smblk stays where it is. * NOTE: Beware of splitting up free mem (SM_USE == 0) since sbm_nget may * steal it out from under unless precautions are taken! See comments * at sbm_mget related to this. */struct smblk *sbm_split(smp,coff)struct smblk *smp;SBMO coff;{ register struct smblk *sm, *smx; register SBMO csiz; if((sm = smp)->smlen <= (csiz = coff)) return(0); if((smx = sbm_nget()) == 0) return(0); smx->smlen = sm->smlen - csiz; /* Set 2nd size */ smx->smaddr = sm->smaddr + csiz; /* Set 2nd addr */ sm->smlen = csiz; /* Take from 1st size */ smx->smflags = sm->smflags; /* Copy flags */ if(smx->smforw = sm->smforw) /* Splice 2nd after 1 */ smx->smforw->smback = smx; smx->smback = sm; sm->smforw = smx; /* Put 2nd into chain */ return(smx); /* Return ptr to 2nd smblk */}#if 0 /* Replaced by "bcopy" for system-dep efficiency *//* SBM_SCPY - Copy string of bytes. Somewhat machine-dependent; * Tries to be clever about using word moves instead of byte moves. */sbm_scpy(from, to, count) /* Copy count bytes from -> to */char *from, *to;unsigned count;{ register char *s1, *s2; register unsigned cnt; int tmp; if((cnt = count) == 0) return; s1 = from; s2 = to; while(rndrem((int)s1)) /* Get 1st ptr aligned */ { *s2++ = *s1++; if(--cnt == 0) return; } if(rndrem((int)s2) == 0) /* Do wd move if ptr 2 now aligned */ {#ifdef DUMBPCC /* Code for dumber (Portable C type) compiler */ register WORD *ap, *bp; tmp = cnt; ap = (WORD *) s1; bp = (WORD *) s2; if(cnt = rnddiv(cnt)) do { *bp++ = *ap++; } while(--cnt); if ((cnt = rndrem(tmp)) ==0) return; s1 = (char *) ap; s2 = (char *) bp;#else /* Tight loop for efficient copying on 11s */ tmp = cnt; if(cnt = rnddiv(cnt)) do { *((WORD *)s2)++ = *((WORD *)s1)++; } while(--cnt); if((cnt = rndrem(tmp)) == 0) return;#endif /*-DUMBPCC*/ } do { *s2++ = *s1++; } /* Finish up with byte loop */ while(--cnt);}#endif /*COMMENT*/struct smblk * /* If it returns at all, this is most common type */sbm_err(val,str,a0,a1,a2,a3)char *str;struct smblk *val;{ int *sptr; sptr = (int *) &sptr; /* Point to self on stack */ sptr += 5; /* Point to return addr */ if((int)sbm_debug==1) abort(); if(sbm_debug) (*sbm_debug)(0,*sptr,str,a0,a1,a2,a3); return(val);}/* These routines correspond to the V7 LIBC routines as described * in the V7 UPM (3). They should provide satisfactory emulation * if the documentation is correct. Replacement is necessary since * the SBM routines are jealous and cannot tolerate competition for * calls of SBRK; i.e. the memory being managed must be contiguous. *//* Guaranteed to return word-aligned pointer to area of AT LEAST * requested size. Area size is rounded up to word boundary. */char *malloc(size)unsigned size;{ register struct smblk *sm, **sma; register SBMO siz; siz = rndup(size + sizeof (struct smblk *)); /* Make room for ptr */ if((sm = sbm_mget(siz,siz)) == 0) return(0); *(sma = (struct smblk **)sm->smaddr) = sm; /* Store ptr in addr-1 */ return((char *)++sma);}char *alloc(size) /* For V6 programs - note different failure value! */unsigned size;{ register char *addr; return((addr = malloc(size)) ? addr : (char *) -1);}free(ptr)char *ptr;{ register struct smblk *sm, **smp; smp = &((struct smblk **)ptr)[-1]; /* Point to addr-1 */ sm = *smp; /* Pluck SM ptr therefrom */ if(((sm->smflags&0377) != SM_NID) || sm->smaddr != (SBMA)smp) return((int)sbm_err(0,"free: bad arg %o", ptr)); sbm_mfree(sm); return(1);}char *realloc(ptr,size)char *ptr;unsigned size;{ register struct smblk *sm, **smp; smp = &((struct smblk **)ptr)[-1]; /* Point to addr-1 */ sm = *smp; /* Pluck SM ptr therefrom */ if(((sm->smflags&0377) != SM_NID) || (sm->smaddr != (SBMA)smp)) return((char *)sbm_err(0,"realloc: bad arg %o",ptr)); if((sm = sbm_exp(sm, rndup(size+(sizeof(struct smblk *))))) == 0) return(0); *(smp = (struct smblk **)sm->smaddr) = sm; /* Save smblk ptr */ return((char *)++smp);}char *calloc(nelem,elsize)unsigned nelem, elsize;{ register SBMO cmin; register WORD *ip; /* Clear in units of words */ register char *addr; if((cmin = nelem*elsize) == 0 /* Find # bytes to get */ || (addr = malloc(cmin)) == 0) /* Get it */ return(0); ip = (WORD *) addr; /* Set up ptr to area */ cmin = rnddiv(cmin+WDSIZE-1); /* Find # words to clear */ do { *ip++ = 0; } while (--cmin); /* Zap the area */ return(addr);}/* SBM_NGC() - Specific routine for GC'ing SMBLK nodes. * * SBM_XNGC(begp, elsize, type) - Compact nodes of specified type. * Scans allocated mem from low to high to find chunks with nodes of * the specified type. * Flushes current freelist and rebuilds it as scan progresses, * such that 1st thing on list is lowest-addr node. When a node is * seen that can be moved, new node is acquired from freelist if * it exists, otherwise no move is made. If a chunk has been scanned * and no active nodes remain, it is flushed and freelist updated. * NOTE: This has not yet been verified to work with nodes of any * type other than SMBLK. */sbm_ngc(){ register struct smblk *sm; if(!(sm = sbm_nxtra)) return((int)sbm_err(0,"Zero sbm_nxtra")); sm->smflags |= SM_USE; /* Ensure this one isn't GC'd */ sbm_xngc(&sbm_nfl, sizeof(struct smblk), SM_MNODS); sm->smflags = 0; /* Flush temporary crock */}sbm_xngc(begp, elsize, flag)struct smblk **begp;unsigned elsize, flag;{ register struct smblk *sm, *chk, *smf; struct smblk *ftail, *savtail; int cnt, inuse; *begp = ftail = 0; /* Flush node freelist */ for(chk = sbm_list; chk; chk = chk->smforw) if(chk->smflags&flag) { sm = (struct smblk *) chk->smaddr; cnt = (chk->smuse)/elsize; savtail = ftail; inuse = 0; smf = *begp; /* Set up ptr to 1st freelist node */ while(--cnt >= 0) { /* Here decide if movable */ if(sm->smflags && smf /* Live and have copy place */ && ( (sm->smflags&SM_USE) == 0 /* Free mem? */ || (sm->smflags&(SM_MNODS|SM_DNODS)) ) && sm->smback) /* has backptr (see ncpy) */ { /* Move the node */ *begp = smf->smforw; /* Get free node */ if(smf == ftail) ftail = 0; if(smf == savtail) savtail = 0; /* Move node. Already checked for back ptr * of 0 since no obvious way to tell where * the ptr to list is kept. Sigh. */ sbm_nmov(sm,smf,(struct smblk **)0,elsize); /* Get ptr to new freelist node. Note * check to ensure that it is not in this * same chunk (if it is, no point in moving * any nodes!) */ if((smf = *begp) >= chk) smf = 0; /* Zero if same chk */ sm->smflags = 0; /* Make node free */ } /* At this point, not movable */ if(sm->smflags == 0) /* Free node? */ { if(ftail) /* Add to freelist */ ftail->smforw = sm; ftail = sm; if(*begp == 0) *begp = sm; sm->smforw = 0; } else inuse++; sm = (struct smblk *)((SBMA)sm + elsize); } if(inuse == 0 /* All free? */ && (sm = chk->smback)) /* & not 1st? */ { if(savtail) /* Edit freelist */ (ftail = savtail)->smforw = 0; else *begp = ftail = 0; sbm_mfree(chk); chk = sm; } }}/* * Note that proc must return a zero value, or loop aborts and * returns that selfsame value. */sbm_nfor(flag,nodsiz,proc,arg)int flag;int (*proc)();int nodsiz;struct sbfile *arg;{ register struct smblk *sm, *np; register int cnt; int res; for(sm = sbm_list; sm; sm = sm->smforw) if(sm->smflags&flag) { np = (struct smblk *) sm->smaddr; cnt = sm->smuse/nodsiz; do { if(np->smflags) if(res = (*proc)(np,arg)) return(res); np = (struct smblk *)((SBMA)np + nodsiz); } while(--cnt); } return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -