It is accomplished ...
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
static void init_pdentry(pdentry *e)
|
||||
Sets e's value to 0.
|
||||
|
||||
static void init_ptentry(ptentry *e)
|
||||
Sets e's value to 0.
|
||||
|
||||
static void _update_all_pgdirs(int index, pdentry e)
|
||||
For every entry in the translation map, set the index'th entry to e.
|
||||
|
||||
static int lock_tmap(vm_translation_map *map)
|
||||
Locks the map; if we are the only ones, sets invalidated page count to 0.
|
||||
|
||||
static int unlock_tmap(vm_translation_map *map)
|
||||
unlocks the map; if no one else has it, call flush_tmap
|
||||
|
||||
static void destroy_tmap(vm_translation_map *map)
|
||||
Iterate over the entries in the tmap list, removing map when found. Frees the pages associated with this map.
|
||||
|
||||
static void put_pgtable_in_pgdir(pdentry *e, addr pgtable_phys, int attributes)
|
||||
Populates the pdentry with pgtable_phys and attributes
|
||||
|
||||
static int map_tmap(vm_translation_map *map, addr va, addr pa, unsigned int attributes)
|
||||
Allocates, if necessary, a page table entry. Gets the page for the page table entry (new or not), populates the page tabel entry with pa and attributes. Puts back the page table entry. Updates the pages to invalidate list.
|
||||
|
||||
static int unmap_tmap(vm_translation_map *map, addr start, addr end)
|
||||
Loops over the pagetable, finding the page that is present that holds this address. Gets it, and marks the page as not present. Replaces the page and updates the pages to invalidate list.
|
||||
|
||||
static int query_tmap(vm_translation_map *map, addr va, addr *out_physical, unsigned int *out_flags)
|
||||
Finds the page table's entry for this virtual address. Returns the physical address and flags.
|
||||
|
||||
static addr get_mapped_size_tmap(vm_translation_map *map)
|
||||
Returns map_count.
|
||||
|
||||
static int protect_tmap(vm_translation_map *map, addr base, addr top, unsigned int attributes)
|
||||
Unimplemented.
|
||||
|
||||
static int clear_flags_tmap(vm_translation_map *map, addr va, unsigned int flags)
|
||||
Finds the PTE and clears the requested flags.
|
||||
|
||||
static void flush_tmap(vm_translation_map *map)
|
||||
Invalidates the TLBs. If too many are in the list, all of the TLBs are invalidated. If not, a list is invalidated.
|
||||
|
||||
static int map_iospace_chunk(addr va, addr pa)
|
||||
Creates 1024 page table entries, for io.
|
||||
|
||||
static int get_physical_page_tmap(addr pa, addr *va, int flags)
|
||||
Looks to see if pa is already mapped. If so, return its virtual address in va. If not, find a place to map it and do so.
|
||||
|
||||
static int put_physical_page_tmap(addr va)
|
||||
Releases a reference to a "checked out" virtual mapping
|
||||
|
||||
int vm_translation_map_create(vm_translation_map *new_map, bool kernel)
|
||||
Sets up new_map, allocating memory and setting its initial state.
|
||||
|
||||
int vm_translation_map_module_init(kernel_args *ka)
|
||||
Clears the bottom 2 gig of memory's page mapping. Allocates space for page maps. Initializes data structures. Puts the page tables in the kernel's pagedir.
|
||||
|
||||
void vm_translation_map_module_init_post_sem(kernel_args *ka)
|
||||
Initializes this module's semaphores and mutexes.
|
||||
|
||||
int vm_translation_map_module_init2(kernel_args *ka)
|
||||
Creates anonymous regions for the kernel pagedir, physical page mappings, iospaces' virtual chunk descriptors and iospaces' page tables. Creates a null region for iospace.
|
||||
|
||||
int vm_translation_map_quick_map(kernel_args *ka, addr va, addr pa, unsigned int attributes, addr (get_free_page)(kernel_args *))
|
||||
Maps a page, ignoring already set up info.
|
||||
|
||||
static int vm_translation_map_quick_query(addr va, addr *out_physical)
|
||||
Gets the physical address for a page.
|
||||
|
||||
addr vm_translation_map_get_pgdir(vm_translation_map *map)
|
||||
Returns the pagedirectory structure.
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
int arch_vm_init (kernel_args *ka)
|
||||
First round of initialization; does nothing.
|
||||
|
||||
int arch_vm_init2 (kernel_args *ka)
|
||||
Marks the bios and dma ranges as "in use".
|
||||
|
||||
int arch_vm_init_endvm (kernel_args *ka)
|
||||
Maps the dma region into kernel space
|
||||
|
||||
void arch_vm_aspace_swap(vm_address_space *aspace)
|
||||
Calls i386_swap_pgdir
|
||||
@@ -0,0 +1,210 @@
|
||||
Variables
|
||||
|
||||
static vm_address_space *kernel_aspace;
|
||||
static region_id next_region_id;
|
||||
static void *region_table;
|
||||
static sem_id region_hash_sem;
|
||||
static aspace_id next_aspace_id;
|
||||
static void *aspace_table;
|
||||
static sem_id aspace_hash_sem;
|
||||
static int max_commit;
|
||||
static spinlock_t max_commit_lock;
|
||||
|
||||
Functions
|
||||
|
||||
static int region_compare(void *_r, const void *key)
|
||||
Compares _r (a vm_region) to key to see if their id's are the same. If so, return 0, else return -1
|
||||
|
||||
static unsigned int region_hash(void *_r, const void *key, unsigned int range)
|
||||
If _r is null, return key (a region_id) mod range, else return _r's id mod range.
|
||||
|
||||
static int aspace_compare(void *_a, const void *key)
|
||||
Compares _a (an address space) to key to see if their id's are the same. If so, return 0, else return -1
|
||||
|
||||
static unsigned int aspace_hash(void *_a, const void *key, unsigned int range)
|
||||
If _a is null, return key (an aspace_id) mod range, else return _a's id mod range.
|
||||
|
||||
vm_address_space *vm_get_aspace_by_id(aspace_id aid)
|
||||
Does a hash lookup on aid to find a vm_address_space struct. Increments its reference count and returns it.
|
||||
|
||||
vm_region *vm_get_region_by_id(region_id rid)
|
||||
Does a hash lookup on rid to find a vm_region. Increments its reference count and returns it.
|
||||
|
||||
region_id vm_find_region_by_name(aspace_id aid, const char *name)
|
||||
Finds this address space's structure. Iterates over the region list, looking for a match for name. vm_put_aspace's the address space.
|
||||
|
||||
static vm_region *_vm_create_region_struct(vm_address_space *aspace, const char *name, int wiring, int lock)
|
||||
Allocates space for a region and its name. Populates the name. Gets a new region id and assigns it. Sets map to the address space's virtual map.
|
||||
|
||||
static int find_and_insert_region_slot(vm_virtual_map *map, addr start, addr size, addr end, int addr_type, vm_region *region)
|
||||
Loops over the map's region list until it finds where this region should be inserted. If addr_type is any address, find any spot where it will fit and set the region up to start at the end of the previous one + 1. If we are searching for an exact address, see if that area is free and if so, use it. Increment map's change count.
|
||||
|
||||
|
||||
static int map_backing_store(vm_address_space *aspace, vm_store *store, void **vaddr,off_t offset, addr size, int addr_type, int wiring, int lock, int mapping, vm_region **_region, const char *region_name)
|
||||
Creates a region structure for this address space, name, wiring and lock. If this is a private map, create a new store, cache and cache_ref for private copies of pages. If the store's commited size is too small, ask the store to attempt to commit more. Aquire a reference to the cache_ref. Ensure that no one is deleting this address space; if they are, exit with an error. Insert this region into the address space. Attaches the cache to the region. Inserts the region into the region hash table. Adds a reference to the address space. Releases the cache_ref reference.
|
||||
|
||||
region_id user_vm_create_anonymous_region(char *uname, void **uaddress, int addr_type, addr size, int wiring, int lock)
|
||||
Does some safety checking, copies the name and address to kernel space, calls vm_create_anonymous_region, then copies the return result to uaddress.
|
||||
|
||||
region_id vm_create_anonymous_region(aspace_id aid, char *name, void **address, int addr_type, addr size, int wiring, int lock)
|
||||
Gets the address space structure. Creates an anonymous store object, a (temporary) cache and a cache_ref. Acquires a ref to the cache_ref. Calls map_backing_store for this address and size. Releases the cache_ref. If wiring is lazy, do nothing. If wiring is wired, calls soft_fault to simulate a fault and force the mapping to occur. If the wiring is "wired already", i.e. we cheated at boot time to make this happen, then find the pages and call vm_cache_insert_page to insert the pages into the cache. If the wiring is contiguous, allocate the pages and put them into the cache.
|
||||
|
||||
|
||||
region_id vm_map_physical_memory(aspace_id aid, char *name, void **address, int addr_type, addr size, int lock, addr phys_addr)
|
||||
Get the address space structure. Create a device store object, a cache and a cache_ref. Acquire a reference for the cache_ref. map backing store to this space and size. release the reference to the cache_ref.
|
||||
|
||||
region_id vm_create_null_region(aspace_id aid, char *name, void **address, int addr_type, addr size)
|
||||
Get the address space structure. Create a null store object, a cache and a cache_ref. Acquire a reference for the cache_ref. map backing store to this space and size. release the reference to the cache_ref.
|
||||
|
||||
static region_id _vm_map_file(aspace_id aid, char *name, void **address, int addr_type,addr size, int lock, int mapping, const char *path, off_t offset, bool kernel)
|
||||
Get the address space structure. Get the vnode from the path. If this cache doesn't already exist:
|
||||
create a vnode store object, a cache and a cache_ref. Acquire a reference for the cache_ref. set the cache_ptr to this cache_ref, and keep retrying until it works. release the reference to the cache_ref.
|
||||
Acquire a ref to the cache_ref. map backing store, release the ref and put the address space.
|
||||
|
||||
region_id vm_map_file(aspace_id aid, char *name, void **address, int addr_type, addr size, int lock, int mapping, const char *path, off_t offset)
|
||||
Convenience function - calls _vm_map_file with a kernel param of true.
|
||||
|
||||
region_id user_vm_map_file(char *uname, void **uaddress, int addr_type, addr size, int lock, int mapping, const char *upath, off_t offset)
|
||||
Sanity checks the name, address and path. Copies those into kernel space and calls _vm_map_file with a kernel param of false.
|
||||
|
||||
region_id user_vm_clone_region(char *uname, void **uaddress, int addr_type, region_id source_region, int mapping, int lock)
|
||||
Sanity checks the name and address. Copies those into kernel space and calls vm_clone_region.
|
||||
|
||||
region_id vm_clone_region(aspace_id aid, char *name, void **address, int addr_type, region_id source_region, int mapping, int lock)
|
||||
Gets the address space and region structures. maps backing store and returns.
|
||||
|
||||
static int __vm_delete_region(vm_address_space *aspace, vm_region *region)
|
||||
If the region's address space matches aspace, put_region it.
|
||||
|
||||
static int _vm_delete_region(vm_address_space *aspace, region_id rid)
|
||||
Gets the region, calls __vm_delete_region, then puts the region.
|
||||
|
||||
int vm_delete_region(aspace_id aid, region_id rid)
|
||||
Gets the address space. Calls _vm_delete_region, puts the address space and returns.
|
||||
|
||||
static void _vm_put_region(vm_region *region, bool aspace_locked)
|
||||
Check to see if there are still references to this region. If not, remove it from the global list and return. Remove the region from the adress space's region list. Remove the region from the vm_cache. Unmap it from the translation map.
|
||||
|
||||
void vm_put_region(vm_region *region)
|
||||
Calls _vm_put_region with locked=false.
|
||||
|
||||
int user_vm_get_region_info(region_id id, vm_region_info *uinfo)
|
||||
Calls vm_get_region_info after sanity checking the vm_region_info pointer.
|
||||
|
||||
int vm_get_region_info(region_id id, vm_region_info *info)
|
||||
Fills in the vm_region_info structure with id, base, size, lock, wiring and name.
|
||||
|
||||
int vm_get_page_mapping(aspace_id aid, addr vaddr, addr *paddr)
|
||||
Returns a physical address, given a virtual one.
|
||||
|
||||
static void display_mem(int argc, char **argv)
|
||||
Displays a value in memory.
|
||||
|
||||
static void dump_cache_ref(int argc, char **argv)
|
||||
Dumps a cache ref to debugging terminal
|
||||
|
||||
static const char *page_state_to_text(int state)
|
||||
Converts a state enum to a descriptive string.
|
||||
|
||||
static void dump_cache(int argc, char **argv)
|
||||
Dumps a particular cache entry.
|
||||
|
||||
static void _dump_region(vm_region *region)
|
||||
Dumps a particular region
|
||||
|
||||
static void dump_region(int argc, char **argv)
|
||||
Finds region by id and dumps it.
|
||||
|
||||
static void dump_region_list(int argc, char **argv)
|
||||
Dumps info about every region.
|
||||
|
||||
static void _dump_aspace(vm_address_space *aspace)
|
||||
Dumps data about an address space.
|
||||
|
||||
static void dump_aspace(int argc, char **argv)
|
||||
Finds an address space by ID and dumps it.
|
||||
|
||||
static void dump_aspace_list(int argc, char **argv)
|
||||
Dumps data about every address space.
|
||||
|
||||
vm_address_space *vm_get_kernel_aspace(void)
|
||||
Returns a pointer to the kernel address space structure.
|
||||
|
||||
aspace_id vm_get_kernel_aspace_id(void)
|
||||
Returns the kernel's address space id.
|
||||
|
||||
vm_address_space *vm_get_current_user_aspace(void)
|
||||
Gets the current user address space, given an id.
|
||||
|
||||
aspace_id vm_get_current_user_aspace_id(void)
|
||||
Uses the thread structure to get the current address space id.
|
||||
|
||||
void vm_put_aspace(vm_address_space *aspace)
|
||||
Removes a reference to the adress space. If it is the last one, destory the aspace.
|
||||
|
||||
aspace_id vm_create_aspace(const char *name, addr base, addr size, bool kernel)
|
||||
Allocate space for the structure and the name. Set default state. Creates a translation map. Initializes the virtual map and adds the structure to the global address space list.
|
||||
|
||||
int vm_delete_aspace(aspace_id aid)
|
||||
Gets the aspace struct from the id. If someone is already deleting, bail out. Put all of the regions, and put the aspace twice to cause it to be deleted.
|
||||
|
||||
int vm_aspace_walk_start(struct hash_iterator *i)
|
||||
calls open_hash on the aspace table.
|
||||
|
||||
vm_address_space *vm_aspace_walk_next(struct hash_iterator *i)
|
||||
Get the next address space in the hash list.
|
||||
|
||||
static int vm_thread_dump_max_commit(void *unused)
|
||||
Calls the unused function, then loops forever, printing the max_commit changes. Weird.
|
||||
|
||||
int vm_init(kernel_args *ka)
|
||||
Calls translation_map_module_init, and arch_vm_init. Initializes its globals, maps in the new heap and initializes it. Initializes the page list and the cache list. Creates the region and address space hash maps. Creates the kernel address space. Calls arch_vm_init2 and vm_page_init2. Allocates vm space for the stuff that the boot loader already had (heap, kernel read only, kernel read write, bootdir and the kstacks. Calls arch_vm_init_endvm. Adds commands to the debugger.
|
||||
|
||||
int vm_init_postsem(kernel_args *ka)
|
||||
Calls vm_translation_map_module_init_post_sem, creates the vm locking semaphores, and calls heap_init_postsem.
|
||||
|
||||
int vm_init_postthread(kernel_args *ka)
|
||||
Creates a max_commit_thread, calling vm_thread_dump_max_commit.
|
||||
|
||||
int vm_page_fault(addr address, addr fault_address, bool is_write, bool is_user, addr *newip)
|
||||
Calls vm_soft_fault. If that fails then checks to see if there is a fault handler for this case. If so, ensures that it is called. If there is no such case, kernel_panic (is this a good thing?)
|
||||
|
||||
static int vm_soft_fault(addr address, bool is_write, bool is_user)
|
||||
Sanity checks the address, determining if it is kernel or user land and getting the appropriate address space. Looks up the region from the aspace's map and the address. On failure, fail. Checks permissions. Finds the regions's cache ref; if there is a fault function for that cache_ref, invoke it and return with the error that the fault function returns.
|
||||
Otherwise, iterates over the cache chain:
|
||||
If the page is found in the current cache, set that page as busy and stop iterating.
|
||||
Otherwise, insert a dummy page in this cache (to keep other threads of the same process from chasing us in fault land)
|
||||
See if this cache's store has a "has_page" function. If so, call it. If it finds the page (meaning that the page is in this cache's storage), allocate a new physical page, read the data into the page and stop iterating.
|
||||
If we didn't find a cache, pick one (if we are in write mode, the top, if not, the deepest cache).
|
||||
If we don't have a page at this point, make a new one and insert it into the cache. Replace the dummy page, if any, with our new page.
|
||||
If this is a writable page and we are not in the topmost cache, we need another physical page for writes. Find the original page and copy it to the new page. Replace the dummy page, if any, with our new page.
|
||||
Ensure that the address region is still legit.
|
||||
Map the new page into the address space.
|
||||
Replace the dummy page, if any, with our new page.
|
||||
Set the page to active. Release all locks.
|
||||
|
||||
|
||||
static vm_region *vm_virtual_map_lookup(vm_virtual_map *map, addr address)
|
||||
Walk the region list of this map, looking for a region containing this address and return it.
|
||||
|
||||
int vm_get_physical_page(addr paddr, addr *vaddr, int flags)
|
||||
Get the physical page for this virtual address.
|
||||
|
||||
int vm_put_physical_page(addr vaddr)
|
||||
Put the physical page for this virtual address.
|
||||
|
||||
void vm_increase_max_commit(addr delta)
|
||||
Lock everything, increase max_commit, then unlock everything.
|
||||
|
||||
int user_memcpy(void *to, const void *from, size_t size)
|
||||
Calls the arch_ version.
|
||||
|
||||
int user_strcpy(char *to, const char *from)
|
||||
Calls the arch_ version.
|
||||
|
||||
int user_strncpy(char *to, const char *from, size_t size)
|
||||
Calls the arch_ version.
|
||||
|
||||
int user_memset(void *s, char c, size_t count)
|
||||
Calls the arch_ version.
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
Variables
|
||||
static void *page_cache_table
|
||||
|
||||
static spinlock_t page_cache_table_lock
|
||||
|
||||
static int page_compare_func(void *_p, const void *_key)
|
||||
Compares a vm_page's cache_ref and offset to those of key. Returns 0 on match, -1 otherwise.
|
||||
|
||||
static unsigned int page_hash_func(void *_p, const void *_key, unsigned int range)
|
||||
If p is not null, use it otherwise use key; computes a hash value for offset and reference.
|
||||
|
||||
int vm_cache_init(kernel_args *ka)
|
||||
Calls hash_init, sets page_cache_table_lock to unlocked and returns 0.
|
||||
|
||||
vm_cache *vm_cache_create(vm_store *store)
|
||||
Allocates a vm_cache structure and populates with 0's and NULLs (except for store).
|
||||
|
||||
vm_cache_ref *vm_cache_ref_create(vm_cache *cache)
|
||||
Allocates a vm_cache_ref, setting it to point to the passed in cache. It initalizes the references lock and returns.
|
||||
|
||||
void vm_cache_acquire_ref(vm_cache_ref *cache_ref, bool acquire_store_ref)
|
||||
If the cache_ref is null, panic. Otherwise, if we are to aquire a reference and there is an aquire reference function for this cache's store, call that function. Finally, increment this cache references' count.
|
||||
|
||||
void vm_cache_release_ref(vm_cache_ref *cache_ref)
|
||||
If this cache_ref is the last reference to its cache, we call destroy on the store, remove all of its pages from the page_cache_table and set the state of them to free, increase max_commit by the size of the now freed storage, remove the reference to the original cache, destroy the reference's mutex and its space.
|
||||
Otherwise, we call the store's release ref and return.
|
||||
|
||||
vm_page *vm_cache_lookup_page(vm_cache_ref *cache_ref, off_t offset)
|
||||
Lock the page_cache_table_lock and lookup the offset and cache_ref in the page_cache_table, then unlock.
|
||||
|
||||
void vm_cache_insert_page(vm_cache_ref *cache_ref, vm_page *page, off_t offset)
|
||||
Add this page to the page_cache_table.
|
||||
|
||||
void vm_cache_remove_page(vm_cache_ref *cache_ref, vm_page *page)
|
||||
Find this page and remove it from the hash list. Clean up the linked lists.
|
||||
|
||||
int vm_cache_insert_region(vm_cache_ref *cache_ref, vm_region *region)
|
||||
Add this region to the cache_ref's region list.
|
||||
|
||||
int vm_cache_remove_region(vm_cache_ref *cache_ref, vm_region *region)
|
||||
Remove this region from the cache_ref's region list.
|
||||
@@ -0,0 +1,33 @@
|
||||
Variables
|
||||
|
||||
bool trimming_cycle;
|
||||
Do we need free space?
|
||||
|
||||
static addr free_memory_low_water;
|
||||
|
||||
static addr free_memory_high_water;
|
||||
|
||||
static void scan_pages(vm_address_space *aspace, addr free_target)
|
||||
Finds a region in this address space to scan.
|
||||
Locks the region's cache_ref.
|
||||
For each page,
|
||||
if the page is present, do nothing with this page
|
||||
Lookup the page structure. If this page doesn't exist, do nothing with this page.
|
||||
If the page is written to or is hard wired (unswapable), do nothing with it.
|
||||
If the page is not accessed and is active and we need space (free_target), unmap it. If this is the last reference to that mapped page, put it on the inactive list.
|
||||
If the page has been modified, but wasn't on the active list, put it there.
|
||||
Move to the next region in this address space, wrap around until we hit the first one.
|
||||
|
||||
static int page_daemon()
|
||||
Walk through every address space:
|
||||
Adjust the size of the processes' working set (i.e. memory allocation) to be larger or smaller, to tailor to faults.
|
||||
Set trimming cycle if free pages is below the high water mark.
|
||||
Clear trimming cycle if free pages is above high water mark.
|
||||
Set free memory target to be the processes' mapped size minus the working set
|
||||
Call scan_pages
|
||||
|
||||
|
||||
int vm_daemon_init()
|
||||
Sets high water to pages/4 and low water to pages/8.
|
||||
Creates the page daemon as a kernel thread.
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
Variables
|
||||
extern bool trimming_cycle;
|
||||
Determines if we are trimming - if we are nearly out of space
|
||||
|
||||
static page_queue page_free_queue;
|
||||
The queue that holds unused (but not cleared) pages
|
||||
|
||||
static page_queue page_clear_queue;
|
||||
The queue that holds cleared (0'ed) pages
|
||||
|
||||
static page_queue page_modified_queue;
|
||||
The queue that holds altered pages
|
||||
|
||||
static page_queue page_active_queue;
|
||||
The queue that holds in use pages that are not altered
|
||||
|
||||
static vm_page *all_pages;
|
||||
Every page in the system
|
||||
|
||||
static addr physical_page_offset;
|
||||
The first address of real ram
|
||||
|
||||
static unsigned int num_pages;
|
||||
Total number of pages in the system
|
||||
|
||||
static spinlock_t page_lock;
|
||||
A lock to protect the queues.
|
||||
|
||||
static sem_id modified_pages_available;
|
||||
A semaphore to indicate if there are pages that need to be written to disk
|
||||
|
||||
static void clear_page(addr pa);
|
||||
Sets all values in this page to 0.
|
||||
|
||||
static vm_page * dequeue_page(page_queue *q)
|
||||
Standard queue remove first page; has count; no locking
|
||||
|
||||
void dump_page_stats(int argc, char **argv);
|
||||
Dumps counts of each state (active, inactive, busy, not used, modified, free, cleared, wired)
|
||||
|
||||
void dump_free_page_table(int argc, char **argv)
|
||||
Not done.
|
||||
|
||||
static void enqueue_page(page_queue *q, vm_page *page)
|
||||
Standard queue add a page; has count; no locking; SPECIAL - for page_modified_queue, if there is only one page modified (new one), release semaphore
|
||||
|
||||
static bool is_page_in_phys_range(kernel_args *ka, addr paddr)
|
||||
Determines if a physical address is in the physical memory that exists.
|
||||
|
||||
static void move_page_to_queue(page_queue *from_q, page_queue *to_q, vm_page *page)
|
||||
Removes the page from the from_q and adds it to the to_q.
|
||||
|
||||
static int pageout_daemon()
|
||||
aquires the "modified pages available" semaphore. Gets first page from modified list. Sets it to busy, updates all processes mapping this page that it is no longer a modified page, writes it out to disk, then puts it on the active list (i.e. not modified). Doesn't write out "anonymous" blocks unless we are trimming.
|
||||
|
||||
static int page_scrubber(void *);
|
||||
Every 1/10 second, takes a page from the free queue, memsets it to 0's, then puts it on the clear queue.
|
||||
|
||||
static void remove_page_from_queue(page_queue *q, vm_page *page)
|
||||
Removes a given page from the given page queue. No locking.
|
||||
|
||||
addr vm_alloc_from_ka_struct(kernel_args *ka, unsigned int size, int lock)
|
||||
Gets virtual space in the ka using vm_alloc_vspace_from_ka_struct, then uses vm_alloc_ppage_from_kernel_struct to find a physical page to map it to.
|
||||
|
||||
static addr vm_alloc_ppage_from_kernel_struct(kernel_args *ka)
|
||||
Attempts to extend, by one page, one of the phys_alloc_range blocks in the kernel args.
|
||||
|
||||
static addr vm_alloc_vspace_from_ka_struct(kernel_args *ka, unsigned int size)
|
||||
Attempts to find an address range that can be extended to hold size bytes.
|
||||
|
||||
vm_page * vm_lookup_page(addr page_num)
|
||||
Does the math to get vm_page pointer from a page number.
|
||||
|
||||
int vm_mark_page_inuse(addr page)
|
||||
Calls vm_mark_page_range_inuse with len of 1.
|
||||
|
||||
int vm_mark_page_range_inuse(addr start_page, addr len)
|
||||
Sets state to PAGE_STATE_UNUSED for all pages in this range.
|
||||
|
||||
vm_page * vm_page_allocate_page(int page_state)
|
||||
Gets a single page from the clear or free queue (from page_state), fall back to the other.
|
||||
|
||||
vm_page * vm_page_allocate_page_run(int page_state, addr len)
|
||||
Attempts to find a run of pages "len" long that are either free or clear. If found, pulls them from their queues and calls vm_page_set_state_nolock on them
|
||||
|
||||
vm_page * vm_page_allocate_specific_page(addr page_num, int page_state)
|
||||
Finds this page, removes it from the clear or free queue, clears it if necessary and returns. Returns NULL for not found or page in use.
|
||||
|
||||
int vm_page_init(kernel_args *ka)
|
||||
Initializes the free, clear, modified and active queues. Sets up the vm structures.
|
||||
|
||||
int vm_page_init2(kernel_args *ka)
|
||||
Properly maps the vm structures allocated in vm_page_init.
|
||||
|
||||
int vm_page_init_postthread(kernel_args *ka)
|
||||
Creates the page scrubber and the pageout daemon.
|
||||
|
||||
addr vm_page_num_pages()
|
||||
Returns the total number of pages.
|
||||
|
||||
addr vm_page_num_free_pages()
|
||||
Returns count of pages in free and clear queues.
|
||||
|
||||
int vm_page_set_state(vm_page *page, int page_state)
|
||||
Locks, then calls vm_page_set_state_nolock, then unlocks.
|
||||
|
||||
static int vm_page_set_state_nolock(vm_page *page, int page_state);
|
||||
Moves a page from the state that it is in to the state specified, and moves it from the old queue to the new one.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
static void anonymous_destroy(struct vm_store *store)
|
||||
Free's the memory associated with store
|
||||
|
||||
static off_t anonymous_commit(struct vm_store *store, off_t size)
|
||||
Returns 0
|
||||
|
||||
static int anonymous_has_page(struct vm_store *store, off_t offset)
|
||||
Returns 0
|
||||
|
||||
static ssize_t anonymous_read(struct vm_store *store, off_t offset, iovecs *vecs)
|
||||
Returns unimplemented
|
||||
|
||||
static ssize_t anonymous_write(struct vm_store *store, off_t offset, iovecs *vecs)
|
||||
Returns 0
|
||||
/*
|
||||
static int anonymous_fault(struct vm_store *backing_store, struct vm_address_space *aspace, off_t offset)
|
||||
*/
|
||||
|
||||
|
||||
vm_store *vm_store_create_anonymous_noswap()
|
||||
Allocates space for a vm_store. Populates its ops with the above, sets its cache and data to none.
|
||||
@@ -0,0 +1,20 @@
|
||||
static void device_destroy(struct vm_store *store)
|
||||
Frees the space associated with this store
|
||||
|
||||
static off_t device_commit(struct vm_store *store, off_t size)
|
||||
Sets this store's commited size to size.
|
||||
|
||||
static int device_has_page(struct vm_store *store, off_t offset)
|
||||
Returns 0
|
||||
|
||||
static ssize_t device_read(struct vm_store *store, off_t offset, iovecs *vecs)
|
||||
Returns unimplemented.
|
||||
|
||||
static ssize_t device_write(struct vm_store *store, off_t offset, iovecs *vecs)
|
||||
Returns 0
|
||||
|
||||
static int device_fault(struct vm_store *store, struct vm_address_space *aspace, off_t offset)
|
||||
Should be called when a page is not mapped in. Locks the translation map, Finds the region in the cache that contains this page and maps it in. Unlocks the cache.
|
||||
|
||||
vm_store *vm_store_create_device(addr base_addr)
|
||||
Allocates memory for the vm_store structure, plus the data_store_device structure. Sets cache to null, and data to the device_store_data. Sets the device_store_data's base address to the base address passed in.
|
||||
@@ -0,0 +1,20 @@
|
||||
static void null_destroy(struct vm_store *store)
|
||||
Frees this stores space.
|
||||
|
||||
static off_t null_commit(struct vm_store *store, off_t size)
|
||||
Sets committed size to size and returns it.
|
||||
|
||||
static int null_has_page(struct vm_store *store, off_t offset)
|
||||
returns 1.
|
||||
|
||||
static ssize_t null_read(struct vm_store *store, off_t offset, iovecs *vecs)
|
||||
Returns -1.
|
||||
|
||||
static ssize_t null_write(struct vm_store *store, off_t offset, iovecs *vecs)
|
||||
Returns -1.
|
||||
|
||||
static int null_fault(struct vm_store *store, struct vm_address_space *aspace, off_t offset)
|
||||
Returns a Fatal page fault error.
|
||||
|
||||
vm_store *vm_store_create_null(void)
|
||||
Creates an empty vm_store struct.
|
||||
@@ -0,0 +1,23 @@
|
||||
static void vnode_destroy(struct vm_store *store)
|
||||
Frees memory associated with this store.
|
||||
|
||||
static off_t vnode_commit(struct vm_store *store, off_t size)
|
||||
Sets committed size to size and returns it.
|
||||
|
||||
static int vnode_has_page(struct vm_store *store, off_t offset)
|
||||
Returns 1.
|
||||
|
||||
static ssize_t vnode_read(struct vm_store *store, off_t offset, iovecs *vecs)
|
||||
Calls vfs_readpage.
|
||||
|
||||
static ssize_t vnode_write(struct vm_store *store, off_t offset, iovecs *vecs)
|
||||
calls vfs_writepage
|
||||
|
||||
static void vnode_acquire_ref(struct vm_store *store)
|
||||
Calls vfs_vnode_aquire_ref
|
||||
|
||||
static void vnode_release_ref(struct vm_store *store)
|
||||
Calls vfs_vnode_release_ref
|
||||
|
||||
vm_store *vm_store_create_vnode(void *vnode)
|
||||
Creates space for a vm_store and a vnode_store_data. Sets data = vnode_store_data. Sets the vnode_store_data's vnode to vnode.
|
||||
Reference in New Issue
Block a user