Changeset a294ad0 in mainline for generic/src/mm/frame.c
- Timestamp:
- 2006-02-02T14:00:32Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2d43f3e
- Parents:
- 758e065
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/src/mm/frame.c
r758e065 ra294ad0 77 77 } 78 78 79 /** 80 * Find AND LOCK zone that can allocate order frames 81 * 82 * Assume zone_head_lock is locked. 83 */ 84 static zone_t * find_free_zone(__u8 order) 85 { 86 link_t *cur; 87 zone_t *z; 88 89 for (cur = zone_head.next; cur != &zone_head;cur = cur->next) { 90 z = list_get_instance(cur, zone_t, link); 91 92 spinlock_lock(&z->lock); 93 94 /* Check if the zone has 2^order frames area available */ 95 if (buddy_system_can_alloc(z->buddy_system, order)) 96 return z; 97 98 spinlock_unlock(&z->lock); 99 } 100 return NULL; 101 } 102 79 103 /** Allocate power-of-two frames of physical memory. 80 104 * 81 105 * @param flags Flags for host zone selection and address processing. 82 106 * @param order Allocate exactly 2^order frames. 107 * @param pzone Pointer to preferred zone pointer, on output it changes 108 * to the zone that the frame was really allocated to 83 109 * 84 110 * @return Allocated frame. 85 111 */ 86 __address frame_alloc(int flags, __u8 order, int * status )112 __address frame_alloc(int flags, __u8 order, int * status, zone_t **pzone) 87 113 { 88 114 ipl_t ipl; 89 link_t *cur, *tmp; 90 zone_t *z; 115 link_t *tmp; 91 116 zone_t *zone = NULL; 92 117 frame_t *frame = NULL; … … 100 125 * First, find suitable frame zone. 101 126 */ 102 for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { 103 z = list_get_instance(cur, zone_t, link); 104 105 spinlock_lock(&z->lock); 106 107 /* Check if the zone has 2^order frames area available */ 108 if (buddy_system_can_alloc(z->buddy_system, order)) { 109 zone = z; 110 break; 111 } 112 113 spinlock_unlock(&z->lock); 114 } 115 127 if (pzone && *pzone) { 128 spinlock_lock(&(*pzone)->lock); 129 if (!buddy_system_can_alloc((*pzone)->buddy_system, order)) 130 spinlock_unlock(&(*pzone)->lock); 131 else 132 zone = *pzone; 133 } 134 if (!zone) { 135 zone = find_free_zone(order); 136 /* If no memory, reclaim some slab memory, 137 if it does not help, reclaim all */ 138 if (!zone && !(flags & FRAME_NO_RECLAIM)) 139 if (slab_reclaim(0) || slab_reclaim(SLAB_RECLAIM_ALL)) 140 zone = find_free_zone(order); 141 } 142 116 143 if (!zone) { 117 144 if (flags & FRAME_PANIC) … … 162 189 *status = FRAME_OK; 163 190 } 191 if (pzone) 192 *pzone = zone; 164 193 return v; 165 194 } 166 195 167 /** Free a frame. 168 * 169 * Find respective frame structrue for supplied addr. 170 * Decrement frame reference count. 171 * If it drops to zero, move the frame structure to free list. 172 * 173 * @param addr Address of the frame to be freed. It must be a multiple of FRAME_SIZE. 174 */ 175 void frame_free(__address addr) 176 { 177 ipl_t ipl; 196 /** Convert address to zone pointer 197 * 198 * Assume zone_head_lock is held 199 * 200 * @param addr Physical address 201 * @param lock If true, lock the zone 202 */ 203 static zone_t * addr2zone(__address addr, int lock) 204 { 178 205 link_t *cur; 179 zone_t *z; 180 zone_t *zone = NULL; 181 frame_t *frame; 182 int order; 183 184 ASSERT(addr % FRAME_SIZE == 0); 185 186 ipl = interrupts_disable(); 187 spinlock_lock(&zone_head_lock); 188 189 /* 190 * First, find host frame zone for addr. 191 */ 206 zone_t *z = NULL; 207 192 208 for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { 193 209 z = list_get_instance(cur, zone_t, link); 194 210 195 211 spinlock_lock(&z->lock); 196 197 if (IS_KA(addr))198 addr = KA2PA(addr);199 212 200 213 /* … … 202 215 */ 203 216 if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) { 204 zone = z; 205 break; 217 if (!lock) 218 spinlock_unlock(&z->lock); 219 return z; 206 220 } 207 221 208 222 spinlock_unlock(&z->lock); 209 223 } 210 211 ASSERT(zone != NULL); 224 225 panic("Cannot find addr2zone: 0x%X", addr); 226 } 227 228 /** Return frame_t structure corresponding to address 229 * 230 * 231 */ 232 frame_t * frame_addr2frame(__address addr) 233 { 234 ipl_t ipl; 235 frame_t *frame; 236 zone_t *zone; 237 238 if (IS_KA(addr)) 239 addr = KA2PA(addr); 240 241 /* Disable interrupts to avoid deadlocks with interrupt handlers */ 242 ipl = interrupts_disable(); 243 spinlock_lock(&zone_head_lock); 244 245 zone = addr2zone(addr,0); 246 frame = ADDR2FRAME(zone, addr); 247 248 spinlock_unlock(&zone_head_lock); 249 interrupts_restore(ipl); 250 251 return frame; 252 } 253 254 255 /** Free a frame. 256 * 257 * Find respective frame structrue for supplied addr. 258 * Decrement frame reference count. 259 * If it drops to zero, move the frame structure to free list. 260 * 261 * @param addr Address of the frame to be freed. It must be a multiple of FRAME_SIZE. 262 */ 263 void frame_free(__address addr) 264 { 265 ipl_t ipl; 266 zone_t *zone; 267 frame_t *frame; 268 int order; 269 270 ASSERT(addr % FRAME_SIZE == 0); 271 272 if (IS_KA(addr)) 273 addr = KA2PA(addr); 274 275 ipl = interrupts_disable(); 276 spinlock_lock(&zone_head_lock); 277 278 /* 279 * First, find host frame zone for addr. 280 */ 281 zone = addr2zone(addr, 1); /* This locks the zone automatically */ 212 282 213 283 frame = ADDR2FRAME(zone, addr);
Note:
See TracChangeset
for help on using the changeset viewer.