Subversion Repositories HelenOS-historic

Rev

Rev 759 | Rev 764 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 759 Rev 762
Line 74... Line 74...
74
    }
74
    }
75
 
75
 
76
    frame_arch_init();
76
    frame_arch_init();
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
/** Allocate power-of-two frames of physical memory.
103
/** Allocate power-of-two frames of physical memory.
80
 *
104
 *
81
 * @param flags Flags for host zone selection and address processing.
105
 * @param flags Flags for host zone selection and address processing.
82
 * @param order Allocate exactly 2^order frames.
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
 * @return Allocated frame.
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
    ipl_t ipl;
114
    ipl_t ipl;
89
    link_t *cur, *tmp;
115
    link_t *tmp;
90
    zone_t *z;
-
 
91
    zone_t *zone = NULL;
116
    zone_t *zone = NULL;
92
    frame_t *frame = NULL;
117
    frame_t *frame = NULL;
93
    __address v;
118
    __address v;
94
   
119
   
95
loop:
120
loop:
Line 97... Line 122...
97
    spinlock_lock(&zone_head_lock);
122
    spinlock_lock(&zone_head_lock);
98
 
123
 
99
    /*
124
    /*
100
     * First, find suitable frame zone.
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);
127
    if (pzone && *pzone) {
104
       
-
 
105
        spinlock_lock(&z->lock);
128
        spinlock_lock(&(*pzone)->lock);
106
 
-
 
107
        /* Check if the zone has 2^order frames area available  */
-
 
108
        if (buddy_system_can_alloc(z->buddy_system, order)) {
129
        if (!buddy_system_can_alloc((*pzone)->buddy_system, order))
109
            zone = z;
130
            spinlock_unlock(&(*pzone)->lock);
110
            break;
-
 
111
        }
131
        else
112
       
-
 
113
        spinlock_unlock(&z->lock);
132
            zone = *pzone;
114
    }
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);
115
   
141
    }
-
 
142
 
116
    if (!zone) {
143
    if (!zone) {
117
        if (flags & FRAME_PANIC)
144
        if (flags & FRAME_PANIC)
118
            panic("Can't allocate frame.\n");
145
            panic("Can't allocate frame.\n");
119
       
146
       
120
        /*
147
        /*
Line 159... Line 186...
159
   
186
   
160
    if (flags & FRAME_ATOMIC) {
187
    if (flags & FRAME_ATOMIC) {
161
        ASSERT(status != NULL);
188
        ASSERT(status != NULL);
162
        *status = FRAME_OK;
189
        *status = FRAME_OK;
163
    }
190
    }
-
 
191
    if (pzone)
-
 
192
        *pzone = zone;
164
    return v;
193
    return v;
165
}
194
}
166
 
195
 
-
 
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
{
-
 
205
    link_t *cur;
-
 
206
    zone_t *z = NULL;
-
 
207
 
-
 
208
    for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
-
 
209
        z = list_get_instance(cur, zone_t, link);
-
 
210
       
-
 
211
        spinlock_lock(&z->lock);
-
 
212
       
-
 
213
        /*
-
 
214
         * Check if addr belongs to z.
-
 
215
         */
-
 
216
        if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) {
-
 
217
            if (!lock)
-
 
218
                spinlock_unlock(&z->lock);
-
 
219
            return z;
-
 
220
        }
-
 
221
 
-
 
222
        spinlock_unlock(&z->lock);
-
 
223
    }
-
 
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
 
167
/** Free a frame.
255
/** Free a frame.
168
 *
256
 *
169
 * Find respective frame structrue for supplied addr.
257
 * Find respective frame structrue for supplied addr.
170
 * Decrement frame reference count.
258
 * Decrement frame reference count.
171
 * If it drops to zero, move the frame structure to free list.
259
 * If it drops to zero, move the frame structure to free list.
Line 173... Line 261...
173
 * @param addr Address of the frame to be freed. It must be a multiple of FRAME_SIZE.
261
 * @param addr Address of the frame to be freed. It must be a multiple of FRAME_SIZE.
174
 */
262
 */
175
void frame_free(__address addr)
263
void frame_free(__address addr)
176
{
264
{
177
    ipl_t ipl;
265
    ipl_t ipl;
178
    link_t *cur;
-
 
179
    zone_t *z;
266
    zone_t *zone;
180
    zone_t *zone = NULL;
-
 
181
    frame_t *frame;
267
    frame_t *frame;
182
    int order;
268
    int order;
183
   
269
   
184
    ASSERT(addr % FRAME_SIZE == 0);
270
    ASSERT(addr % FRAME_SIZE == 0);
185
   
271
   
-
 
272
    if (IS_KA(addr))
-
 
273
        addr = KA2PA(addr);
-
 
274
 
186
    ipl = interrupts_disable();
275
    ipl = interrupts_disable();
187
    spinlock_lock(&zone_head_lock);
276
    spinlock_lock(&zone_head_lock);
188
   
277
   
189
    /*
278
    /*
190
     * First, find host frame zone for addr.
279
     * First, find host frame zone for addr.
191
     */
280
     */
192
    for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
281
    zone = addr2zone(addr, 1); /* This locks the zone automatically */
193
        z = list_get_instance(cur, zone_t, link);
-
 
194
       
-
 
195
        spinlock_lock(&z->lock);
-
 
196
       
-
 
197
        if (IS_KA(addr))
-
 
198
            addr = KA2PA(addr);
-
 
199
       
-
 
200
        /*
-
 
201
         * Check if addr belongs to z.
-
 
202
         */
-
 
203
        if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) {
-
 
204
            zone = z;
-
 
205
            break;
-
 
206
        }
-
 
207
 
-
 
208
        spinlock_unlock(&z->lock);
-
 
209
    }
-
 
210
   
-
 
211
    ASSERT(zone != NULL);
-
 
212
   
282
   
213
    frame = ADDR2FRAME(zone, addr);
283
    frame = ADDR2FRAME(zone, addr);
214
   
284
   
215
    /* remember frame order */
285
    /* remember frame order */
216
    order = frame->buddy_order;
286
    order = frame->buddy_order;