# 2.11BSD#431 - /usr/src/sys/sys/vm_text.c

##### Functions

    xalloc            X
    xccdec            X
    xexpand           X
    xfree             X
    xinit             X
    xlock             X
    xumount           X
    xuncore           X
    xunlock           X
    xuntext           X
    xwait             X

##### Variables

    xhead             X
    xstats            X
    xtail             X

##### Macros

    ALLOC             X
    FREE_AT_HEAD      X
    FREE_AT_TAIL      X
    XUNLOCK           X
    X_LOCK            X

       1: /*
       2:  * Copyright (c) 1986 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  *
       6:  *	@(#)vm_text.c	1.2 (2.11BSD GTE) 11/26/94
       7:  */
       8:
       9: #include "param.h"
      10: #include "../machine/seg.h"
      11:
      12: #include "map.h"
      13: #include "user.h"
      14: #include "proc.h"
      15: #include "text.h"
      16: #include "inode.h"
      17: #include "buf.h"
      18: #include "uio.h"
      19: #include "systm.h"
      20:
      21: #define X_LOCK(xp) { \
      22:     while ((xp)->x_flag & XLOCK) { \
      23:         (xp)->x_flag |= XWANT; \
      24:         sleep((caddr_t)(xp), PSWP); \
      25:     } \
      26:     (xp)->x_flag |= XLOCK; \
      27: }
      28: #define XUNLOCK(xp) { \
      29:     if ((xp)->x_flag & XWANT) \
      30:         wakeup((caddr_t)(xp)); \
      31:     (xp)->x_flag &= ~(XLOCK|XWANT); \
      32: }
      33: #define FREE_AT_HEAD(xp) { \
      34:     (xp)->x_forw = xhead; \
      35:     xhead = (xp); \
      36:     (xp)->x_back = &xhead; \
      37:     if (xtail == &xhead) \
      38:         xtail = &(xp)->x_forw; \
      39:     else \
      40:         (xp)->x_forw->x_back = &(xp)->x_forw; \
      41: }
      42: #define FREE_AT_TAIL(xp) { \
      43:     (xp)->x_back = xtail; \
      44:     *xtail = (xp); \
      45:     xtail = &(xp)->x_forw; \
      46:     /* x_forw is NULL */ \
      47: }
      48: #define ALLOC(xp) { \
      49:     *((xp)->x_back) = (xp)->x_forw; \
      50:     if ((xp)->x_forw) \
      51:         (xp)->x_forw->x_back = (xp)->x_back; \
      52:     else \
      53:         xtail = (xp)->x_back; \
      54:     (xp)->x_forw = NULL; \
      55:     (xp)->x_back = NULL; \
      56: }
      57:
      58: /*
      59:  * We place free text table entries on a free list.
      60:  * All text images are treated as "sticky,"
      61:  * and are placed on the free list (as an LRU cache) when unused.
      62:  * They may be reclaimed from the free list until reused.
      63:  * Files marked sticky are locked into the table, and are never freed.
      64:  */
      65: struct  text *xhead, **xtail;       /* text table free list */
      66: #ifdef UCB_METER
      67: struct  xstats xstats;          /* cache statistics */
      68: #endif
      69:
      70: /*
      71:  * initialize text table
      72:  */
      73: xinit()
      74: {
      75:     register struct text *xp;
      76:
      77:     xtail = &xhead;
      78:     for (xp = text; xp < textNTEXT; xp++)
      79:         FREE_AT_TAIL(xp);
      80: }
      81:
      82: /*
      83:  * Decrement loaded reference count of text object.  If not sticky and
      84:  * count of zero, attach to LRU cache, at the head if traced or the
      85:  * inode has a hard link count of zero, otherwise at the tail.
      86:  */
      87: xfree()
      88: {
      89:     register struct text *xp;
      90:
      91:     if ((xp = u.u_procp->p_textp) == NULL)
      92:         return;
      93: #ifdef UCB_METER
      94:     xstats.free++;
      95: #endif
      96:     X_LOCK(xp);
      97:     /*
      98: 	 * Don't add the following test to the "if" below:
      99: 	 *
     100: 	 *	(xp->x_iptr->i_mode & ISVTX) == 0
     101: 	 *
     102: 	 * all text under 2.10 is sticky in an LRU cache.  Putting the
     103: 	 * above test in makes sticky text objects ``gluey'' and nearly
     104: 	 * impossible to flush from memory.
     105: 	 */
     106:     if (--xp->x_count == 0) {
     107:         if (xp->x_flag & XTRC || xp->x_iptr->i_nlink == 0) {
     108:             xp->x_flag &= ~XLOCK;
     109:             xuntext(xp);
     110:             FREE_AT_HEAD(xp);
     111:         } else {
     112: #ifdef UCB_METER
     113:             if (xp->x_flag & XWRIT) {
     114:                 xstats.free_cacheswap++;
     115:                 xp->x_flag |= XUNUSED;
     116:             }
     117:             xstats.free_cache++;
     118: #endif
     119:             --xp->x_ccount;
     120:             FREE_AT_TAIL(xp);
     121:         }
     122:     } else {
     123:         --xp->x_ccount;
     124: #ifdef UCB_METER
     125:         xstats.free_inuse++;
     126: #endif
     127:     }
     128:     XUNLOCK(xp);
     129:     u.u_procp->p_textp = NULL;
     130: }
     131:
     132: /*
     133:  * Attach to a shared text segment.  If there is no shared text, just
     134:  * return.  If there is, hook up to it.  If it is not available from
     135:  * core or swap, it has to be read in from the inode (ip); the written
     136:  * bit is set to force it to be written out as appropriate.  If it is
     137:  * not available from core, a swap has to be done to get it back.
     138:  */
     139: xalloc(ip, ep)
     140:     struct exec *ep;
     141:     register struct inode *ip;
     142: {
     143:     register struct text *xp;
     144:     register u_int  count;
     145:     off_t   offset;
     146:     size_t ts;
     147:
     148:     if (ep->a_text == 0)
     149:         return;
     150: #ifdef UCB_METER
     151:     xstats.alloc++;
     152: #endif
     153:     while ((xp = ip->i_text) != NULL) {
     154:         if (xp->x_flag&XLOCK) {
     155:             /*
     156: 			 * Wait for text to be unlocked,
     157: 			 * then start over (may have changed state).
     158: 			 */
     159:             xwait(xp);
     160:             continue;
     161:         }
     162:         X_LOCK(xp);
     163:         if (xp->x_back) {
     164:             ALLOC(xp);
     165: #ifdef UCB_METER
     166:             xstats.alloc_cachehit++;
     167:             xp->x_flag &= ~XUNUSED;
     168: #endif
     169:         }
     170: #ifdef UCB_METER
     171:         else
     172:             xstats.alloc_inuse++;
     173: #endif
     174:         xp->x_count++;
     175:         u.u_procp->p_textp = xp;
     176:         if (!xp->x_caddr && !xp->x_ccount)
     177:             xexpand(xp);
     178:         else
     179:             ++xp->x_ccount;
     180:         XUNLOCK(xp);
     181:         return;
     182:     }
     183:     xp = xhead;
     184:     if (xp == NULL) {
     185:         tablefull("text");
     186:         psignal(u.u_procp, SIGKILL);
     187:         return;
     188:     }
     189:     ALLOC(xp);
     190:     if (xp->x_iptr) {
     191: #ifdef UCB_METER
     192:         xstats.alloc_cacheflush++;
     193:         if (xp->x_flag & XUNUSED)
     194:             xstats.alloc_unused++;
     195: #endif
     196:         xuntext(xp);
     197:     }
     198:     xp->x_flag = XLOAD|XLOCK;
     199:     ts = btoc(ep->a_text);
     200:     if (u.u_ovdata.uo_ovbase)
     201:         xp->x_size = u.u_ovdata.uo_ov_offst[NOVL];
     202:     else
     203:         xp->x_size = ts;
     204:     if ((xp->x_daddr = malloc(swapmap, (size_t)ctod(xp->x_size))) == NULL) {
     205:         swkill(u.u_procp, "xalloc");
     206:         return;
     207:     }
     208:     xp->x_count = 1;
     209:     xp->x_ccount = 0;
     210:     xp->x_iptr = ip;
     211:     ip->i_flag |= ITEXT;
     212:     ip->i_text = xp;
     213:     ip->i_count++;
     214:     u.u_procp->p_textp = xp;
     215:     xexpand(xp);
     216:     estabur(ts, (u_int)0, (u_int)0, 0, RW);
     217:     offset = sizeof(struct exec);
     218:     if (u.u_ovdata.uo_ovbase)
     219:         offset += (NOVL + 1) * sizeof(u_int);
     220:     u.u_procp->p_flag |= SLOCK;
     221:     u.u_error = rdwri(UIO_READ, ip, (caddr_t)0, ep->a_text & ~1,
     222:             offset, UIO_USERISPACE, IO_UNIT, (int *)0);
     223:
     224:     if (u.u_ovdata.uo_ovbase) { /* read in overlays if necessary */
     225:         register int i;
     226:
     227:         offset += (off_t)(ep->a_text & ~1);
     228:         for (i = 1; i <= NOVL; i++) {
     229:             u.u_ovdata.uo_curov = i;
     230:             count = ctob(u.u_ovdata.uo_ov_offst[i] - u.u_ovdata.uo_ov_offst[i-1]);
     231:             if (count) {
     232:                 choverlay(RW);
     233:                 u.u_error = rdwri(UIO_READ, ip,
     234:                     (caddr_t)(ctob(stoc(u.u_ovdata.uo_ovbase))),
     235:                     count, offset, UIO_USERISPACE,
     236:                     IO_UNIT, (int *)0);
     237:                 offset += (off_t) count;
     238:             }
     239:         }
     240:     }
     241:     u.u_ovdata.uo_curov = 0;
     242:     u.u_procp->p_flag &= ~SLOCK;
     243:     xp->x_flag |= XWRIT;
     244:     xp->x_flag &= ~XLOAD;
     245: }
     246:
     247: /*
     248:  * Assure core for text segment.  If there isn't enough room to get process
     249:  * in core, swap self out.  x_ccount must be 0.  Text must be locked to keep
     250:  * someone else from freeing it in the meantime.   Don't change the locking,
     251:  * it's correct.
     252:  */
     253: xexpand(xp)
     254:     register struct text *xp;
     255: {
     256:     if ((xp->x_caddr = malloc(coremap, xp->x_size)) != NULL) {
     257:         if ((xp->x_flag & XLOAD) == 0)
     258:             swap(xp->x_daddr, xp->x_caddr, xp->x_size, B_READ);
     259:         xp->x_ccount++;
     260:         XUNLOCK(xp);
     261:         return;
     262:     }
     263:     if (setjmp(&u.u_ssave)) {
     264:         sureg();
     265:         return;
     266:     }
     267:     swapout(u.u_procp, X_FREECORE, X_OLDSIZE, X_OLDSIZE);
     268:     XUNLOCK(xp);
     269:     u.u_procp->p_flag |= SSWAP;
     270:     swtch();
     271:     /* NOTREACHED */
     272: }
     273:
     274: /*
     275:  * Lock and unlock a text segment from swapping
     276:  */
     277: xlock(xp)
     278:     register struct text *xp;
     279: {
     280:
     281:     X_LOCK(xp);
     282: }
     283:
     284: /*
     285:  * Wait for xp to be unlocked if it is currently locked.
     286:  */
     287: xwait(xp)
     288: register struct text *xp;
     289: {
     290:
     291:     X_LOCK(xp);
     292:     XUNLOCK(xp);
     293: }
     294:
     295: xunlock(xp)
     296: register struct text *xp;
     297: {
     298:
     299:     XUNLOCK(xp);
     300: }
     301:
     302: /*
     303:  * Decrement the in-core usage count of a shared text segment.
     304:  * When it drops to zero, free the core space.  Write the swap
     305:  * copy of the text if as yet unwritten.
     306:  */
     307: xccdec(xp)
     308:     register struct text *xp;
     309: {
     310:     if (!xp->x_ccount)
     311:         return;
     312:     X_LOCK(xp);
     313:     if (--xp->x_ccount == 0) {
     314:         if (xp->x_flag & XWRIT) {
     315:             swap(xp->x_daddr, xp->x_caddr, xp->x_size, B_WRITE);
     316:             xp->x_flag &= ~XWRIT;
     317:         }
     318:         mfree(coremap, xp->x_size, xp->x_caddr);
     319:         xp->x_caddr = NULL;
     320:     }
     321:     XUNLOCK(xp);
     322: }
     323:
     324: /*
     325:  * Free the swap image of all unused saved-text text segments which are from
     326:  * device dev (used by umount system call).  If dev is NODEV, do all devices
     327:  * (used when rebooting or malloc of swapmap failed).
     328:  */
     329: xumount(dev)
     330:     register dev_t dev;
     331: {
     332:     register struct text *xp;
     333:
     334:     for (xp = text; xp < textNTEXT; xp++)
     335:         if (xp->x_iptr != NULL &&
     336:             (dev == xp->x_iptr->i_dev || dev == NODEV))
     337:             xuntext(xp);
     338: }
     339:
     340: /*
     341:  * Remove text image from the text table.
     342:  * the use count must be zero.
     343:  */
     344: xuntext(xp)
     345:     register struct text *xp;
     346: {
     347:     register struct inode *ip;
     348:
     349:     X_LOCK(xp);
     350:     if (xp->x_count == 0) {
     351:         ip = xp->x_iptr;
     352:         xp->x_iptr = NULL;
     353:         mfree(swapmap, ctod(xp->x_size), xp->x_daddr);
     354:         if (xp->x_caddr)
     355:             mfree(coremap, xp->x_size, xp->x_caddr);
     356:         ip->i_flag &= ~ITEXT;
     357:         ip->i_text = NULL;
     358:         irele(ip);
     359:     }
     360:     XUNLOCK(xp);
     361: }
     362:
     363: /*
     364:  * Free up "size" core; if swap copy of text has not yet been written,
     365:  * do so.
     366:  */
     367: xuncore(size)
     368:     register size_t size;
     369: {
     370:     register struct text *xp;
     371:
     372:     for (xp = xhead; xp; xp = xp->x_forw) {
     373:         if (!xp->x_iptr)
     374:             continue;
     375:         X_LOCK(xp);
     376:         if (!xp->x_ccount && xp->x_caddr) {
     377:             if (xp->x_flag & XWRIT) {
     378:                 swap(xp->x_daddr, xp->x_caddr, xp->x_size, B_WRITE);
     379:                 xp->x_flag &= ~XWRIT;
     380:             }
     381:             mfree(coremap, xp->x_size, xp->x_caddr);
     382:             xp->x_caddr = NULL;
     383:             if (xp->x_size >= size) {
     384:                 XUNLOCK(xp);
     385:                 return;
     386:             }
     387:         }
     388:         XUNLOCK(xp);
     389:     }
     390: }

