⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sm_machdep.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
#ifndef lintstatic	char	*sccsid = "@(#)sm_machdep.c	4.2  (ULTRIX)        9/6/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1989 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* ************************************************************************//* * *   Modification History: * * 4 Sep 90 -- dlh *	added include of vectors.h * * 31 Aug 89 -- gg *	Initialise u_odsize and u_ossize before calling ptexpand * * 24 Jul 89 -- jmartin *	Change interface to ptexpand. * * 5-May-89 -- Adrian Thoms *	Added code to check shared mem allocations against *	user page table limit maxprocptes * * 10-Feb-89 -- depp *	New file -- machine dependent routines for SYSTEM V shared memory * */#include "../machine/mtpr.h"#include "../machine/pte.h"#include "../h/param.h"		/* includes types.h & vax/param.h */#include "../h/dir.h"#include "../h/user.h"		/* includes errno.h		*/#include "../h/proc.h"#include "../h/seg.h"#include "../h/cmap.h"#include "../h/vm.h"#include "../h/kmalloc.h"#include "../h/ipc.h"#include "../h/shm.h"#ifdef vax#include "../machine/vectors.h"#endif vaxextern struct sminfo sminfo;/* * This routine does the actual attach of the SMS to the process' address * 	space. * * input parameters: *	p	proc pointer *	sp	smem pointer *	addr	addr parameter from syscall *	flag	flag parameter from syscall * * return codes: *	0	Normal return, attach was successful *	1	error return, u_error set * * panics: *	"sm_attach: out of segments" -- Upon entering routine, *	we are guaranteed that there is enough room in the sm_p array *	to store the per process attach information.  However, we find *	this not to be true. *  */sm_attach(p, sp, addr, flag)struct proc *p;register struct smem *sp;char *addr;int flag;{	struct p_sm *psm;	register int i, smindex = 0;	register int *seg, *sm;	register int segbeg, segend;	int pflag;	struct pte *ptaddr;	size_t osms;		/* SM size before this attach */	int smsize;		/* SM size in CLSIZE chunks */	int p0lr, p1lr;	int s;	smsize = clrnd(btoc(sp->sm_size));	/* An address of 0 places the shared memory	*/	/* into a first fit location.			*/	if (addr == NULL){		seg = ((int *)mfpr(P0BR)) + u.u_tsize +				u.u_dsize + sminfo.smbrk;		seg = (int *)clrnd((int)seg);		segbeg = (int *)seg - (int *)mfpr(P0BR);		if (p->p_smcount) {			for ( ; smindex < sminfo.smseg; smindex++) {			       if (p->p_sm[smindex].sm_p == NULL)				       break;			       if (segbeg + smsize < p->p_sm[smindex].sm_saddr)				       break;			       segbeg = p->p_sm[smindex].sm_eaddr + CLSIZE;			}			if (smindex == sminfo.smseg)				panic("sm_attach: out of segments");		}		segend = segbeg + smsize;	} else {			/* Check to make sure segment does not	*/			/* overlay any valid segments.		*/			/* "addr" was tested or rounded to	*/			/* cluster boundary in code above	*/		segbeg = btop(addr);		if (isatsv(p, segbeg) ||  vtodp(p, segbeg) < p->p_dsize ) {			u.u_error = EINVAL;			return(1);		}		segend = segbeg + smsize;		if (p->p_smcount) {			for ( ; smindex < sminfo.smseg; smindex++) {				if (p->p_sm[smindex].sm_p ==(struct smem *)NULL)					break;				if (segend <= p->p_sm[smindex].sm_saddr)					break;			}			if (smindex == sminfo.smseg)			        panic ("sm_attach: out of segments 2");							if (smindex && 			    (segbeg < p->p_sm[smindex - 1].sm_eaddr)) {				u.u_error = EINVAL;				return(1);			}		}	}	/* Need to increase the size of the page table,	*/	/* allocate and clear.				*/	p0lr = u.u_pcb.pcb_p0lr & ~AST_CLR;	p1lr = u.u_pcb.pcb_p1lr & ~PME_CLR;	{	/* Check that limit for p0 + p1 page tables not exceeded */		extern unsigned maxprocptes; /* param.c */		if (segend + u.u_ssize + HIGHPAGES > maxprocptes) {			u.u_error = ENOMEM;			return(1);		}	}	u.u_odsize = p->p_dsize;	u.u_ossize = p->p_ssize;	u.u_osmsize = p->p_smsize;	if (p->p_smbeg == 0 || p->p_smbeg > segbeg)		p->p_smbeg = segbeg;	if (p->p_smend < segend){		p->p_smend = segend;		p->p_smsize = u.u_smsize = segend - u.u_tsize - u.u_dsize;	}	if (p0lr < segend) {		/* Compute the end of the text+data regions and	*/		/* the beginning of the stack region in the	*/		/* page tables, and expand the page tables if	*/		/* necessary.					*/		register struct pte *p0, *p1;		register int change;		p0 = u.u_pcb.pcb_p0br + p0lr;		p1 = u.u_pcb.pcb_p1br + p1lr;		if ((change = segend - p0lr) > p1 - p0) {			SM_UNLOCK(sp);	/* avoid deadlock (yuch) */			ptexpand(clrnd(ctopt(change - (p1 - p0))), 0);			SM_LOCK(sp);		}		seg = (int *)p->p_p0br + p0lr;		for (i = 0; i < change; i++)			*seg++ = 0;		setp0lr(segend);	}	/* Copy the shared memory segment in	*/	sm = (int *)sp->sm_ptaddr;	seg = (int *)p->p_p0br + segbeg;	pflag = ((flag & SM_RDONLY) ? PG_URKW : PG_UW);	sm_ins_psm(p, smindex);    /* create hole in p_sm array */	psm = &p->p_sm[smindex];	psm->sm_p = sp;	psm->sm_saddr = segbeg;	psm->sm_eaddr = segend;	psm->sm_pflag = pflag;	s = splimp();	smp_lock(&lk_smem, LK_RETRY);	for (i = 0; i < smsize; i++)		if (((struct fpte *)sm)->pg_fod)			*seg++ = *sm++ | pflag;		else			*seg++ = *sm++ | PG_ALLOC | pflag;	psm->sm_link = sp->sm_caddr;	sp->sm_caddr = p;	sp->sm_count++;	sp->sm_ccount++;	smp_unlock(&lk_smem);	(void)splx(s);	u.u_r.r_val1 = ctob(segbeg);	return(0);}/* * This routine is called by smccdec to propogate any "dirty" PTEs on user * level back to the SMS global page table * * this process is detaching from this SMS (due to exit, swapout,  * or detach) so if the modify bit is on for any of the SMS PTEs  * we must be sure to propogate it back to the primary PTEs before  * the copy-PTEs are zeroed.  Note: Since the primary PTEs are only * table entries and are not used by the hardware, an TBIS is not * required. * */sm_cpdirty(p,sp)	register struct proc *p;	register struct smem *sp;{	register i;	register struct pte *pte;	register int smsize;	for (i = 0; i < sminfo.smseg; i++) {		if (p->p_sm[i].sm_p == sp){			break;		}	}	if (i == sminfo.smseg)		panic("smccdec: smseg");	smsize = clrnd(btoc(sp->sm_size));	pte = p->p_p0br + p->p_sm[i].sm_saddr;	for (i = 0; i < smsize; i += CLSIZE, pte += CLSIZE){		register int j;		if (dirtycl(pte)){			*(int *)(sp->sm_ptaddr + i) |= PG_M;			distcl(sp->sm_ptaddr + i);		}		for (j = 0; j < CLSIZE; j++)			*(int *)(pte+j) = 0;	}}/*  * VM_SYSTEM_SMGET() -- kernel level smget() routine for kernel/user mapping * *   This routine MUST only be used to map static kernel page aligned data *   structures into an application's address space.  This routine will *   perform a special version of the shmget() system call.  The assumptions *   are as follows *       1. The system virtual address space, and the underlaying PTEs are *          fully static (i.e., DO NOT use km_alloc'd sva) *       2. The caller validates that the application is permitted to  *          create this Shared Memory Segment (SMS) *       3. Once the application has requested the driver to "get" the  *          SMS (via an IOCTL I assume), full SMS semantics are in effect. *          This means that the application must now call the shmat() system  *          call to actually attach to this segment.  Also, the SMS can *          be detached, reattached, and (upon the last detach) removed. *       4. The beginning system virtual address and size are page cluster *          aligned.  It is up to the calling routine to insure that the  *          protocol for finding a non-page aligned structure is in place for *          the application. * *   INPUT PARAMETERS: *          sva        Beginning system virtual address to be double mapped *          size       Size of the segment in bytes * *               Note: Both must be page aligned * *          mode       This is the protection field.  It uses file type *                     protection (user, group, others) for read/write. *                     Note that execute permission is not used. * *   RETURN PARAMETER: *          -1         Error setting up SMS, u.u_error has been set to *                     indicate error condition *          smid       Shared memory identifier, to be passed back to the *                     application.  This is the normal return value. */vm_system_smget(sva, size, mode) int sva;int size;int mode;{	register int num_ptes = btop(size);	register struct pte *spte;	register struct pte *upte;	register struct smem *sp;	register int smid;	register int nocache;	extern struct smem *smconv();	XPRINTF(XPR_SM,"enter vm_system_smget: sva 0x%x size %d mode %o",		sva, size, mode, 0);	if (((sva & VA_SPACE) != VA_SYS) || 	    !isclbnd(sva) || !isclbnd(size) || (size < CLBYTES)) {		u.u_error = EINVAL;		return (-1);	}	spte = svtopte(sva); 	while (num_ptes--) {		if ((spte++)->pg_v == 0) {			u.u_error = EINVAL;			return(-1);		}	}	mode &= 0777;	if ((smid = smget(sva, size, IPC_CREAT | IPC_SYSTEM | mode)) == -1) {		return(-1);	}	/* 	 * get the smem pointer, as it has just been allocated or 	 * retrieved, it must exist.	 */	if ((sp = smconv(smid, 0)) == NULL)		panic("vm_system_smget: invalid SMS");	/* if first time, then fill */	upte = sp->sm_ptaddr;	if (upte->pg_v == 0) {		num_ptes = btop(size);		spte = svtopte(sva);		while (num_ptes--) 			*(int *) (upte++) = 				PG_V | (*(int *) (spte++) & PG_PFNUM);		XPRINTF(XPR_SM,"vm_system_smget: first pte 0x%x *pte 0x%x",			sp->sm_ptaddr, *(int *) sp->sm_ptaddr,0,0);	}	return (smid);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -