sys/text.c

05100 #include "../h/param.h" 05101 #include "../h/systm.h" 05102 #include "../h/map.h" 05103 #include "../h/dir.h" 05104 #include "../h/user.h" 05105 #include "../h/proc.h" 05106 #include "../h/text.h" 05107 #include "../h/inode.h" 05108 #include "../h/buf.h" 05109 #include "../h/seg.h" 05110 05111 /* 05112 * Swap out process p. 05113 * The ff flag causes its core to be freed-- 05114 * it may be off when called to create an image for a 05115 * child process in newproc. 05116 * Os is the old size of the data area of the process, 05117 * and is supplied during core expansion swaps. 05118 * 05119 * panic: out of swap space 05120 */ 05121 xswap(p, ff, os) 05122 register struct proc *p; 05123 { 05124 register a; 05125 05126 if(os == 0) 05127 os = p->p_size; 05128 a = malloc(swapmap, ctod(p->p_size)); 05129 if(a == NULL) 05130 panic("out of swap space"); 05131 p->p_flag |= SLOCK; 05132 xccdec(p->p_textp); 05133 swap(a, p->p_addr, os, B_WRITE); 05134 if(ff) 05135 mfree(coremap, os, p->p_addr); 05136 p->p_addr = a; 05137 p->p_flag &= ~(SLOAD|SLOCK); 05138 p->p_time = 0; 05139 if(runout) { 05140 runout = 0; 05141 wakeup((caddr_t)&runout); 05142 } 05143 } 05144 05145 /* 05146 * relinquish use of the shared text segment 05147 * of a process. 05148 */ 05149 xfree() 05150 { 05151 register struct text *xp; 05152 register struct inode *ip; 05153 05154 if((xp=u.u_procp->p_textp) == NULL) 05155 return; 05156 xlock(xp); 05157 xp->x_flag &= ~XLOCK; 05158 u.u_procp->p_textp = NULL; 05159 ip = xp->x_iptr; 05160 if(--xp->x_count==0 && (ip->i_mode&ISVTX)==0) { 05161 xp->x_iptr = NULL; 05162 mfree(swapmap, ctod(xp->x_size), xp->x_daddr); 05163 mfree(coremap, xp->x_size, xp->x_caddr); 05164 ip->i_flag &= ~ITEXT; 05165 if (ip->i_flag&ILOCK) 05166 ip->i_count--; 05167 else 05168 iput(ip); 05169 } else 05170 xccdec(xp); 05171 } 05172 05173 /* 05174 * Attach to a shared text segment. 05175 * If there is no shared text, just return. 05176 * If there is, hook up to it: 05177 * if it is not currently being used, it has to be read 05178 * in from the inode (ip); the written bit is set to force it 05179 * to be written out as appropriate. 05180 * If it is being used, but is not currently in core, 05181 * a swap has to be done to get it back. 05182 */ 05183 xalloc(ip) 05184 register struct inode *ip; 05185 { 05186 register struct text *xp; 05187 register unsigned ts; 05188 register struct text *xp1; 05189 05190 if(u.u_exdata.ux_tsize == 0) 05191 return; 05192 xp1 = NULL; 05193 for (xp = &text[0]; xp < &text[NTEXT]; xp++) { 05194 if(xp->x_iptr == NULL) { 05195 if(xp1 == NULL) 05196 xp1 = xp; 05197 continue; 05198 } 05199 if(xp->x_iptr == ip) { 05200 xlock(xp); 05201 xp->x_count++; 05202 u.u_procp->p_textp = xp; 05203 if (xp->x_ccount == 0) 05204 xexpand(xp); 05205 else 05206 xp->x_ccount++; 05207 xunlock(xp); 05208 return; 05209 } 05210 } 05211 if((xp=xp1) == NULL) { 05212 printf("out of text"); 05213 psignal(u.u_procp, SIGKIL); 05214 return; 05215 } 05216 xp->x_flag = XLOAD|XLOCK; 05217 xp->x_count = 1; 05218 xp->x_ccount = 0; 05219 xp->x_iptr = ip; 05220 ip->i_flag |= ITEXT; 05221 ip->i_count++; 05222 ts = btoc(u.u_exdata.ux_tsize); 05223 xp->x_size = ts; 05224 if((xp->x_daddr = malloc(swapmap, (int)ctod(ts))) == NULL) 05225 panic("out of swap space"); 05226 u.u_procp->p_textp = xp; 05227 xexpand(xp); 05228 estabur(ts, (unsigned)0, (unsigned)0, 0, RW); 05229 u.u_count = u.u_exdata.ux_tsize; 05230 u.u_offset = sizeof(u.u_exdata); 05231 u.u_base = 0; 05232 u.u_segflg = 2; 05233 u.u_procp->p_flag |= SLOCK; 05234 readi(ip); 05235 u.u_procp->p_flag &= ~SLOCK; 05236 u.u_segflg = 0; 05237 xp->x_flag = XWRIT; 05238 } 05239 05240 /* 05241 * Assure core for text segment 05242 * Text must be locked to keep someone else from 05243 * freeing it in the meantime. 05244 * x_ccount must be 0. 05245 */ 05246 xexpand(xp) 05247 register struct text *xp; 05248 { 05249 if ((xp->x_caddr = malloc(coremap, xp->x_size)) != NULL) { 05250 if ((xp->x_flag&XLOAD)==0) 05251 swap(xp->x_daddr, xp->x_caddr, xp->x_size, B_READ); 05252 xp->x_ccount++; 05253 xunlock(xp); 05254 return; 05255 } 05256 if (save(u.u_ssav)) { 05257 sureg(); 05258 return; 05259 } 05260 xswap(u.u_procp, 1, 0); 05261 xunlock(xp); 05262 u.u_procp->p_flag |= SSWAP; 05263 qswtch(); 05264 /* no return */ 05265 } 05266 05267 /* 05268 * Lock and unlock a text segment from swapping 05269 */ 05270 xlock(xp) 05271 register struct text *xp; 05272 { 05273 05274 while(xp->x_flag&XLOCK) { 05275 xp->x_flag |= XWANT; 05276 sleep((caddr_t)xp, PSWP); 05277 } 05278 xp->x_flag |= XLOCK; 05279 } 05280 05281 xunlock(xp) 05282 register struct text *xp; 05283 { 05284 05285 if (xp->x_flag&XWANT) 05286 wakeup((caddr_t)xp); 05287 xp->x_flag &= ~(XLOCK|XWANT); 05288 } 05289 05290 /* 05291 * Decrement the in-core usage count of a shared text segment. 05292 * When it drops to zero, free the core space. 05293 */ 05294 xccdec(xp) 05295 register struct text *xp; 05296 { 05297 05298 if (xp==NULL || xp->x_ccount==0) 05299 return; 05300 xlock(xp); 05301 if (--xp->x_ccount==0) { 05302 if (xp->x_flag&XWRIT) { 05303 xp->x_flag &= ~XWRIT; 05304 swap(xp->x_daddr,xp->x_caddr,xp->x_size,B_WRITE); 05305 } 05306 mfree(coremap, xp->x_size, xp->x_caddr); 05307 } 05308 xunlock(xp); 05309 } 05310 05311 /* 05312 * free the swap image of all unused saved-text text segments 05313 * which are from device dev (used by umount system call). 05314 */ 05315 xumount(dev) 05316 register dev; 05317 { 05318 register struct text *xp; 05319 05320 for (xp = &text[0]; xp < &text[NTEXT]; xp++) 05321 if (xp->x_iptr!=NULL && dev==xp->x_iptr->i_dev) 05322 xuntext(xp); 05323 } 05324 05325 /* 05326 * remove a shared text segment from the text table, if possible. 05327 */ 05328 xrele(ip) 05329 register struct inode *ip; 05330 { 05331 register struct text *xp; 05332 05333 if (ip->i_flag&ITEXT==0) 05334 return; 05335 for (xp = &text[0]; xp < &text[NTEXT]; xp++) 05336 if (ip==xp->x_iptr) 05337 xuntext(xp); 05338 } 05339 05340 /* 05341 * remove text image from the text table. 05342 * the use count must be zero. 05343 */ 05344 xuntext(xp) 05345 register struct text *xp; 05346 { 05347 register struct inode *ip; 05348 05349 xlock(xp); 05350 if (xp->x_count) { 05351 xunlock(xp); 05352 return; 05353 } 05354 ip = xp->x_iptr; 05355 xp->x_flag &= ~XLOCK; 05356 xp->x_iptr = NULL; 05357 mfree(swapmap, ctod(xp->x_size), xp->x_daddr); 05358 ip->i_flag &= ~ITEXT; 05359 if (ip->i_flag&ILOCK) 05360 ip->i_count--; 05361 else 05362 iput(ip); 05363 } 05364 05365 05366 05367 05368 05369 05370 05371 05372 05373 05374 05375 05376 05377 05378 05379 05380 05381 05382 05383 05384 05385 05386 05387 05388 05389 05390 05391 05392 05393 05394 05395 05396 05397 05398 05399