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

📄 vm_objec.c

📁 open bsd vm device design
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  * Copyright (c) 1991, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)vm_object.c	8.7 (Berkeley) 5/11/95 * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. * * Authors: Avadis Tevanian, Jr., Michael Wayne Young *  * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. *  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. *  * Carnegie Mellon requests users of this software to return to * *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU *  School of Computer Science *  Carnegie Mellon University *  Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. *//* *	Virtual memory object module. */#include <sys/param.h>#include <sys/systm.h>#include <sys/malloc.h>#include <vm/vm.h>#include <vm/vm_page.h>/* *	Virtual memory objects maintain the actual data *	associated with allocated virtual memory.  A given *	page of memory exists within exactly one object. * *	An object is only deallocated when all "references" *	are given up.  Only one "reference" to a given *	region of an object should be writeable. * *	Associated with each object is a list of all resident *	memory pages belonging to that object; this list is *	maintained by the "vm_page" module, and locked by the object's *	lock. * *	Each object also records a "pager" routine which is *	used to retrieve (and store) pages to the proper backing *	storage.  In addition, objects may be backed by other *	objects from which they were virtual-copied. * *	The only items within the object structure which are *	modified after time of creation are: *		reference count		locked by object's lock *		pager routine		locked by object's lock * */struct vm_object	kernel_object_store;struct vm_object	kmem_object_store;#define	VM_OBJECT_HASH_COUNT	157int	vm_cache_max = 100;	/* can patch if necessary */struct	vm_object_hash_head vm_object_hashtable[VM_OBJECT_HASH_COUNT];long	object_collapses = 0;long	object_bypasses  = 0;static void _vm_object_allocate __P((vm_size_t, vm_object_t));/* *	vm_object_init: * *	Initialize the VM objects module. */voidvm_object_init(size)	vm_size_t	size;{	register int	i;	TAILQ_INIT(&vm_object_cached_list);	TAILQ_INIT(&vm_object_list);	vm_object_count = 0;	simple_lock_init(&vm_cache_lock);	simple_lock_init(&vm_object_list_lock);	for (i = 0; i < VM_OBJECT_HASH_COUNT; i++)		TAILQ_INIT(&vm_object_hashtable[i]);	kernel_object = &kernel_object_store;	_vm_object_allocate(size, kernel_object);	kmem_object = &kmem_object_store;	_vm_object_allocate(VM_KMEM_SIZE + VM_MBUF_SIZE, kmem_object);}/* *	vm_object_allocate: * *	Returns a new object with the given size. */vm_object_tvm_object_allocate(size)	vm_size_t	size;{	register vm_object_t	result;	result = (vm_object_t)		malloc((u_long)sizeof *result, M_VMOBJ, M_WAITOK);	_vm_object_allocate(size, result);	return(result);}static void_vm_object_allocate(size, object)	vm_size_t		size;	register vm_object_t	object;{	TAILQ_INIT(&object->memq);	vm_object_lock_init(object);	object->ref_count = 1;	object->resident_page_count = 0;	object->size = size;	object->flags = OBJ_INTERNAL;	/* vm_allocate_with_pager will reset */	object->paging_in_progress = 0;	object->copy = NULL;	/*	 *	Object starts out read-write, with no pager.	 */	object->pager = NULL;	object->paging_offset = 0;	object->shadow = NULL;	object->shadow_offset = (vm_offset_t) 0;	simple_lock(&vm_object_list_lock);	TAILQ_INSERT_TAIL(&vm_object_list, object, object_list);	vm_object_count++;	cnt.v_nzfod += atop(size);	simple_unlock(&vm_object_list_lock);}/* *	vm_object_reference: * *	Gets another reference to the given object. */voidvm_object_reference(object)	register vm_object_t	object;{	if (object == NULL)		return;	vm_object_lock(object);	object->ref_count++;	vm_object_unlock(object);}/* *	vm_object_deallocate: * *	Release a reference to the specified object, *	gained either through a vm_object_allocate *	or a vm_object_reference call.  When all references *	are gone, storage associated with this object *	may be relinquished. * *	No object may be locked. */voidvm_object_deallocate(object)	register vm_object_t	object;{	vm_object_t	temp;	while (object != NULL) {		/*		 *	The cache holds a reference (uncounted) to		 *	the object; we must lock it before removing		 *	the object.		 */		vm_object_cache_lock();		/*		 *	Lose the reference		 */		vm_object_lock(object);		if (--(object->ref_count) != 0) {			/*			 *	If there are still references, then			 *	we are done.			 */			vm_object_unlock(object);			vm_object_cache_unlock();			return;		}		/*		 *	See if this object can persist.  If so, enter		 *	it in the cache, then deactivate all of its		 *	pages.		 */		if (object->flags & OBJ_CANPERSIST) {			TAILQ_INSERT_TAIL(&vm_object_cached_list, object,				cached_list);			vm_object_cached++;			vm_object_cache_unlock();			vm_object_deactivate_pages(object);			vm_object_unlock(object);			vm_object_cache_trim();			return;		}		/*		 *	Make sure no one can look us up now.		 */		vm_object_remove(object->pager);		vm_object_cache_unlock();		temp = object->shadow;		vm_object_terminate(object);			/* unlocks and deallocates object */		object = temp;	}}/* *	vm_object_terminate actually destroys the specified object, freeing *	up all previously used resources. * *	The object must be locked. */voidvm_object_terminate(object)	register vm_object_t	object;{	register vm_page_t	p;	vm_object_t		shadow_object;	/*	 *	Detach the object from its shadow if we are the shadow's	 *	copy.	 */	if ((shadow_object = object->shadow) != NULL) {		vm_object_lock(shadow_object);		if (shadow_object->copy == object)			shadow_object->copy = NULL;#if 0		else if (shadow_object->copy != NULL)			panic("vm_object_terminate: copy/shadow inconsistency");#endif		vm_object_unlock(shadow_object);	}	/*	 * Wait until the pageout daemon is through with the object.	 */	while (object->paging_in_progress) {		vm_object_sleep(object, object, FALSE);		vm_object_lock(object);	}	/*	 * If not an internal object clean all the pages, removing them	 * from paging queues as we go.	 *	 * XXX need to do something in the event of a cleaning error.	 */	if ((object->flags & OBJ_INTERNAL) == 0)		(void) vm_object_page_clean(object, 0, 0, TRUE, TRUE);	/*	 * Now free the pages.	 * For internal objects, this also removes them from paging queues.	 */	while ((p = object->memq.tqh_first) != NULL) {		VM_PAGE_CHECK(p);		vm_page_lock_queues();		vm_page_free(p);		cnt.v_pfree++;		vm_page_unlock_queues();	}	vm_object_unlock(object);	/*	 * Let the pager know object is dead.	 */	if (object->pager != NULL)		vm_pager_deallocate(object->pager);	simple_lock(&vm_object_list_lock);	TAILQ_REMOVE(&vm_object_list, object, object_list);	vm_object_count--;	simple_unlock(&vm_object_list_lock);	/*	 * Free the space for the object.	 */	free((caddr_t)object, M_VMOBJ);}/* *	vm_object_page_clean * *	Clean all dirty pages in the specified range of object. *	If syncio is TRUE, page cleaning is done synchronously. *	If de_queue is TRUE, pages are removed from any paging queue *	they were on, otherwise they are left on whatever queue they *	were on before the cleaning operation began. * *	Odd semantics: if start == end, we clean everything. * *	The object must be locked. * *	Returns TRUE if all was well, FALSE if there was a pager error *	somewhere.  We attempt to clean (and dequeue) all pages regardless *	of where an error occurs. */boolean_tvm_object_page_clean(object, start, end, syncio, de_queue)	register vm_object_t	object;	register vm_offset_t	start;	register vm_offset_t	end;	boolean_t		syncio;	boolean_t		de_queue;{	register vm_page_t	p;	int onqueue;	boolean_t noerror = TRUE;	if (object == NULL)		return (TRUE);	/*	 * If it is an internal object and there is no pager, attempt to	 * allocate one.  Note that vm_object_collapse may relocate one	 * from a collapsed object so we must recheck afterward.	 */	if ((object->flags & OBJ_INTERNAL) && object->pager == NULL) {		vm_object_collapse(object);		if (object->pager == NULL) {			vm_pager_t pager;			vm_object_unlock(object);			pager = vm_pager_allocate(PG_DFLT, (caddr_t)0,						  object->size, VM_PROT_ALL,						  (vm_offset_t)0);			if (pager)				vm_object_setpager(object, pager, 0, FALSE);			vm_object_lock(object);		}	}	if (object->pager == NULL)		return (FALSE);again:	/*	 * Wait until the pageout daemon is through with the object.	 */	while (object->paging_in_progress) {		vm_object_sleep(object, object, FALSE);		vm_object_lock(object);	}	/*	 * Loop through the object page list cleaning as necessary.	 */	for (p = object->memq.tqh_first; p != NULL; p = p->listq.tqe_next) {		if ((start == end || p->offset >= start && p->offset < end) &&		    !(p->flags & PG_FICTITIOUS)) {			if ((p->flags & PG_CLEAN) &&			    pmap_is_modified(VM_PAGE_TO_PHYS(p)))				p->flags &= ~PG_CLEAN;			/*			 * Remove the page from any paging queue.			 * This needs to be done if either we have been			 * explicitly asked to do so or it is about to			 * be cleaned (see comment below).			 */			if (de_queue || !(p->flags & PG_CLEAN)) {				vm_page_lock_queues();				if (p->flags & PG_ACTIVE) {					TAILQ_REMOVE(&vm_page_queue_active,						     p, pageq);					p->flags &= ~PG_ACTIVE;					cnt.v_active_count--;					onqueue = 1;				} else if (p->flags & PG_INACTIVE) {					TAILQ_REMOVE(&vm_page_queue_inactive,						     p, pageq);					p->flags &= ~PG_INACTIVE;					cnt.v_inactive_count--;					onqueue = -1;				} else					onqueue = 0;				vm_page_unlock_queues();			}			/*			 * To ensure the state of the page doesn't change			 * during the clean operation we do two things.			 * First we set the busy bit and write-protect all			 * mappings to ensure that write accesses to the			 * page block (in vm_fault).  Second, we remove			 * the page from any paging queue to foil the			 * pageout daemon (vm_pageout_scan).			 */			pmap_page_protect(VM_PAGE_TO_PHYS(p), VM_PROT_READ);			if (!(p->flags & PG_CLEAN)) {				p->flags |= PG_BUSY;				object->paging_in_progress++;				vm_object_unlock(object);				/*				 * XXX if put fails we mark the page as				 * clean to avoid an infinite loop.				 * Will loose changes to the page.				 */				if (vm_pager_put(object->pager, p, syncio)) {					printf("%s: pager_put error\n",					       "vm_object_page_clean");					p->flags |= PG_CLEAN;					noerror = FALSE;				}				vm_object_lock(object);				object->paging_in_progress--;				if (!de_queue && onqueue) {					vm_page_lock_queues();					if (onqueue > 0)

⌨️ 快捷键说明

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