Another work-in-progress towards having extra structures per mapping per page:
* vm_area and vm_page now have a new field "mappings" where they will store lists of vm_page_mapping structures. vm_page::ref_count is gone, as it's no longer needed (it was never updated correctly, anyway). * vm_caches now have a type field, ie. CACHE_TYPE_RAM for anonymous areas - this makes the stores a bit less independent, but is quite handy in several places. * Added new vm_map_page() and vm_unmap_pages() functions to be used whenever you map in or unmap pages into/from an area. They don't do much more than handling vm_page::wired_count correctly right now, though (ie. B_LAZY_LOCK is now working as expected as well). * Moved the device fault handler to vm_map_physical_memory(); it was not really used as a fault handler, anyway. * Didn't notice Ingo's changes to the I/O space region broke lock_memory(). It now checks the type of the area that contains the memory, and doesn't lock anymore if not needed which solves the problem in a platform independent way. * Implemented lock_memory() and unlock_memory() for real: they now change the vm_page::wired_count member to identify pages that shouldn't be paged out. * vm_area_for() now uses vm_area_lookup() internally. * Fixed various potential overflow conditions with areas that reach 0xffffffff. * Creating anonymous areas with B_FULL_LOCK no longer causes vm_soft_fault() to be called, instead, the pages are allocated and mapped (via vm_map_page()) directly. * Removed the _vm_ prefix for create_area_struct() and create_reserved_area_struct(). * Fixed a bug in vm_page_write_modified() that would not have enqueued pages that failed to be written to the modified queue again when needed. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20251 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -60,10 +60,11 @@ area_id vm_clone_area(team_id team, const char *name, void **address,
|
||||
status_t vm_delete_area(team_id aid, area_id id);
|
||||
status_t vm_create_vnode_cache(void *vnode, vm_cache_ref **_cacheRef);
|
||||
vm_area *vm_area_lookup(vm_address_space *addressSpace, addr_t address);
|
||||
|
||||
status_t vm_set_area_memory_type(area_id id, addr_t physicalBase, uint32 type);
|
||||
|
||||
status_t vm_get_page_mapping(team_id team, addr_t vaddr, addr_t *paddr);
|
||||
status_t vm_unmap_pages(vm_area *area, addr_t base, size_t length);
|
||||
status_t vm_map_page(vm_area *area, vm_page *page, addr_t address,
|
||||
uint32 protection);
|
||||
status_t vm_get_physical_page(addr_t paddr, addr_t *vaddr, uint32 flags);
|
||||
status_t vm_put_physical_page(addr_t vaddr);
|
||||
|
||||
|
||||
@@ -10,10 +10,60 @@
|
||||
|
||||
|
||||
#include <kernel.h>
|
||||
#include <sys/uio.h>
|
||||
#include <arch/vm_types.h>
|
||||
#include <arch/vm_translation_map.h>
|
||||
#include <util/DoublyLinkedQueue.h>
|
||||
|
||||
#include <sys/uio.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct vm_page_mapping;
|
||||
typedef DoublyLinkedListLink<vm_page_mapping> vm_page_mapping_link;
|
||||
#else
|
||||
typedef struct { void *previous; void *next; } vm_page_mapping_link;
|
||||
#endif
|
||||
|
||||
typedef struct vm_page_mapping {
|
||||
vm_page_mapping_link page_link;
|
||||
vm_page_mapping_link area_link;
|
||||
struct vm_page *page;
|
||||
struct vm_area *area;
|
||||
} vm_page_mapping;
|
||||
|
||||
#ifdef __cplusplus
|
||||
class DoublyLinkedPageLink {
|
||||
public:
|
||||
inline vm_page_mapping_link *operator()(vm_page_mapping *element) const
|
||||
{
|
||||
return &element->page_link;
|
||||
}
|
||||
|
||||
inline const vm_page_mapping_link *operator()(const vm_page_mapping *element) const
|
||||
{
|
||||
return &element->page_link;
|
||||
}
|
||||
};
|
||||
|
||||
class DoublyLinkedAreaLink {
|
||||
public:
|
||||
inline vm_page_mapping_link *operator()(vm_page_mapping *element) const
|
||||
{
|
||||
return &element->area_link;
|
||||
}
|
||||
|
||||
inline const vm_page_mapping_link *operator()(const vm_page_mapping *element) const
|
||||
{
|
||||
return &element->area_link;
|
||||
}
|
||||
};
|
||||
|
||||
typedef class DoublyLinkedQueue<vm_page_mapping, DoublyLinkedPageLink> vm_page_mappings;
|
||||
typedef class DoublyLinkedQueue<vm_page_mapping, DoublyLinkedAreaLink> vm_area_mappings;
|
||||
#else // !__cplusplus
|
||||
typedef void *vm_page_mappings;
|
||||
typedef void *vm_area_mappings;
|
||||
#endif
|
||||
|
||||
// vm page
|
||||
typedef struct vm_page {
|
||||
@@ -31,12 +81,15 @@ typedef struct vm_page {
|
||||
struct vm_page *cache_prev;
|
||||
struct vm_page *cache_next;
|
||||
|
||||
int32 ref_count;
|
||||
vm_page_mappings mappings;
|
||||
|
||||
uint32 type : 2;
|
||||
uint32 state : 3;
|
||||
uint32 busy_reading : 1;
|
||||
uint32 busy_writing : 1;
|
||||
uint8 type : 2;
|
||||
uint8 state : 3;
|
||||
uint8 busy_reading : 1;
|
||||
uint8 busy_writing : 1;
|
||||
|
||||
uint16 wired_count;
|
||||
int8 usage_count;
|
||||
} vm_page;
|
||||
|
||||
enum {
|
||||
@@ -56,6 +109,13 @@ enum {
|
||||
PAGE_STATE_UNUSED
|
||||
};
|
||||
|
||||
enum {
|
||||
CACHE_TYPE_RAM = 0,
|
||||
CACHE_TYPE_VNODE,
|
||||
CACHE_TYPE_DEVICE,
|
||||
CACHE_TYPE_NULL
|
||||
};
|
||||
|
||||
// vm_cache_ref
|
||||
typedef struct vm_cache_ref {
|
||||
struct vm_cache *cache;
|
||||
@@ -82,6 +142,7 @@ typedef struct vm_cache {
|
||||
uint32 temporary : 1;
|
||||
uint32 scan_skip : 1;
|
||||
uint32 busy : 1;
|
||||
uint32 type : 5;
|
||||
} vm_cache;
|
||||
|
||||
// vm area
|
||||
@@ -97,6 +158,7 @@ typedef struct vm_area {
|
||||
|
||||
struct vm_cache_ref *cache_ref;
|
||||
off_t cache_offset;
|
||||
vm_area_mappings mappings;
|
||||
|
||||
struct vm_address_space *address_space;
|
||||
struct vm_area *address_space_next;
|
||||
|
||||
Reference in New Issue
Block a user