#### Defined functions

xalloc defined in line 139; used 2 times

- in /usr/src/sys/sys/kern_exec.c line 558, 587

xccdec defined in line 307; used 1 times

- in /usr/src/sys/sys/vm_swap.c line 110

xexpand defined in line 253; used 2 times

- in line 177, 215

xfree defined in line 87; used 3 times

- in /usr/src/sys/sys/kern_exec.c line 557, 574
- in /usr/src/sys/sys/kern_exit.c line 92

xinit defined in line 73; used 1 times

- in /usr/src/sys/sys/init_main.c line 97

xlock defined in line 277; used 1 times

- in /usr/src/sys/sys/vm_swap.c line 36

xumount defined in line 329; used 4 times

- in /usr/src/sys/pdp/machdep2.c line 397
- in /usr/src/sys/sys/subr_rmap.c line 89, 237
- in /usr/src/sys/sys/ufs_mount.c line 282

xuncore defined in line 367; used 4 times

- in /usr/src/sys/sys/subr_rmap.c line 93, 241-243(3)

xunlock defined in line 295; used 3 times

- in /usr/src/sys/sys/vm_swap.c line 40, 49, 59

xuntext defined in line 344; used 6 times

- in line 109, 196, 337
- in /usr/src/sys/sys/ufs_fio.c line 64
- in /usr/src/sys/sys/ufs_syscalls.c line 367, 599

xwait defined in line 287; used 1 times

- in line 159

#### Defined variables

xhead defined in line 65; used 7 times

- in line 34-37(4), 77, 183, 372

xstats defined in line 67; used 9 times

- in line 94, 114-117(2), 125, 151, 166, 172, 192-194(2)

xtail defined in line 65; used 7 times

- in line 37-45(5), 53, 77

#### Defined macros

ALLOC defined in line 48; used 2 times

- in line 164, 189

FREE_AT_HEAD defined in line 33; used 1 times

- in line 110

FREE_AT_TAIL defined in line 42; used 2 times

- in line 79, 120

XUNLOCK defined in line 28; used 10 times

- in line 128, 180, 260, 268, 292, 299, 321, 360, 384-388(2)

X_LOCK defined in line 21; used 7 times

- in line 96, 162, 281, 291, 312, 349, 375

Last modified: 1994-11-27 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1034 |