Files
Arquivotheca.SunOS-4.1.4/sys/old/vm_text.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

348 lines
6.7 KiB
C

/* @(#)vm_text.c 1.1 94/10/31 SMI; from UCB 4.14 82/12/17 */
#include <machine/pte.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/map.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/text.h>
#include <sys/buf.h>
#include <sys/seg.h>
#include <sys/vm.h>
#include <sys/cmap.h>
#include <sys/uio.h>
#include <sys/vfs.h>
#include <sys/vnode.h>
/*
* relinquish use of the shared text segment
* of a process.
*/
xfree()
{
register struct text *xp;
register struct vnode *vp;
struct vattr vattr;
if((xp=u.u_procp->p_textp) == NULL)
return;
xlock(xp);
vp = xp->x_vptr;
if(--xp->x_count==0 &&
(VOP_GETATTR(vp, &vattr, u.u_cred)!=0 || (vattr.va_mode & VSVTX)==0)) {
/*
* If the "getattr" fails, assume it's not sticky.
*/
xunlink(u.u_procp);
xp->x_rssize -= vmemfree(tptopte(u.u_procp, 0), xp->x_size);
if (xp->x_rssize != 0)
panic("xfree rssize");
vp->v_flag &= ~(VTEXT|VTEXTMOD);
VN_RELE(vp);
while (xp->x_poip)
(void) sleep((caddr_t)&xp->x_poip, PSWP+1);
vsxfree(xp, (long)xp->x_size);
xp->x_flag &= ~XLOCK;
xp->x_vptr = NULL;
} else {
xp->x_flag &= ~XLOCK;
xccdec(xp, u.u_procp);
}
u.u_procp->p_textp = NULL;
}
/*
* Attach to a shared text segment.
* If there is no shared text, just return.
* If there is, hook up to it:
* if it is not currently being used, it has to be read
* in from the vnode (vp); the written bit is set to force it
* to be written out as appropriate.
* If it is being used, but is not currently in core,
* a swap has to be done to get it back.
*/
xalloc(vp, pagi)
register struct vnode *vp;
{
register struct text *xp;
register struct text *xp1;
caddr_t tmemoffset;
int tfileoffset;
struct vattr vattr;
caddr_t gettmem();
if(u.u_exdata.ux_tsize == 0)
return;
again:
if (VOP_GETATTR(vp, &vattr, u.u_cred) != 0) {
swkill(u.u_procp, "xalloc: getattr failed");
return;
}
xp1 = NULL;
for (xp = text; xp < textNTEXT; xp++) {
if(xp->x_vptr == NULL) {
if(xp1 == NULL)
xp1 = xp;
continue;
}
if (((int)xp->x_count > 0 || (vattr.va_mode & VSVTX)) &&
xp->x_vptr == vp) {
if (xp->x_flag&XLOCK) {
xwait(xp);
goto again;
}
xlock(xp);
xp->x_count++;
u.u_procp->p_textp = xp;
xlink(u.u_procp);
xunlock(xp);
return;
}
}
if((xp=xp1) == NULL) {
tablefull("text");
psignal(u.u_procp, SIGKILL);
return;
}
if (xp->x_vptr) {
goto again;
}
xp->x_vptr = vp;
xp->x_flag = XLOAD|XLOCK;
if (pagi)
xp->x_flag |= XPAGV;
tfileoffset = gettfile();
tmemoffset = (caddr_t)gettmem();
xp->x_size = clrnd(btoc(u.u_exdata.ux_tsize));
if (vsxalloc(xp) == NULL) {
xp->x_flag &= ~XLOCK;
xp->x_vptr = NULL;
swkill(u.u_procp, "xalloc: no swap space for text");
return;
}
xp->x_count = 1;
xp->x_ccount = 0;
xp->x_rssize = 0;
vp->v_flag |= VTEXT;
VN_HOLD(vp);
u.u_procp->p_textp = xp;
xlink(u.u_procp);
if (pagi == 0) {
settprot((long)RW);
u.u_procp->p_flag |= SKEEP;
(void) vn_rdwr(UIO_READ, vp, tmemoffset,
(int)u.u_exdata.ux_tsize, tfileoffset,
UIO_USERSPACE, IO_UNIT, (int *)0);
u.u_procp->p_flag &= ~SKEEP;
}
settprot((long)RO);
xp->x_flag |= XWRIT;
xp->x_flag &= ~XLOAD;
xunlock(xp);
}
/*
* Lock and unlock a text segment from swapping
*/
xlock(xp)
register struct text *xp;
{
while(xp->x_flag&XLOCK) {
xp->x_flag |= XWANT;
(void) sleep((caddr_t)xp, PSWP);
}
xp->x_flag |= XLOCK;
}
/*
* Wait for xp to be unlocked if it is currently locked.
*/
xwait(xp)
register struct text *xp;
{
xlock(xp);
xunlock(xp);
}
xunlock(xp)
register struct text *xp;
{
if (xp->x_flag&XWANT)
wakeup((caddr_t)xp);
xp->x_flag &= ~(XLOCK|XWANT);
}
/*
* Decrement the in-core usage count of a shared text segment.
* When it drops to zero, free the core space.
*/
xccdec(xp, p)
register struct text *xp;
register struct proc *p;
{
if (xp==NULL || xp->x_ccount==0)
return;
xlock(xp);
if (--xp->x_ccount == 0) {
if (xp->x_flag & XWRIT) {
vsswap(p, tptopte(p, 0), CTEXT, 0, xp->x_size, (struct dmap *)0);
if (xp->x_flag & XPAGV)
(void) swap(p, xp->x_ptdaddr,
(caddr_t)tptopte(p, 0),
xp->x_size * sizeof (struct pte),
B_WRITE, B_PAGET, swapdev_vp, 0);
xp->x_flag &= ~XWRIT;
} else
xp->x_rssize -= vmemfree(tptopte(p, 0), xp->x_size);
if (xp->x_rssize != 0)
panic("text rssize");
}
xunlink(p);
xunlock(xp);
}
/*
* free the swap image of all unused saved-text text segments
* which are from virtual filesystem vfsp(used by umount system call).
*/
xumount(vfsp)
register struct vfs *vfsp;
{
register struct text *xp;
for (xp = text; xp < textNTEXT; xp++)
if ((xp->x_vptr != NULL) && (xp->x_vptr->v_vfsp == vfsp))
xuntext(xp);
mpurgevfs(vfsp);
}
/*
* remove a shared text segment from the text table, if possible.
*/
xrele(vp)
register struct vnode *vp;
{
register struct text *xp;
if ((vp->v_flag&VTEXT)==0)
return;
for (xp = text; xp < textNTEXT; xp++)
if (vp==xp->x_vptr)
xuntext(xp);
}
/*
* remove text image from the text table.
* the use count must be zero.
*/
xuntext(xp)
register struct text *xp;
{
register struct vnode *vp;
xlock(xp);
if (xp->x_count) {
xunlock(xp);
return;
}
vp = xp->x_vptr;
xp->x_flag &= ~XLOCK;
xp->x_vptr = NULL;
vsxfree(xp, (long)xp->x_size);
vp->v_flag &= ~(VTEXT|VTEXTMOD);
VN_RELE(vp);
}
/*
* Add a process to those sharing a text segment by
* getting the page tables and then linking to x_caddr.
*/
xlink(p)
register struct proc *p;
{
register struct text *xp = p->p_textp;
if (xp == 0)
return;
vinitpt(p);
p->p_xlink = xp->x_caddr;
xp->x_caddr = p;
xp->x_ccount++;
}
xunlink(p)
register struct proc *p;
{
register struct text *xp = p->p_textp;
register struct proc *q;
if (xp == 0)
return;
if (xp->x_caddr == p) {
xp->x_caddr = p->p_xlink;
p->p_xlink = 0;
return;
}
for (q = xp->x_caddr; q->p_xlink; q = q->p_xlink)
if (q->p_xlink == p) {
q->p_xlink = p->p_xlink;
p->p_xlink = 0;
return;
}
panic("lost text");
}
/*
* Replace p by q in a text incore linked list.
* Used by vfork(), internally.
*/
xrepl(p, q)
struct proc *p, *q;
{
register struct text *xp = q->p_textp;
if (xp == 0)
return;
xunlink(p);
q->p_xlink = xp->x_caddr;
xp->x_caddr = q;
}
int xkillcnt = 0;
/*
* Invalidate the text associated with vp.
* Purge in core cache of pages associated with vp and kill all active
* processes.
*/
xinval(vp)
register struct vnode *vp;
{
register struct text *xp;
register struct proc *p;
mpurge(vp);
for (xp = text; xp < textNTEXT; xp++) {
if ((xp->x_flag & XPAGV) && (xp->x_vptr == vp)) {
for (p = xp->x_caddr; p; p = p->p_xlink) {
/*
* swkill without uprintf
*/
printf(
"pid %d killed due to text modification\n",
p->p_pid);
psignal(p, SIGKILL);
p->p_flag |= SULOCK;
xkillcnt++;
}
break;
}
}
}