1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 * 6 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. 7 * Distributed under the terms of the NewOS License. 8 */ 9 10 11 #include <vm/VMArea.h> 12 13 #include <new> 14 15 #include <heap.h> 16 17 18 #define AREA_HASH_TABLE_SIZE 1024 19 20 21 rw_lock VMAreaHash::sLock = RW_LOCK_INITIALIZER("area hash"); 22 VMAreaHashTable VMAreaHash::sTable; 23 static area_id sNextAreaID = 1; 24 25 26 // #pragma mark - VMArea 27 28 VMArea::VMArea(VMAddressSpace* addressSpace, uint32 wiring, uint32 protection) 29 : 30 name(NULL), 31 protection(protection), 32 wiring(wiring), 33 memory_type(0), 34 cache(NULL), 35 no_cache_change(0), 36 cache_offset(0), 37 cache_type(0), 38 page_protections(NULL), 39 address_space(addressSpace), 40 cache_next(NULL), 41 cache_prev(NULL), 42 hash_next(NULL) 43 { 44 new (&mappings) VMAreaMappings; 45 } 46 47 48 VMArea::~VMArea() 49 { 50 free(page_protections); 51 free(name); 52 } 53 54 55 status_t 56 VMArea::Init(const char* name) 57 { 58 // restrict the area name to B_OS_NAME_LENGTH 59 size_t length = strlen(name) + 1; 60 if (length > B_OS_NAME_LENGTH) 61 length = B_OS_NAME_LENGTH; 62 63 // clone the name 64 this->name = (char*)malloc_nogrow(length); 65 if (this->name == NULL) 66 return B_NO_MEMORY; 67 strlcpy(this->name, name, length); 68 69 id = atomic_add(&sNextAreaID, 1); 70 return B_OK; 71 } 72 73 74 // #pragma mark - VMAreaHash 75 76 77 /*static*/ status_t 78 VMAreaHash::Init() 79 { 80 return sTable.Init(AREA_HASH_TABLE_SIZE); 81 } 82 83 84 /*static*/ VMArea* 85 VMAreaHash::Lookup(area_id id) 86 { 87 ReadLock(); 88 VMArea* area = LookupLocked(id); 89 ReadUnlock(); 90 return area; 91 } 92 93 94 /*static*/ area_id 95 VMAreaHash::Find(const char* name) 96 { 97 ReadLock(); 98 99 area_id id = B_NAME_NOT_FOUND; 100 101 // TODO: Iterating through the whole table can be very slow and the whole 102 // time we're holding the lock! Use a second hash table! 103 104 for (VMAreaHashTable::Iterator it = sTable.GetIterator(); 105 VMArea* area = it.Next();) { 106 if (strcmp(area->name, name) == 0) { 107 id = area->id; 108 break; 109 } 110 } 111 112 ReadUnlock(); 113 114 return id; 115 } 116 117 118 /*static*/ void 119 VMAreaHash::Insert(VMArea* area) 120 { 121 WriteLock(); 122 sTable.Insert(area); 123 WriteUnlock(); 124 } 125 126 127 /*static*/ void 128 VMAreaHash::Remove(VMArea* area) 129 { 130 WriteLock(); 131 sTable.Remove(area); 132 WriteUnlock(); 133 } 134