+++ /dev/null
-/*
- * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- * @OSF_COPYRIGHT@
- */
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989 Carnegie Mellon University
- * All Rights Reserved.
- *
- * 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 Mellon
- * the rights to redistribute these changes.
- */
-/*
- */
-
-/*
- * This module maintains information about the presence of
- * pages not in memory. Since an external memory object
- * must maintain a complete knowledge of its contents, this
- * information takes the form of hints.
- */
-#include <string.h> /* for memcpy()/memset() */
-
-#include <mach/boolean.h>
-#include <vm/vm_external.h>
-#include <kern/kalloc.h>
-#include <mach/vm_param.h>
-#include <kern/assert.h>
-
-/*
- * The implementation uses bit arrays to record whether
- * a page has been written to external storage. For
- * convenience, these bit arrays come in various sizes.
- * For example, a map N bytes long can record:
- *
- * 16 bytes = 128 pages = (@ 4KB/page) 512KB
- * 1024 bytes = 8192 pages = (@ 4KB/page) 32MB
- * 4096 bytes = 32768 pages = (@ 4KB/page) 128MB
- *
- * For a 32-bit machine with 4KB pages, the largest size
- * would be 128KB = 32 pages. Machines with a larger page
- * size are more efficient.
- *
- * This subsystem must be very careful about memory allocation,
- * since vm_external_create() is almost always called with
- * vm_privilege set. The largest map to be allocated must be less
- * than or equal to a single page, and the kalloc subsystem must
- * never allocate more than a single page in response to a kalloc()
- * request. Also, vm_external_destroy() must not take any blocking
- * locks, since it is called with a vm_object lock held. This
- * implies that kfree() MUST be implemented in terms of zfree()
- * NOT kmem_free() for all request sizes that this subsystem uses.
- *
- * For efficiency, this subsystem knows that the kalloc() subsystem
- * is implemented in terms of power-of-2 allocation, and that the
- * minimum allocation unit is KALLOC_MINSIZE
- *
- * XXXO
- * Should consider using existence_map to hold bits directly
- * when existence_size <= 4 bytes (i.e., 32 pages).
- */
-
-#define SMALL_SIZE KALLOC_MINSIZE
-#define LARGE_SIZE PAGE_SIZE
-
-static vm_object_size_t power_of_2(vm_object_size_t size);
-
-static vm_object_size_t
-power_of_2(vm_object_size_t size)
-{
- vm_object_size_t power;
-
- power = 2 * SMALL_SIZE;
- while (power < size) {
- power <<= 1;
- }
- return(power);
-}
-
-vm_external_map_t
-vm_external_create(
- vm_object_offset_t size)
-{
- vm_object_size_t bytes;
- vm_external_map_t result = VM_EXTERNAL_NULL;
-
- bytes = stob(size);
- if (bytes <= SMALL_SIZE) {
- result = (vm_external_map_t)kalloc(SMALL_SIZE);
- if (result != NULL) {
- memset(result, 0, SMALL_SIZE);
- }
- } else if (bytes <= LARGE_SIZE) {
- bytes = power_of_2(bytes);
-
- assert((vm_size_t) bytes == bytes);
- result = (vm_external_map_t)kalloc((vm_size_t)bytes);
- if (result != NULL) {
- assert((size_t) bytes == bytes);
- memset(result, 0, (size_t) bytes);
- }
- }
- return(result);
-}
-
-void
-vm_external_destroy(
- vm_external_map_t map,
- vm_object_size_t size)
-{
- vm_object_size_t bytes;
-
- if (map == VM_EXTERNAL_NULL)
- return;
-
- bytes = stob(size);
- if (bytes <= SMALL_SIZE) {
- bytes = SMALL_SIZE;
- } else {
- bytes = power_of_2(bytes);
- }
- assert((vm_size_t) bytes == bytes);
- kfree(map, (vm_size_t) bytes);
-}
-
-/*
- * Return the number of bytes needed for a vm_external_map given the
- * size of the object to be mapped, i.e. the size of the map that was
- * created by vm_external_create.
- */
-vm_object_size_t
-vm_external_map_size(
- vm_object_size_t size)
-{
- vm_object_size_t bytes;
-
- bytes = stob(size);
- if (bytes != 0) {
- if (bytes <= SMALL_SIZE) {
- bytes = SMALL_SIZE;
- } else {
- bytes = power_of_2(bytes);
- }
- }
- return bytes;
-}
-
-void
-vm_external_copy(
- vm_external_map_t old_map,
- vm_object_size_t old_size,
- vm_external_map_t new_map)
-{
- vm_object_size_t bytes;
-
- /*
- * Cannot copy non-existent maps
- */
- if ((old_map == VM_EXTERNAL_NULL) || (new_map == VM_EXTERNAL_NULL))
- return;
-
- /*
- * Copy old map to new
- */
- bytes = stob(old_size);
- assert((size_t) bytes == bytes);
- memcpy(new_map, old_map, (size_t) bytes);
-}
-
-boolean_t
-vm_external_within(
- vm_object_size_t new_size,
- vm_object_size_t old_size)
-{
- vm_object_size_t new_bytes;
- vm_object_size_t old_bytes;
-
- assert(new_size >= old_size);
-
- /*
- * "old_bytes" is calculated to be the actual amount of space
- * allocated for a map of size "old_size".
- */
- old_bytes = stob(old_size);
- if (old_bytes <= SMALL_SIZE) old_bytes = SMALL_SIZE;
- else if (old_bytes <= LARGE_SIZE) old_bytes = power_of_2(old_bytes);
-
- /*
- * "new_bytes" is the map size required to map the "new_size" object.
- * Since the rounding algorithms are the same, we needn't actually
- * round up new_bytes to get the correct answer
- */
- new_bytes = stob(new_size);
-
- return(new_bytes <= old_bytes);
-}
-
-vm_external_state_t
-_vm_external_state_get(
- vm_external_map_t map,
- vm_object_offset_t offset)
-{
- uint64_t bit, byte;
-
- assert (map != VM_EXTERNAL_NULL);
-
- bit = atop_64(offset);
- byte = bit >> 3;
- if (map[byte] & (1 << (bit & 07))) {
- return VM_EXTERNAL_STATE_EXISTS;
- } else {
- return VM_EXTERNAL_STATE_ABSENT;
- }
-}
-
-void
-vm_external_state_set(
- vm_external_map_t map,
- vm_object_offset_t offset)
-{
- uint64_t bit, byte;
-
- if (map == VM_EXTERNAL_NULL)
- return;
-
- bit = atop_64(offset);
- byte = bit >> 3;
- map[byte] |= (1 << (bit & 07));
-}
-
-void
-vm_external_state_clr(
- vm_external_map_t map,
- vm_object_offset_t offset)
-{
- uint64_t bit, byte;
-
- if (map == VM_EXTERNAL_NULL)
- return;
-
- bit = atop_64(offset);
- byte = bit >> 3;
- map[byte] &= ~(1 << (bit & 07));
-}
-
-void
-vm_external_module_initialize(void)
-{
-}