--- Gnu-Mach/vm/vm_map.h 2020/09/02 04:42:55 1.1.1.2 +++ Gnu-Mach/vm/vm_map.h 2020/09/02 04:54:15 1.1.1.7 @@ -43,18 +43,24 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include -#include +#include +#include + +/* TODO: make it dynamic */ +#define KENTRY_DATA_SIZE (256*PAGE_SIZE) /* * Types defined: * - * vm_map_t the high-level address map data structure. * vm_map_entry_t an entry in an address map. * vm_map_version_t a timestamp of a map, for use with vm_map_lookup * vm_map_copy_t represents memory copied from an address map, @@ -99,9 +105,18 @@ struct vm_map_entry { #define vme_next links.next #define vme_start links.start #define vme_end links.end + struct rbtree_node tree_node; /* links to other entries in tree */ + struct rbtree_node gap_node; /* links to other entries in gap tree */ + struct list gap_list; /* links to other entries with + the same gap size */ + vm_size_t gap_size; /* size of available memory + following this entry */ union vm_map_object object; /* object I point to */ vm_offset_t offset; /* offset into object */ unsigned int + /* boolean_t */ in_gap_tree:1, /* entry is in the gap tree if true, + or linked to other entries with + the same gap size if false */ /* boolean_t */ is_shared:1, /* region is shared */ /* boolean_t */ is_sub_map:1, /* Is "object" a submap? */ /* boolean_t */ in_transition:1, /* Entry being changed */ @@ -134,9 +149,10 @@ typedef struct vm_map_entry *vm_map_entr */ struct vm_map_header { struct vm_map_links links; /* first, last, min, max */ + struct rbtree tree; /* Sorted tree of entries */ + struct rbtree gap_tree; /* Sorted tree of gap lists + for allocations */ int nentries; /* Number of entries */ - boolean_t entries_pageable; - /* are map entries pageable? */ }; /* @@ -149,9 +165,11 @@ struct vm_map_header { * * Implementation: * Maps are doubly-linked lists of map entries, sorted - * by address. One hint is used to start - * searches again from the last successful search, - * insertion, or removal. Another hint is used to + * by address. They're also contained in a red-black tree. + * One hint is used to start searches again at the last + * successful search, insertion, or removal. If the hint + * lookup failed (i.e. the hint didn't refer to the requested + * entry), a BST lookup is performed. Another hint is used to * quickly find free space. */ struct vm_map { @@ -161,19 +179,22 @@ struct vm_map { #define max_offset hdr.links.end /* end of range */ pmap_t pmap; /* Physical map */ vm_size_t size; /* virtual size */ + vm_size_t user_wired; /* wired by user size */ int ref_count; /* Reference count */ decl_simple_lock_data(, ref_lock) /* Lock for ref_count field */ vm_map_entry_t hint; /* hint for quick lookups */ decl_simple_lock_data(, hint_lock) /* lock for hint storage */ vm_map_entry_t first_free; /* First free space hint */ - boolean_t wait_for_space; /* Should callers wait + + /* Flags */ + unsigned int wait_for_space:1, /* Should callers wait for space? */ - boolean_t wiring_required;/* All memory wired? */ + /* boolean_t */ wiring_required:1; /* All memory wired? */ + unsigned int timestamp; /* Version number */ -}; -typedef struct vm_map *vm_map_t; -#define VM_MAP_NULL ((vm_map_t) 0) + const char *name; /* Associated name */ +}; #define vm_map_to_entry(map) ((struct vm_map_entry *) &(map)->hdr.links) #define vm_map_first_entry(map) ((map)->hdr.links.next) @@ -228,11 +249,7 @@ typedef struct vm_map_version { * (returned) and an abort flag (abort if TRUE). */ -#if iPSC386 || iPSC860 #define VM_MAP_COPY_PAGE_LIST_MAX 64 -#else /* iPSC386 || iPSC860 */ -#define VM_MAP_COPY_PAGE_LIST_MAX 8 -#endif /* iPSC386 || iPSC860 */ typedef struct vm_map_copy { int type; @@ -335,13 +352,9 @@ MACRO_BEGIN \ (map)->timestamp = 0; \ MACRO_END -#define vm_map_lock(map) \ -MACRO_BEGIN \ - lock_write(&(map)->lock); \ - (map)->timestamp++; \ -MACRO_END +void vm_map_lock(struct vm_map *map); +void vm_map_unlock(struct vm_map *map); -#define vm_map_unlock(map) lock_write_done(&(map)->lock) #define vm_map_lock_read(map) lock_read(&(map)->lock) #define vm_map_unlock_read(map) lock_read_done(&(map)->lock) #define vm_map_lock_write_to_read(map) \ @@ -357,46 +370,101 @@ MACRO_END * Exported procedures that operate on vm_map_t. */ -extern vm_offset_t kentry_data; -extern vm_offset_t kentry_data_size; -extern int kentry_count; -extern void vm_map_init(); /* Initialize the module */ - -extern vm_map_t vm_map_create(); /* Create an empty map */ -extern vm_map_t vm_map_fork(); /* Create a map in the image - * of an existing map */ - -extern void vm_map_reference(); /* Gain a reference to - * an existing map */ -extern void vm_map_deallocate(); /* Lose a reference */ - -extern kern_return_t vm_map_enter(); /* Enter a mapping */ -extern kern_return_t vm_map_find_entry(); /* Enter a mapping primitive */ -extern kern_return_t vm_map_remove(); /* Deallocate a region */ -extern kern_return_t vm_map_protect(); /* Change protection */ -extern kern_return_t vm_map_inherit(); /* Change inheritance */ - -extern void vm_map_print(); /* Debugging: print a map */ - -extern kern_return_t vm_map_lookup(); /* Look up an address */ -extern boolean_t vm_map_verify(); /* Verify that a previous - * lookup is still valid */ +/* Initialize the module */ +extern void vm_map_init(void); + +/* Initialize an empty map */ +extern void vm_map_setup(vm_map_t, pmap_t, vm_offset_t, vm_offset_t); +/* Create an empty map */ +extern vm_map_t vm_map_create(pmap_t, vm_offset_t, vm_offset_t); +/* Create a map in the image of an existing map */ +extern vm_map_t vm_map_fork(vm_map_t); + +/* Gain a reference to an existing map */ +extern void vm_map_reference(vm_map_t); +/* Lose a reference */ +extern void vm_map_deallocate(vm_map_t); + +/* Enter a mapping */ +extern kern_return_t vm_map_enter(vm_map_t, vm_offset_t *, vm_size_t, + vm_offset_t, boolean_t, vm_object_t, + vm_offset_t, boolean_t, vm_prot_t, + vm_prot_t, vm_inherit_t); +/* Enter a mapping primitive */ +extern kern_return_t vm_map_find_entry(vm_map_t, vm_offset_t *, vm_size_t, + vm_offset_t, vm_object_t, + vm_map_entry_t *); +/* Deallocate a region */ +extern kern_return_t vm_map_remove(vm_map_t, vm_offset_t, vm_offset_t); +/* Change protection */ +extern kern_return_t vm_map_protect(vm_map_t, vm_offset_t, vm_offset_t, + vm_prot_t, boolean_t); +/* Change inheritance */ +extern kern_return_t vm_map_inherit(vm_map_t, vm_offset_t, vm_offset_t, + vm_inherit_t); + +/* Look up an address */ +extern kern_return_t vm_map_lookup(vm_map_t *, vm_offset_t, vm_prot_t, + vm_map_version_t *, vm_object_t *, + vm_offset_t *, vm_prot_t *, boolean_t *); +/* Find a map entry */ +extern boolean_t vm_map_lookup_entry(vm_map_t, vm_offset_t, + vm_map_entry_t *); +/* Verify that a previous lookup is still valid */ +extern boolean_t vm_map_verify(vm_map_t, vm_map_version_t *); /* vm_map_verify_done is now a macro -- see below */ -extern kern_return_t vm_map_copyin(); /* Make a copy of a region */ -extern kern_return_t vm_map_copyin_page_list();/* Make a copy of a region - * using a page list copy */ -extern kern_return_t vm_map_copyout(); /* Place a copy into a map */ -extern kern_return_t vm_map_copy_overwrite();/* Overwrite existing memory - * with a copy */ -extern void vm_map_copy_discard(); /* Discard a copy without - * using it */ -extern kern_return_t vm_map_copy_discard_cont();/* Page list continuation - * version of previous */ - -extern kern_return_t vm_map_machine_attribute(); - /* Add or remove machine- - dependent attributes from - map regions */ +/* Make a copy of a region */ +extern kern_return_t vm_map_copyin(vm_map_t, vm_offset_t, vm_size_t, + boolean_t, vm_map_copy_t *); +/* Make a copy of a region using a page list copy */ +extern kern_return_t vm_map_copyin_page_list(vm_map_t, vm_offset_t, + vm_size_t, boolean_t, + boolean_t, vm_map_copy_t *, + boolean_t); +/* Place a copy into a map */ +extern kern_return_t vm_map_copyout(vm_map_t, vm_offset_t *, vm_map_copy_t); +/* Overwrite existing memory with a copy */ +extern kern_return_t vm_map_copy_overwrite(vm_map_t, vm_offset_t, + vm_map_copy_t, boolean_t); +/* Discard a copy without using it */ +extern void vm_map_copy_discard(vm_map_copy_t); +extern void vm_map_copy_page_discard(vm_map_copy_t); +extern vm_map_copy_t vm_map_copy_copy(vm_map_copy_t); +/* Page list continuation version of previous */ +extern kern_return_t vm_map_copy_discard_cont(vm_map_copyin_args_t, + vm_map_copy_t *); + +/* Add or remove machine- dependent attributes from map regions */ +extern kern_return_t vm_map_machine_attribute(vm_map_t, vm_offset_t, + vm_size_t, + vm_machine_attribute_t, + vm_machine_attribute_val_t *); + +/* Delete entry from map */ +extern void vm_map_entry_delete(vm_map_t, vm_map_entry_t); + +kern_return_t vm_map_delete( + vm_map_t map, + vm_offset_t start, + vm_offset_t end); + +kern_return_t vm_map_copyout_page_list( + vm_map_t dst_map, + vm_offset_t *dst_addr, /* OUT */ + vm_map_copy_t copy); + +void vm_map_copy_page_discard (vm_map_copy_t copy); + +boolean_t vm_map_lookup_entry( + vm_map_t map, + vm_offset_t address, + vm_map_entry_t *entry); /* OUT */ + +static inline void vm_map_set_name(vm_map_t map, const char *name) +{ + map->name = name; +} + /* * Functions implemented as macros @@ -419,7 +487,9 @@ extern kern_return_t vm_map_machine_attr /* * Pageability functions. Includes macro to preserve old interface. */ -extern kern_return_t vm_map_pageable_common(); +extern kern_return_t vm_map_pageable_common(vm_map_t, vm_offset_t, + vm_offset_t, vm_prot_t, + boolean_t); #define vm_map_pageable(map, s, e, access) \ vm_map_pageable_common(map, s, e, access, FALSE) @@ -434,6 +504,42 @@ extern kern_return_t vm_map_pageable_com extern vm_object_t vm_submap_object; /* + * vm_map_copyin_object: + * + * Create a copy object from an object. + * Our caller donates an object reference. + */ +extern kern_return_t vm_map_copyin_object( + vm_object_t object, + vm_offset_t offset, /* offset of region in object */ + vm_size_t size, /* size of region in object */ + vm_map_copy_t *copy_result); /* OUT */ + +/* + * vm_map_submap: [ kernel use only ] + * + * Mark the given range as handled by a subordinate map. + * + * This range must have been created with vm_map_find using + * the vm_submap_object, and no other operations may have been + * performed on this range prior to calling vm_map_submap. + * + * Only a limited number of operations can be performed + * within this rage after calling vm_map_submap: + * vm_fault + * [Don't try vm_map_copyin!] + * + * To remove a submapping, one must first remove the + * range from the superior map, and then destroy the + * submap (if desired). [Better yet, don't try it.] + */ +extern kern_return_t vm_map_submap( + vm_map_t map, + vm_offset_t start, + vm_offset_t end, + vm_map_t submap); + +/* * Wait and wakeup macros for in_transition map entries. */ #define vm_map_entry_wait(map, interruptible) \ @@ -445,4 +551,25 @@ extern vm_object_t vm_submap_object; #define vm_map_entry_wakeup(map) thread_wakeup((event_t)&(map)->hdr) +/* + * This routine is called only when it is known that + * the entry must be split. + */ +extern void _vm_map_clip_start( + struct vm_map_header *map_header, + vm_map_entry_t entry, + vm_offset_t start); + +/* + * vm_map_clip_end: [ internal use only ] + * + * Asserts that the given entry ends at or before + * the specified address; if necessary, + * it splits the entry into two. + */ +void _vm_map_clip_end( + struct vm_map_header *map_header, + vm_map_entry_t entry, + vm_offset_t end); + #endif /* _VM_VM_MAP_H_ */