#include "sys/param.h" #include "sys/config.h" #include "sys/mmu.h" #include "sys/types.h" #include "sys/sysmacros.h" #include "sys/systm.h" #include "sys/sysinfo.h" #include "sys/callo.h" #include "sys/dir.h" #include "sys/signal.h" #include "sys/user.h" #include "sys/ipc.h" #include "sys/shm.h" #include "sys/proc.h" #include "sys/text.h" #include "sys/psl.h" #include "sys/var.h" #include "sys/context.h" #include "sys/map.h" /* #define HOWFAR */ extern struct shminfo shminfo; /* shared memory info structure */ struct context cxhdr; /* head of context structure */ /* * Allocate a new context freeing one if necessary */ struct context * cxalloc() { register struct context *cx; /* * search for unused context */ for (cx = cxhdr.cx_forw; cx != &cxhdr; cx = cx->cx_forw) if (cx->cx_proc == 0) return(cxunlink(cx)); /* * return the context on top of the queue */ cx = cxhdr.cx_forw; cxrfree(cx); return(cxunlink(cx)); } /* * Find first used context and free it */ cxfree() { register struct context *cx; for (cx = cxhdr.cx_forw; cx != &cxhdr; cx = cx->cx_forw) { if (cx->cx_proc) { cxrelse(cx); return(0); } } return(-1); } /* * Initialize the context structure linked list */ cxinit() { register struct context *cx; register i; i = USERCX; cx = &cxhdr; cx->cx_forw = cx->cx_back = cx; for (cx = &context[0]; cx < &context[NUMUCONTX]; cx++) { cx->cx_num = cxntocx(i++); cxtail(cx); } } /* * Release the context associated with * a given context structure and * move it to the head of the queue */ cxrelse(cx) register struct context *cx; { register struct context **backp; if (cx == 0) return; #ifdef HOWFAR printf("Releasing %d segs for cx %d\n", cx->cx_dsize, cx->cx_num); #endif cxrfree(cx); cx->cx_back->cx_forw = cx->cx_forw; cx->cx_forw->cx_back = cx->cx_back; backp = (struct context **)&cxhdr.cx_forw; (*backp)->cx_back = cx; cx->cx_forw = *backp; *backp = cx; cx->cx_back = &cxhdr; } /* * Release the context associated with * a given context structure */ cxrfree(cx) register struct context *cx; { register struct proc *p; register struct cxphys *cxp; register struct cxshm *cxs; int i; if ((p = cx->cx_proc) == NULL) return; if (cx->cx_dsize > 0) { #ifdef HOWFAR printf("Freeing %d data segments at %d for pid %d\n", cx->cx_dsize, cx->cx_daddr, p->p_pid); #endif if (cx->cx_daddr == 0) printf("cxrfree error. cx_daddr = 0\n"); mfree(cxmap, (short)cx->cx_dsize, (short)cx->cx_daddr); cx->cx_dsize = 0; cx->cx_daddr = 0; } cxp = &cx->cx_phys[0]; for (i=0; icx_phsize) { mfree(cxmap, (short)cxp->cx_phsize, (short)cxp->cx_phaddr); cxp->cx_phsize = 0; cxp->cx_phaddr = 0; } cxp++; } cxs = &cx->cx_shm[0]; for (i=0; i < shminfo.shmseg; i++) { if (cxs->cx_shmsize) { mfree(cxmap, (short)cxs->cx_shmsize, (short)cxs->cx_shmaddr); cxs->cx_shmsize = 0; cxs->cx_shmaddr = 0; } cxs++; } cx->cx_proc = 0; p->p_context = 0; } /* * Put a context buffer onto the tail of the context queue */ cxtail(cx) register struct context *cx; { register struct context **backp; backp = (struct context **)&cxhdr.cx_back; (*backp)->cx_forw = cx; cx->cx_back = *backp; *backp = cx; cx->cx_forw = &cxhdr; } /* * Release context resources associated * with a text segment. */ cxtxfree(xp) register struct text *xp; { register struct proc *p; for (p = &proc[0]; p < (struct proc *)v.ve_proc; p++) if (p->p_textp == xp) cxrelse(p->p_context); if (xp->x_cxaddr == 0 || xp->x_size == 0) return; mfree(cxmap, (short)ctos(xp->x_size), (short)xp->x_cxaddr); xp->x_cxaddr = 0; } /* * unlink a context structure from the queue */ struct context * cxunlink(cx) register struct context *cx; { cx->cx_back->cx_forw = cx->cx_forw; cx->cx_forw->cx_back = cx->cx_back; return(cx); } /* * Free all shared text segments */ txfree() { register struct text *xp; register struct proc *p; int n; n = 0; for (p = &proc[0]; p < (struct proc *)v.ve_proc; p++) { if ((xp = p->p_textp) != NULL) { cxrelse(p->p_context); if (xp->x_cxaddr && xp->x_size) { mfree(cxmap, (short)ctos(xp->x_size), (short)xp->x_cxaddr); xp->x_cxaddr = 0; n++; } } } return(n); }