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

📄 vm_objec.c

📁 open bsd vm device design
💻 C
📖 第 1 页 / 共 3 页
字号:
						vm_page_activate(p);					else						vm_page_deactivate(p);					vm_page_unlock_queues();				}				p->flags &= ~PG_BUSY;				PAGE_WAKEUP(p);				goto again;			}		}	}	return (noerror);}/* *	vm_object_deactivate_pages * *	Deactivate all pages in the specified object.  (Keep its pages *	in memory even though it is no longer referenced.) * *	The object must be locked. */voidvm_object_deactivate_pages(object)	register vm_object_t	object;{	register vm_page_t	p, next;	for (p = object->memq.tqh_first; p != NULL; p = next) {		next = p->listq.tqe_next;		vm_page_lock_queues();		vm_page_deactivate(p);		vm_page_unlock_queues();	}}/* *	Trim the object cache to size. */voidvm_object_cache_trim(){	register vm_object_t	object;	vm_object_cache_lock();	while (vm_object_cached > vm_cache_max) {		object = vm_object_cached_list.tqh_first;		vm_object_cache_unlock();		if (object != vm_object_lookup(object->pager))			panic("vm_object_deactivate: I'm sooo confused.");		pager_cache(object, FALSE);		vm_object_cache_lock();	}	vm_object_cache_unlock();}/* *	vm_object_pmap_copy: * *	Makes all physical pages in the specified *	object range copy-on-write.  No writeable *	references to these pages should remain. * *	The object must *not* be locked. */voidvm_object_pmap_copy(object, start, end)	register vm_object_t	object;	register vm_offset_t	start;	register vm_offset_t	end;{	register vm_page_t	p;	if (object == NULL)		return;	vm_object_lock(object);	for (p = object->memq.tqh_first; p != NULL; p = p->listq.tqe_next) {		if ((start <= p->offset) && (p->offset < end)) {			pmap_page_protect(VM_PAGE_TO_PHYS(p), VM_PROT_READ);			p->flags |= PG_COPYONWRITE;		}	}	vm_object_unlock(object);}/* *	vm_object_pmap_remove: * *	Removes all physical pages in the specified *	object range from all physical maps. * *	The object must *not* be locked. */voidvm_object_pmap_remove(object, start, end)	register vm_object_t	object;	register vm_offset_t	start;	register vm_offset_t	end;{	register vm_page_t	p;	if (object == NULL)		return;	vm_object_lock(object);	for (p = object->memq.tqh_first; p != NULL; p = p->listq.tqe_next)		if ((start <= p->offset) && (p->offset < end))			pmap_page_protect(VM_PAGE_TO_PHYS(p), VM_PROT_NONE);	vm_object_unlock(object);}/* *	vm_object_copy: * *	Create a new object which is a copy of an existing *	object, and mark all of the pages in the existing *	object 'copy-on-write'.  The new object has one reference. *	Returns the new object. * *	May defer the copy until later if the object is not backed *	up by a non-default pager. */voidvm_object_copy(src_object, src_offset, size,		    dst_object, dst_offset, src_needs_copy)	register vm_object_t	src_object;	vm_offset_t		src_offset;	vm_size_t		size;	vm_object_t		*dst_object;	/* OUT */	vm_offset_t		*dst_offset;	/* OUT */	boolean_t		*src_needs_copy;	/* OUT */{	register vm_object_t	new_copy;	register vm_object_t	old_copy;	vm_offset_t		new_start, new_end;	register vm_page_t	p;	if (src_object == NULL) {		/*		 *	Nothing to copy		 */		*dst_object = NULL;		*dst_offset = 0;		*src_needs_copy = FALSE;		return;	}	/*	 *	If the object's pager is null_pager or the	 *	default pager, we don't have to make a copy	 *	of it.  Instead, we set the needs copy flag and	 *	make a shadow later.	 */	vm_object_lock(src_object);	if (src_object->pager == NULL ||	    (src_object->flags & OBJ_INTERNAL)) {		/*		 *	Make another reference to the object		 */		src_object->ref_count++;		/*		 *	Mark all of the pages copy-on-write.		 */		for (p = src_object->memq.tqh_first; p; p = p->listq.tqe_next)			if (src_offset <= p->offset &&			    p->offset < src_offset + size)				p->flags |= PG_COPYONWRITE;		vm_object_unlock(src_object);		*dst_object = src_object;		*dst_offset = src_offset;				/*		 *	Must make a shadow when write is desired		 */		*src_needs_copy = TRUE;		return;	}	/*	 *	Try to collapse the object before copying it.	 */	vm_object_collapse(src_object);	/*	 *	If the object has a pager, the pager wants to	 *	see all of the changes.  We need a copy-object	 *	for the changed pages.	 *	 *	If there is a copy-object, and it is empty,	 *	no changes have been made to the object since the	 *	copy-object was made.  We can use the same copy-	 *	object.	 */    Retry1:	old_copy = src_object->copy;	if (old_copy != NULL) {		/*		 *	Try to get the locks (out of order)		 */		if (!vm_object_lock_try(old_copy)) {			vm_object_unlock(src_object);			/* should spin a bit here... */			vm_object_lock(src_object);			goto Retry1;		}		if (old_copy->resident_page_count == 0 &&		    old_copy->pager == NULL) {			/*			 *	Return another reference to			 *	the existing copy-object.			 */			old_copy->ref_count++;			vm_object_unlock(old_copy);			vm_object_unlock(src_object);			*dst_object = old_copy;			*dst_offset = src_offset;			*src_needs_copy = FALSE;			return;		}		vm_object_unlock(old_copy);	}	vm_object_unlock(src_object);	/*	 *	If the object has a pager, the pager wants	 *	to see all of the changes.  We must make	 *	a copy-object and put the changed pages there.	 *	 *	The copy-object is always made large enough to	 *	completely shadow the original object, since	 *	it may have several users who want to shadow	 *	the original object at different points.	 */	new_copy = vm_object_allocate(src_object->size);    Retry2:	vm_object_lock(src_object);	/*	 *	Copy object may have changed while we were unlocked	 */	old_copy = src_object->copy;	if (old_copy != NULL) {		/*		 *	Try to get the locks (out of order)		 */		if (!vm_object_lock_try(old_copy)) {			vm_object_unlock(src_object);			goto Retry2;		}		/*		 *	Consistency check		 */		if (old_copy->shadow != src_object ||		    old_copy->shadow_offset != (vm_offset_t) 0)			panic("vm_object_copy: copy/shadow inconsistency");		/*		 *	Make the old copy-object shadow the new one.		 *	It will receive no more pages from the original		 *	object.		 */		src_object->ref_count--;	/* remove ref. from old_copy */		old_copy->shadow = new_copy;		new_copy->ref_count++;		/* locking not needed - we						   have the only pointer */		vm_object_unlock(old_copy);	/* done with old_copy */	}	new_start = (vm_offset_t) 0;	/* always shadow original at 0 */	new_end   = (vm_offset_t) new_copy->size; /* for the whole object */	/*	 *	Point the new copy at the existing object.	 */	new_copy->shadow = src_object;	new_copy->shadow_offset = new_start;	src_object->ref_count++;	src_object->copy = new_copy;	/*	 *	Mark all the affected pages of the existing object	 *	copy-on-write.	 */	for (p = src_object->memq.tqh_first; p != NULL; p = p->listq.tqe_next)		if ((new_start <= p->offset) && (p->offset < new_end))			p->flags |= PG_COPYONWRITE;	vm_object_unlock(src_object);	*dst_object = new_copy;	*dst_offset = src_offset - new_start;	*src_needs_copy = FALSE;}/* *	vm_object_shadow: * *	Create a new object which is backed by the *	specified existing object range.  The source *	object reference is deallocated. * *	The new object and offset into that object *	are returned in the source parameters. */voidvm_object_shadow(object, offset, length)	vm_object_t	*object;	/* IN/OUT */	vm_offset_t	*offset;	/* IN/OUT */	vm_size_t	length;{	register vm_object_t	source;	register vm_object_t	result;	source = *object;	/*	 *	Allocate a new object with the given length	 */	if ((result = vm_object_allocate(length)) == NULL)		panic("vm_object_shadow: no object for shadowing");	/*	 *	The new object shadows the source object, adding	 *	a reference to it.  Our caller changes his reference	 *	to point to the new object, removing a reference to	 *	the source object.  Net result: no change of reference	 *	count.	 */	result->shadow = source;		/*	 *	Store the offset into the source object,	 *	and fix up the offset into the new object.	 */	result->shadow_offset = *offset;	/*	 *	Return the new things	 */	*offset = 0;	*object = result;}/* *	Set the specified object's pager to the specified pager. */voidvm_object_setpager(object, pager, paging_offset,			read_only)	vm_object_t	object;	vm_pager_t	pager;	vm_offset_t	paging_offset;	boolean_t	read_only;{#ifdef	lint	read_only++;	/* No longer used */#endif	vm_object_lock(object);			/* XXX ? */	object->pager = pager;	object->paging_offset = paging_offset;	vm_object_unlock(object);			/* XXX ? */}/* *	vm_object_hash hashes the pager/id pair. */#define vm_object_hash(pager) \	(((unsigned long)pager)%VM_OBJECT_HASH_COUNT)/* *	vm_object_lookup looks in the object cache for an object with the *	specified pager and paging id. */vm_object_tvm_object_lookup(pager)	vm_pager_t	pager;{	register vm_object_hash_entry_t	entry;	vm_object_t			object;	vm_object_cache_lock();	for (entry = vm_object_hashtable[vm_object_hash(pager)].tqh_first;	     entry != NULL;	     entry = entry->hash_links.tqe_next) {		object = entry->object;		if (object->pager == pager) {			vm_object_lock(object);			if (object->ref_count == 0) {				TAILQ_REMOVE(&vm_object_cached_list, object,					cached_list);				vm_object_cached--;			}			object->ref_count++;			vm_object_unlock(object);			vm_object_cache_unlock();			return(object);		}	}	vm_object_cache_unlock();	return(NULL);}/* *	vm_object_enter enters the specified object/pager/id into *	the hash table. */voidvm_object_enter(object, pager)	vm_object_t	object;	vm_pager_t	pager;{	struct vm_object_hash_head	*bucket;	register vm_object_hash_entry_t	entry;	/*	 *	We don't cache null objects, and we can't cache	 *	objects with the null pager.	 */	if (object == NULL)		return;	if (pager == NULL)		return;	bucket = &vm_object_hashtable[vm_object_hash(pager)];	entry = (vm_object_hash_entry_t)		malloc((u_long)sizeof *entry, M_VMOBJHASH, M_WAITOK);	entry->object = object;	object->flags |= OBJ_CANPERSIST;	vm_object_cache_lock();	TAILQ_INSERT_TAIL(bucket, entry, hash_links);	vm_object_cache_unlock();}/* *	vm_object_remove: * *	Remove the pager from the hash table. *	Note:  This assumes that the object cache *	is locked.  XXX this should be fixed *	by reorganizing vm_object_deallocate. */voidvm_object_remove(pager)	register vm_pager_t	pager;{	struct vm_object_hash_head	*bucket;	register vm_object_hash_entry_t	entry;	register vm_object_t		object;	bucket = &vm_object_hashtable[vm_object_hash(pager)];	for (entry = bucket->tqh_first;	     entry != NULL;	     entry = entry->hash_links.tqe_next) {		object = entry->object;

⌨️ 快捷键说明

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