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

📄 vm_smem.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
#ifndef lintstatic	char	*sccsid = "@(#)vm_smem.c	4.1	(ULTRIX)	7/2/90";#endif lint/*********************************************************************** *									* *			Copyright (c) 1986 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* **********************************************************************//* * *   Modification history: * * 14 Dec 87 -- jaa *	changed to use new kernel memory allocator *	wmemfree is not used anymore * * 29 Apr 86 -- depp *	converted to locking macros from calls routines * *	smlock/smunlock/smwait have are now macros SM_LOCK/SM_UNLOCK/SM_WAIT *	and are defined in /sys/h/vmmac.h * * 03 Jan 86 -- depp *	In "smfree" moved the call to smunlink, so that the memory is *	properly deallocated before the SMS is unlinked. * * 11 Nov 85 -- depp *	Removed all conditional compiles for System V IPC. * * 30 Sep 85 -- depp *	Added shared memory segment locking * * 19 Jul 85 -- depp *	Minor cleanup * * 11 Mar 85 -- depp		SHMEM *	1) - this file provides the virtual memory support for	 *		the shared memory IPC (uipc_smem.c). It is a	 *		direct analog of vm_text.c since the Ultrix	 *		design for shared memory segments is to handle	 *		them the same as shared text segments.		 *		LeRoy Fundingsland    1/16/85    DEC		 *								 */#ifdef vax#include "../vax/mtpr.h"#endif vax#ifdef mips#include "../machine/cpu.h"#endif mips#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 & smem.smpt.h */#include "../h/proc.h"#include "../h/seg.h"#include "../h/cmap.h"#include "../h/vm.h"#include "../h/map.h"#include "../h/kmalloc.h"#include "../h/ipc.h"#include "../h/shm.h"extern struct smem smem[];extern struct sminfo sminfo;extern smtot;/* SMFREE - relinquish use of the shared memory segment of a	*//*	process.						*/smfree(sp)    register struct smem *sp;	/* shared memory header ptr	*/{	register struct proc *p;	register int smsize;		/* in clicks		*/	register long a, npg;#ifdef mips	XPRINTF(XPR_SM,"enter smfree, sp = 0x%x",sp,0,0,0);#endif mips	if(sp == NULL)		return;	p = u.u_procp;	SM_LOCK(sp);	if(--sp->sm_count == 0  &&  (sp->sm_perm.mode & SM_DEST)){		smsize = clrnd((int)btoc(sp->sm_size));		/* free the memory for this SMS, if normal	*/		if ((sp->sm_perm.mode & IPC_SYSTEM) == 0) {			sp->sm_rssize -= vmemfree(sp->sm_ptaddr, smsize);			if(sp->sm_rssize != 0)				panic("smfree rssize");			while (sp->sm_poip)				sleep((caddr_t)&sp->sm_poip, PSWP+1);		}		smunlink(p, sp);		/* free the page table for this SMS	*/		a = btokmx((struct pte *) sp->sm_ptaddr);		npg = clrnd(btoc(sizeof(struct pte) * smsize));		(void) memfree(&Usrptmap[a], npg, KMF_NODETACH);		rmfree(kernelmap, (long)npg, (long)a);		/* free the swap space for this SMS, if normal	*/		if ((sp->sm_perm.mode & IPC_SYSTEM) == 0)			vssmfree(sp, (long)smsize);		smtot -= smsize;		sp->sm_perm.mode = 0;		sp->sm_perm.seq++;		if(((int)(sp->sm_perm.seq * sminfo.smmni + (sp - smem)))								< 0)			sp->sm_perm.seq = 0;		sp->sm_flag &= ~SMLOCK;	} else {		sp->sm_flag &= ~SMLOCK;		smccdec(sp, p);	}}/* SMCCDEC - shared memory core-count decrement. Decrement	*//*	the in-core usage count of a shared data segment. When	*//*	it drops to zero, free the core space.			*/smccdec(sp, p)    register struct smem *sp;    register struct proc *p;{	register int i, smsize;	register struct pte *pte;#ifdef mips	XPRINTF(XPR_SM,"enter smccdec: sp 0x%x p 0x%x",sp,p,0,0);#endif mips	if (sp == NULL  ||  sp->sm_ccount == 0)		return;	SM_LOCK(sp);	sp->sm_ccount--;	/*	 * 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.	 *	 * NOTE: This is not done for system/user sharing PTEs	 */	if ((sp->sm_perm.mode & IPC_SYSTEM) == 0) {#ifdef vax		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_spte;		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;		}#endif vax#ifdef mips		smsize = clrnd(btoc(sp->sm_size));#endif mips		if (sp->sm_ccount == 0 && !(sp->sm_flag & SMNOSW)) {#ifdef DEPPDEBUG			printf("SMS out; sp = 0x%x\n",sp);#endif DEPPDEBUG			vsswap(sp, sp->sm_ptaddr, CSMEM, 0, smsize,			       (struct dmap *)0);			if(sp->sm_rssize != 0)				panic("smccdec: rssize");		}	}	smunlink(p, sp);	SM_UNLOCK(sp);}/* SMLINK - Add a process to those sharing a shared memory	*//*	segment by getting the page tables and then linking to	*//*	sm_caddr.						*/smlink(p, sp)    register struct proc *p;    register struct smem *sp;{	register int smindex;#ifdef mips	XPRINTF(XPR_SM,"enter smlink: sp 0x%x p 0x%x",sp,p,0,0);#endif mips	if(p->p_sm == (struct p_sm *) NULL) {		panic("smlink: p_sm");	}	for(smindex=0; smindex < sminfo.smseg; smindex++)		if(p->p_sm[smindex].sm_p == sp)			break;	if(smindex >= sminfo.smseg)		panic("smlink");	/* cannot happen	*/			/* vinitsmpt() expects that the		*/			/* sm_spte and sm_pflag fields have	*/			/* already been set within the proper	*/			/* "p_sm" struct for this proc.		*/#ifdef vax	vinitsmpt(p, sp);#endif vax	p->p_sm[smindex].sm_link = sp->sm_caddr;	sp->sm_caddr = p;#ifdef DEPPDEBUG	if (sp->sm_ccount == 0)		printf("SMS in; sp = 0x%x\n ",sp);#endif DEPPDEBUG	sp->sm_ccount++;}/* SMUNLINK - unlink the given process from the linked list of	*//*	processes sharing the given shared memory segment.	*/smunlink(p, sp)    register struct proc *p;    register struct smem *sp;{	register struct proc *q;	register int p_smindex, q_smindex;#ifdef mips	XPRINTF(XPR_SM,"enter smunlink: sp 0x%x p 0x%x",sp,p,0,0);#endif mips	if (sp == NULL  ||  sp->sm_caddr == NULL)		return;	if(p->p_sm == (struct p_sm *) NULL) {		panic("smlink: p->p_sm");	}			/* find index of this shared memory	*/			/* seg for this process.		*/	for(p_smindex=0; p_smindex < sminfo.smseg; p_smindex++)		if(p->p_sm[p_smindex].sm_p == sp)			break;			/* return gracefully if not found	*/			/* because sp may not be attached when	*/			/* IPC_RMID is asserted.		*/	if(p_smindex >= sminfo.smseg)		return;			/* handle the special case where "p" is	*/			/* at the beginning of the linked list.	*/	if (sp->sm_caddr == p) {		sp->sm_caddr = p->p_sm[p_smindex].sm_link;		p->p_sm[p_smindex].sm_link = 0;		return;	}			/* now handle the general case		*/			/* find index of shared memory seg	*/			/* for first process in list.		*/	q = sp->sm_caddr;	if(q->p_sm == (struct p_sm *) NULL) {		panic("smlink: q->p_sm");	}	for(q_smindex=0; q_smindex < sminfo.smseg; q_smindex++)		if(q->p_sm[q_smindex].sm_p == sp)			break;	if(q_smindex >= sminfo.smseg)		panic("smunlink #1");	while(q->p_sm[q_smindex].sm_link){		if (q->p_sm[q_smindex].sm_link == p) {			q->p_sm[q_smindex].sm_link =					p->p_sm[p_smindex].sm_link;			p->p_sm[p_smindex].sm_link = 0;			return;		}			/* check next entry in linked list	*/		q = q->p_sm[q_smindex].sm_link;			/* find index of shared memory seg	*/			/* for this process.			*/		for(q_smindex=0; q_smindex < sminfo.smseg; q_smindex++)			if(q->p_sm[q_smindex].sm_p == sp)				break;		if(q_smindex >= sminfo.smseg)			panic("smunlink #2");	}	panic("lost shared memory");}/* SMREPL - Replace p by q in a shared memory incore linked	*//*	list. Used by vfork() (vpassvm()) internally.		*/smrepl(p, q, smindex)    register struct proc *p, *q;{	register struct smem *sp;#ifdef mips	XPRINTF(XPR_SM,"enter smlink: p 0x%x q 0x%x smindex %d",p,q,smindex,0);#endif mips	if((sp = q->p_sm[smindex].sm_p) == NULL)		return;	smunlink(p, sp);	q->p_sm[smindex].sm_link = sp->sm_caddr;	sp->sm_caddr = q;}/*  * 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);#ifdef vax	register struct pte *spte;#endif vax#ifdef mips	register int spfn;#endif mips	register struct pte *upte;	register struct smem *sp;	register int smid;	register int nocache;	extern struct smem *smconv();#ifdef mips	XPRINTF(XPR_SM,"enter vm_system_smget: sva 0x%x size %d mode %o",		sva, size, mode, 0);#endif mips#ifdef vax	if (((sva & VA_SPACE) != VA_SYS) || #endif vax#ifdef mips	if (IS_KUSEG(sva) ||#endif mips	    !isclbnd(sva) || !isclbnd(size) || (size < CLBYTES)) {		u.u_error = EINVAL;		return (-1);	}#ifdef vax	spte = svtopte(sva); 	while (num_ptes--) {		if ((spte++)->pg_v == 0) {			u.u_error = EINVAL;			return(-1);		}	}#endif vax	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);#ifdef vax		spte = svtopte(sva);		while (num_ptes--) 			*(int *) (upte++) = 				PG_V | (*(int *) (spte++) & PG_PFNUM);#endif vax#ifdef mips		if (IS_KSEG0(sva)) {			spfn = K0_TO_PHYS(sva) >> PGSHIFT;			nocache = 0;		}		else if (IS_KSEG1(sva)) {			spfn = K1_TO_PHYS(sva) >> PGSHIFT;			nocache = 1;		}		else if (IS_KSEG2(sva)) {			u.u_error = EINVAL;			return(-1);		} else {			u.u_error = EINVAL;			return(-1);		}		while (num_ptes--) {			upte->pg_v = 1;			upte->pg_m = 1;#ifdef NOMEMCACHE			upte->pg_n = 1;#else  NOMEMCACHE			upte->pg_n = nocache;#endif NOMEMCACHE			upte->pg_prot = PG_UW;			(upte++)->pg_pfnum = spfn++;		}#endif mips		XPRINTF(XPR_SM,"vm_system_smget: first pte 0x%x *pte 0x%x",			sp->sm_ptaddr, *(int *) sp->sm_ptaddr,0,0);	}	return (smid);}#ifdef mips/* * This routine will indicate whether the address is a shared memory segment * and return the segment index via the smindex variable. */sm_retrieve_sms(p, pn, smindex)struct proc *p;register int pn;int *smindex;{	register i;	register struct p_sm *psm = p->p_sm; /* pointer to proc's SMS struct */#ifdef notdef	XPRINTF(XPR_SM,"enter sm_retrieve_sms p 0x%x pn %d",		p,pn,0,0);#endif notdef	if (psm == (struct p_sm *) NULL) 		return(0);	for (i = 0; i < sminfo.smseg; i++, psm++) {		if (psm->sm_p == NULL)			continue;		if ((pn >= psm->sm_saddr) && (pn < psm->sm_eaddr)) {			*smindex = i;			return(1);		}	}	return (0);}/* * This routine will retrieve starting page number of the shared segment within *  the process' address space, given the proc pointer and the smem pointer. * * Since this routine is not called, unless the segment is attached to the  * process, success is guaranteed (or panic will result). */sm_retrieve_sa(p, sp)struct proc *p;struct smem *sp;{	register i;	register struct p_sm *psm = p->p_sm;	if (psm == (struct p_sm *) NULL)		panic ("sm_retrieve_sa: p_sm == (struct p_sm *) NULL");	for (i = 0; i < p->p_smcount; i++, psm++) {		if (sp == psm->sm_p)			return(psm->sm_saddr);	}	panic ("sm_retrieve_sa: Could not find SMS in proc");}#endif mips

⌨️ 快捷键说明

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