1: /* 2: * SCCS id @(#)text.c 2.1 (Berkeley) 8/29/83 3: */ 4: 5: #include "param.h" 6: #include <sys/systm.h> 7: #include <sys/map.h> 8: #include <sys/dir.h> 9: #include <sys/user.h> 10: #include <sys/proc.h> 11: #include <sys/text.h> 12: #include <sys/inode.h> 13: #include <sys/buf.h> 14: #include <sys/seg.h> 15: 16: /* 17: * Swap out process p. 18: * The ff flag causes its core to be freed-- 19: * it may be off when called to create an image for a 20: * child process in newproc. 21: * 22: * panic: out of swap space 23: */ 24: #ifndef VIRUS_VFORK 25: /* 26: * Os is the old size of the data area of the process, 27: * and is supplied during core expansion swaps. 28: */ 29: xswap(p, ff, os) 30: register struct proc *p; 31: #else 32: /* 33: * Odata and ostack are the old data and stack sizes, 34: * supplied during core expansion swaps. 35: */ 36: xswap(p,ff,odata,ostack) 37: register struct proc *p; 38: unsigned odata, ostack; 39: #endif 40: { 41: 42: #ifdef VIRUS_VFORK 43: unsigned a[3]; 44: 45: if (odata == X_OLDSIZE) 46: odata = p->p_dsize; 47: if (ostack == X_OLDSIZE) 48: ostack = p->p_ssize; 49: if (malloc3(swapmap,ctod(p->p_dsize),ctod(p->p_ssize), 50: ctod(USIZE),a) == NULL) 51: panic("out of swap space"); 52: p->p_flag |= SLOCK; 53: xccdec(p->p_textp); 54: if (odata) { 55: swap(a[0], p->p_daddr, odata, B_WRITE); 56: if (ff == X_FREECORE) 57: mfree(coremap, odata, p->p_daddr); 58: } 59: if (ostack) { 60: swap(a[1], p->p_saddr, ostack, B_WRITE); 61: if(ff == X_FREECORE) 62: mfree(coremap, ostack, p->p_saddr); 63: } 64: swap(a[2], p->p_addr, USIZE, B_WRITE); 65: if(ff == X_FREECORE) 66: mfree(coremap, USIZE, p->p_addr); 67: p->p_daddr = a[0]; 68: p->p_saddr = a[1]; 69: p->p_addr = a[2]; 70: p->p_flag &= ~(SLOAD|SLOCK); 71: p->p_time = 0; 72: if(runout) { 73: runout = 0; 74: wakeup((caddr_t)&runout); 75: } 76: 77: #else VIRUS_VFORK 78: register a; 79: 80: if(os == X_OLDSIZE) 81: os = p->p_size; 82: a = malloc(swapmap, ctod(p->p_size)); 83: if(a == NULL) 84: panic("out of swap space"); 85: p->p_flag |= SLOCK; 86: xccdec(p->p_textp); 87: swap(a, p->p_addr, os, B_WRITE); 88: if(ff == X_FREECORE) 89: mfree(coremap, os, p->p_addr); 90: p->p_addr = a; 91: p->p_flag &= ~(SLOAD|SLOCK); 92: p->p_time = 0; 93: if(runout) { 94: runout = 0; 95: wakeup((caddr_t)&runout); 96: } 97: #endif VIRUS_VFORK 98: } 99: 100: /* 101: * relinquish use of the shared text segment 102: * of a process. 103: */ 104: xfree() 105: { 106: register struct text *xp; 107: register struct inode *ip; 108: register struct proc *p = u.u_procp; 109: 110: if((xp=p->p_textp) == NULL) 111: return; 112: xlock(xp); 113: ip = xp->x_iptr; 114: if(--xp->x_count == 0 && (ip->i_mode & ISVTX) == 0) { 115: /* 116: * Only safe to mfree first if we are guaranteed 117: * not to swap with locked text. 118: */ 119: mfree(swapmap, ctod(xp->x_size), xp->x_daddr); 120: mfree(coremap, xp->x_size, xp->x_caddr); 121: ip->i_flag &= ~ITEXT; 122: if (ip->i_flag & ILOCK) 123: ip->i_count--; 124: else 125: iput(ip); 126: xp->x_iptr = NULL; 127: xunlock(xp); 128: } else { 129: xp->x_flag &= ~XLOCK; 130: xccdec(xp); 131: } 132: p->p_textp = NULL; 133: } 134: 135: /* 136: * Attach to a shared text segment. 137: * If there is no shared text, just return. 138: * If there is, hook up to it: 139: * if it is not currently being used, it has to be read 140: * in from the inode (ip); the written bit is set to force it 141: * to be written out as appropriate. 142: * If it is being used, but is not currently in core, 143: * a swap has to be done to get it back. 144: */ 145: xalloc(ip) 146: register struct inode *ip; 147: { 148: register struct text *xp; 149: register unsigned ts; 150: struct text *xp1; 151: 152: if(u.u_exdata.ux_tsize == 0) 153: return; 154: again: 155: xp1 = NULL; 156: for (xp = text; xp < textNTEXT; xp++) { 157: if(xp->x_iptr == NULL) { 158: if(xp1 == NULL) 159: xp1 = xp; 160: continue; 161: } 162: if(xp->x_iptr == ip) { 163: if (xp->x_flag & XLOCK) { 164: /* 165: * Wait for text entry to be unlocked, 166: * then start over in case this text was 167: * xfree'ed. 168: */ 169: xlock(xp); 170: xunlock(xp); 171: goto again; 172: } 173: xlock(xp); 174: xp->x_count++; 175: u.u_procp->p_textp = xp; 176: if (xp->x_ccount == 0) 177: xexpand(xp); 178: else 179: xp->x_ccount++; 180: xunlock(xp); 181: return; 182: } 183: } 184: if((xp=xp1) == NULL) { 185: tablefull("text"); 186: psignal(u.u_procp, SIGKILL); 187: return; 188: } 189: xp->x_flag = XLOAD|XLOCK; 190: xp->x_count = 1; 191: xp->x_ccount = 0; 192: xp->x_iptr = ip; 193: ip->i_flag |= ITEXT; 194: ip->i_count++; 195: #ifdef MENLO_OVLY 196: ts = btoc(u.u_exdata.ux_tsize); 197: if (u.u_ovdata.uo_ovbase) 198: xp->x_size = u.u_ovdata.uo_ov_offst[NOVL]; 199: else 200: xp->x_size = ts; 201: if((xp->x_daddr = malloc(swapmap, (int)ctod(xp->x_size))) == NULL) 202: #else 203: ts = btoc(u.u_exdata.ux_tsize); 204: xp->x_size = ts; 205: if((xp->x_daddr = malloc(swapmap, (int)ctod(ts))) == NULL) 206: #endif 207: panic("out of swap space"); 208: u.u_procp->p_textp = xp; 209: xexpand(xp); 210: estabur(ts, (unsigned)0, (unsigned)0, 0, RW); 211: u.u_count = u.u_exdata.ux_tsize; 212: u.u_offset = sizeof(u.u_exdata); 213: #ifdef MENLO_OVLY 214: if (u.u_ovdata.uo_ovbase) 215: u.u_offset += (1 + NOVL) * sizeof(unsigned); 216: #endif 217: u.u_base = 0; 218: u.u_segflg = 2; 219: u.u_procp->p_flag |= SLOCK; 220: readi(ip); 221: #ifdef MENLO_OVLY 222: /* read in overlays if necessary */ 223: 224: if (u.u_ovdata.uo_ovbase) { 225: register i; 226: for (i = 1; i < 1 + NOVL; i++) { 227: u.u_ovdata.uo_curov = i; 228: u.u_count = ctob(u.u_ovdata.uo_ov_offst[i] 229: - u.u_ovdata.uo_ov_offst[i-1]); 230: u.u_base = ctob(stoc(u.u_ovdata.uo_ovbase)); 231: if( u.u_count != 0) { 232: choverlay(RW); 233: readi(ip); 234: } 235: } 236: } 237: u.u_ovdata.uo_curov = 0; 238: #endif 239: u.u_procp->p_flag &= ~SLOCK; 240: u.u_segflg = 0; 241: xp->x_flag = XWRIT; 242: } 243: 244: /* 245: * Assure core for text segment 246: * Text must be locked to keep someone else from 247: * freeing it in the meantime. 248: * x_ccount must be 0. 249: */ 250: xexpand(xp) 251: register struct text *xp; 252: { 253: if ((xp->x_caddr = malloc(coremap, xp->x_size)) != NULL) { 254: if ((xp->x_flag&XLOAD) == 0) 255: swap(xp->x_daddr, xp->x_caddr, xp->x_size, B_READ); 256: xp->x_ccount++; 257: xunlock(xp); 258: return; 259: } 260: if (save(u.u_ssav)) { 261: sureg(); 262: return; 263: } 264: #ifdef VIRUS_VFORK 265: (void) xswap(u.u_procp, X_FREECORE, X_OLDSIZE, X_OLDSIZE); 266: #else 267: (void) xswap(u.u_procp, X_FREECORE, X_OLDSIZE); 268: #endif 269: xunlock(xp); 270: u.u_procp->p_flag |= SSWAP; 271: #ifdef MENLO_JCL 272: swtch(); 273: #else 274: qswtch(); 275: #endif 276: /* NOTREACHED */ 277: } 278: 279: /* 280: * Lock and unlock a text segment from swapping 281: */ 282: xlock(xp) 283: register struct text *xp; 284: { 285: 286: while(xp->x_flag&XLOCK) { 287: xp->x_flag |= XWANT; 288: sleep((caddr_t)xp, PSWP); 289: } 290: xp->x_flag |= XLOCK; 291: } 292: 293: xunlock(xp) 294: register struct text *xp; 295: { 296: 297: if (xp->x_flag&XWANT) 298: wakeup((caddr_t)xp); 299: xp->x_flag &= ~(XLOCK|XWANT); 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. 305: */ 306: xccdec(xp) 307: register struct text *xp; 308: { 309: 310: if (xp == NULL || xp->x_ccount == 0) 311: return; 312: xlock(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: } 320: xunlock(xp); 321: } 322: 323: /* 324: * Free the swap image of all unused saved-text text segments 325: * which are from device dev (used by umount system call). 326: * Free all unused text segments if dev == NODEV (from malloc). 327: */ 328: xumount(dev) 329: register dev_t dev; 330: { 331: register struct text *xp; 332: 333: for (xp = text; xp < textNTEXT; xp++) 334: if (xp->x_iptr!=NULL && (dev==xp->x_iptr->i_dev || dev==NODEV)) 335: xuntext(xp); 336: } 337: 338: /* 339: * remove a shared text segment from the text table, if possible. 340: */ 341: xrele(ip) 342: register struct inode *ip; 343: { 344: register struct text *xp; 345: 346: if ((ip->i_flag&ITEXT) == 0) 347: return; 348: for (xp = text; xp < textNTEXT; xp++) 349: if (ip == xp->x_iptr) 350: xuntext(xp); 351: } 352: 353: /* 354: * remove text image from the text table. 355: * the use count must be zero. 356: */ 357: xuntext(xp) 358: register struct text *xp; 359: { 360: register struct inode *ip; 361: 362: xlock(xp); 363: if (xp->x_count) { 364: xunlock(xp); 365: return; 366: } 367: ip = xp->x_iptr; 368: xp->x_flag &= ~XLOCK; 369: xp->x_iptr = NULL; 370: mfree(swapmap, ctod(xp->x_size), xp->x_daddr); 371: ip->i_flag &= ~ITEXT; 372: if (ip->i_flag&ILOCK) 373: ip->i_count--; 374: else 375: iput(ip); 376: }