Changeset a294ad0 in mainline for generic/src/mm/frame.c


Ignore:
Timestamp:
2006-02-02T14:00:32Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2d43f3e
Parents:
758e065
Message:

Currently not-working SLAB allocator.

  • slightly changed interface to frame_alloc, allow zone preference
File:
1 edited

Legend:

Unmodified
Added
Removed
  • generic/src/mm/frame.c

    r758e065 ra294ad0  
    7777}
    7878
     79/**
     80 * Find AND LOCK zone that can allocate order frames
     81 *
     82 * Assume zone_head_lock is locked.
     83 */
     84static 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
    79103/** Allocate power-of-two frames of physical memory.
    80104 *
    81105 * @param flags Flags for host zone selection and address processing.
    82106 * @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
    83109 *
    84110 * @return Allocated frame.
    85111 */
    86 __address frame_alloc(int flags, __u8 order, int * status)
     112__address frame_alloc(int flags, __u8 order, int * status, zone_t **pzone)
    87113{
    88114        ipl_t ipl;
    89         link_t *cur, *tmp;
    90         zone_t *z;
     115        link_t *tmp;
    91116        zone_t *zone = NULL;
    92117        frame_t *frame = NULL;
     
    100125         * First, find suitable frame zone.
    101126         */
    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
    116143        if (!zone) {
    117144                if (flags & FRAME_PANIC)
     
    162189                *status = FRAME_OK;
    163190        }
     191        if (pzone)
     192                *pzone = zone;
    164193        return v;
    165194}
    166195
    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 */
     203static zone_t * addr2zone(__address addr, int lock)
     204{
    178205        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
    192208        for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
    193209                z = list_get_instance(cur, zone_t, link);
    194210               
    195211                spinlock_lock(&z->lock);
    196                
    197                 if (IS_KA(addr))
    198                         addr = KA2PA(addr);
    199212               
    200213                /*
     
    202215                 */
    203216                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;
    206220                }
    207221
    208222                spinlock_unlock(&z->lock);
    209223        }
    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 */
     232frame_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 */
     263void 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 */
    212282       
    213283        frame = ADDR2FRAME(zone, addr);
Note: See TracChangeset for help on using the changeset viewer.