Rev 861 | Rev 886 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
854 | serge | 1 | |
2 | #include |
||
3 | #include |
||
4 | #include |
||
5 | #include |
||
6 | |||
7 | |||
8 | |||
9 | |||
10 | |||
11 | |||
12 | |||
13 | |||
14 | |||
15 | |||
16 | { |
||
17 | u32_t val; |
||
18 | asm volatile ("mov %0, edx":"=r"(val)); |
||
19 | return val; |
||
20 | }; |
||
21 | |||
22 | |||
23 | { |
||
24 | asm volatile (""::"d" (val) ); |
||
25 | }; |
||
26 | |||
27 | |||
28 | static void __fastcall buddy_system_free(zone_t *z, link_t *block); |
||
29 | static void zone_mark_unavailable(zone_t *zone, index_t frame_idx); |
||
30 | |||
31 | |||
32 | void __fastcall zone_free(zone_t *zone, pfn_t frame_idx); |
||
859 | serge | 33 | |
854 | serge | 34 | |
35 | |||
36 | |||
37 | |||
38 | |||
39 | |||
40 | |||
41 | |||
42 | static void zone_reserve(zone_t *z, pfn_t base, count_t count); |
||
43 | static void zone_release(zone_t *z, pfn_t base, count_t count); |
||
44 | |||
45 | |||
46 | |||
47 | { |
||
48 | int i; |
||
49 | |||
50 | |||
51 | u32_t size; |
||
52 | count_t pages; |
||
53 | size_t conf_size; |
||
54 | size_t core_size; |
||
55 | |||
56 | |||
57 | DBG("last page = %x total pages = %x\n",mem_amount, pages); |
||
862 | serge | 58 | |
854 | serge | 59 | |
60 | DBG("conf_size = %x free mem start =%x\n",conf_size, pg_balloc); |
||
862 | serge | 61 | |
854 | serge | 62 | |
63 | |||
64 | |||
65 | zone_reserve(&z_core, 0, pg_balloc >> FRAME_WIDTH); |
||
66 | |||
67 | |||
68 | |||
69 | core_size = (pg_free+conf_size+1024*1024*5)&(-1024*1024*4); |
||
70 | // printf("core size = %x core heap = %x\n",core_size,core_size-conf_size-pg_free); |
||
71 | |||
72 | |||
73 | u32_t b0, b1; |
||
74 | |||
75 | |||
76 | p1 = (last_page-core_size)>>12; |
||
77 | |||
78 | |||
79 | b1 = p1*sizeof(frame_t); |
||
80 | |||
81 | |||
82 | // printf("buddy_1: %x pages conf_size %x\n", p1, b1); |
||
83 | |||
84 | |||
85 | zone_create(&z_user, p0, p1); |
||
86 | |||
87 | |||
88 | |||
89 | |||
90 | { |
||
91 | u32_t page; |
||
92 | if( mem_table[i].type != 1) |
||
93 | continue; |
||
94 | page = (mem_table[i].base+mem_table[i].size)&(~4095); |
||
95 | if(page > last_page) |
||
96 | last_page = page; |
||
97 | |||
98 | |||
99 | zone_release(&z_user,mem_table[i].base>>12, mem_table[i].size>>12); |
||
100 | }; |
||
101 | zone_reserve(&z_core, 0x100000>>12,(pg_balloc-OS_BASE-0x100000)>>12); |
||
102 | #endif |
||
103 | }; |
||
104 | |||
105 | |||
106 | { |
||
107 | unsigned int i; |
||
108 | // int znum; |
||
109 | |||
110 | |||
111 | * nobody tries to do that. If some platform requires, remove |
||
112 | * the assert |
||
113 | */ |
||
114 | // ASSERT(confframe); |
||
115 | /* If conframe is supposed to be inside our zone, then make sure |
||
116 | * it does not span kernel & init |
||
117 | */ |
||
118 | |||
119 | |||
120 | |||
121 | |||
122 | z->base = start; |
||
123 | z->count = count; |
||
124 | z->free_count = count; |
||
125 | z->busy_count = 0; |
||
126 | |||
127 | |||
128 | |||
129 | |||
130 | |||
131 | |||
132 | list_initialize(&z->order[i]); |
||
133 | |||
134 | |||
135 | |||
136 | |||
137 | frame_initialize(&z->frames[i]); |
||
138 | } |
||
139 | } |
||
140 | |||
141 | |||
142 | { |
||
143 | int i; |
||
144 | pfn_t top = base+count; |
||
145 | |||
146 | |||
147 | return; |
||
148 | |||
149 | |||
150 | base = z->base; |
||
151 | |||
152 | |||
153 | top = z->base+z->count; |
||
154 | |||
155 | |||
862 | serge | 156 | |
854 | serge | 157 | |
158 | zone_mark_unavailable(z, i - z->base); |
||
159 | |||
160 | |||
161 | |||
162 | |||
163 | { |
||
164 | int i; |
||
165 | pfn_t top = base+count; |
||
166 | |||
167 | |||
168 | return; |
||
169 | |||
170 | |||
171 | base = z->base; |
||
172 | |||
173 | |||
174 | top = z->base+z->count; |
||
175 | |||
176 | |||
862 | serge | 177 | |
854 | serge | 178 | |
179 | z->frames[i-z->base].refcount = 0; |
||
180 | buddy_system_free(z, &z->frames[i-z->base].buddy_link); |
||
181 | } |
||
182 | }; |
||
183 | |||
184 | |||
185 | |||
186 | { |
||
187 | return (index_t) (frame - zone->frames); |
||
188 | } |
||
189 | |||
190 | |||
191 | { |
||
192 | return (index_t) (frame - zone->frames); |
||
193 | } |
||
194 | |||
195 | |||
196 | { |
||
197 | return (index < zone->count); |
||
198 | } |
||
199 | |||
200 | |||
201 | static inline index_t make_frame_index(zone_t *zone, frame_t *frame) |
||
202 | { |
||
203 | return (frame - zone->frames); |
||
204 | } |
||
205 | |||
206 | |||
207 | { |
||
208 | frame->refcount = 1; |
||
209 | frame->buddy_order = 0; |
||
210 | } |
||
211 | |||
212 | |||
213 | |||
214 | u32_t order) |
||
215 | { |
||
216 | frame_t *frame; |
||
217 | index_t index; |
||
218 | |||
219 | |||
220 | |||
221 | |||
222 | do { |
||
223 | if (zone->frames[index].buddy_order != order) { |
||
224 | return &zone->frames[index].buddy_link; |
||
225 | } |
||
226 | } while(index-- > 0); |
||
227 | return NULL; |
||
228 | } |
||
229 | |||
230 | |||
231 | frame_t *frame_l, *frame_r; |
||
232 | |||
233 | |||
234 | frame_r = (frame_l + (1 << (frame_l->buddy_order - 1))); |
||
235 | |||
236 | |||
237 | } |
||
238 | |||
239 | |||
240 | frame_t *frame = (frame_t*)block; |
||
241 | return frame->buddy_order; |
||
242 | } |
||
243 | |||
244 | |||
245 | u32_t order) { |
||
246 | frame_t *frame = (frame_t*)block; |
||
247 | frame->buddy_order = order; |
||
248 | } |
||
249 | |||
250 | |||
251 | link_t *block_2) |
||
252 | { |
||
253 | frame_t *frame1, *frame2; |
||
254 | |||
255 | |||
256 | frame2 = (frame_t*)block_2; |
||
257 | |||
258 | |||
259 | } |
||
260 | |||
261 | |||
262 | frame_t * frame = (frame_t*)block; |
||
263 | frame->refcount = 1; |
||
264 | } |
||
265 | |||
266 | |||
267 | frame_t *frame = (frame_t*)block; |
||
268 | frame->refcount = 0; |
||
269 | } |
||
270 | |||
271 | |||
272 | ((~(((u32_t) -1) << (order)) & (index)) == 0) |
||
273 | #define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) \ |
||
274 | (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0) |
||
275 | |||
276 | |||
277 | (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1) |
||
278 | |||
279 | |||
280 | { |
||
281 | frame_t *frame; |
||
282 | index_t index; |
||
283 | u32_t is_left, is_right; |
||
284 | |||
285 | |||
286 | ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame),frame->buddy_order)); |
||
287 | |||
288 | |||
289 | is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame); |
||
290 | |||
291 | |||
292 | if (is_left) { |
||
293 | index = (frame_index(zone, frame)) + (1 << frame->buddy_order); |
||
294 | } else { /* if (is_right) */ |
||
295 | index = (frame_index(zone, frame)) - (1 << frame->buddy_order); |
||
296 | } |
||
297 | |||
298 | |||
299 | if (zone->frames[index].buddy_order == frame->buddy_order && |
||
300 | zone->frames[index].refcount == 0) { |
||
301 | return &zone->frames[index].buddy_link; |
||
302 | } |
||
303 | } |
||
304 | |||
305 | |||
306 | } |
||
307 | |||
308 | |||
309 | { |
||
310 | link_t *left,*right, *tmp; |
||
311 | u32_t order; |
||
312 | |||
313 | |||
314 | ASSERT(left); |
||
315 | list_remove(left); |
||
316 | while (1) { |
||
317 | if (! buddy_get_order(z,left)) { |
||
318 | buddy_mark_busy(z, left); |
||
319 | return left; |
||
320 | } |
||
321 | |||
322 | |||
323 | |||
324 | |||
325 | buddy_set_order(z, left, order-1); |
||
326 | buddy_set_order(z, right, order-1); |
||
327 | |||
328 | |||
329 | |||
330 | |||
331 | right = left; |
||
332 | left = tmp; |
||
333 | } |
||
334 | ASSERT(tmp == left); |
||
335 | buddy_mark_busy(z, left); |
||
336 | buddy_system_free(z, right); |
||
337 | buddy_mark_available(z, left); |
||
338 | } |
||
339 | } |
||
340 | |||
341 | |||
342 | { |
||
343 | link_t *buddy, *hlp; |
||
344 | u8_t i; |
||
345 | |||
346 | |||
347 | * Determine block's order. |
||
348 | */ |
||
349 | i = buddy_get_order(z, block); |
||
350 | |||
351 | |||
352 | |||
353 | |||
354 | /* |
||
355 | * See if there is any buddy in the list of order i. |
||
356 | */ |
||
357 | buddy = find_buddy(z, block); |
||
358 | if (buddy) { |
||
359 | |||
360 | |||
361 | /* |
||
362 | * Remove buddy from the list of order i. |
||
363 | */ |
||
364 | list_remove(buddy); |
||
365 | |||
366 | |||
367 | * Invalidate order of both block and buddy. |
||
368 | */ |
||
369 | buddy_set_order(z, block, BUDDY_SYSTEM_INNER_BLOCK); |
||
370 | buddy_set_order(z, buddy, BUDDY_SYSTEM_INNER_BLOCK); |
||
371 | |||
372 | |||
373 | * Coalesce block and buddy into one block. |
||
374 | */ |
||
375 | hlp = buddy_coalesce(z, block, buddy); |
||
376 | |||
377 | |||
378 | * Set order of the coalesced block to i + 1. |
||
379 | */ |
||
380 | buddy_set_order(z, hlp, i + 1); |
||
381 | |||
382 | |||
383 | * Recursively add the coalesced block to the list of order i + 1. |
||
384 | */ |
||
385 | buddy_system_free(z, hlp); |
||
386 | return; |
||
387 | } |
||
388 | } |
||
389 | |||
390 | |||
391 | * Insert block into the list of order i. |
||
392 | */ |
||
393 | list_append(block, &z->order[i]); |
||
394 | |||
395 | |||
396 | |||
397 | |||
398 | { |
||
399 | ASSERT(frame_idx < zone->count); |
||
400 | return &zone->frames[frame_idx]; |
||
401 | } |
||
402 | |||
403 | |||
404 | { |
||
405 | frame_t *frame; |
||
406 | link_t *link; |
||
407 | |||
408 | |||
409 | if (frame->refcount) |
||
410 | return; |
||
411 | link = buddy_system_alloc_block(zone, &frame->buddy_link); |
||
412 | ASSERT(link); |
||
413 | zone->free_count--; |
||
414 | } |
||
415 | |||
416 | |||
417 | { |
||
418 | link_t *res, *hlp; |
||
419 | |||
420 | |||
421 | |||
422 | |||
423 | * If the list of order i is not empty, |
||
424 | * the request can be immediatelly satisfied. |
||
425 | */ |
||
426 | if (!list_empty(&z->order[i])) { |
||
427 | res = z->order[i].next; |
||
428 | list_remove(res); |
||
429 | buddy_mark_busy(z, res); |
||
430 | return res; |
||
431 | } |
||
432 | /* |
||
433 | * If order i is already the maximal order, |
||
434 | * the request cannot be satisfied. |
||
435 | */ |
||
436 | if (i == z->max_order) |
||
437 | return NULL; |
||
438 | |||
439 | |||
440 | * Try to recursively satisfy the request from higher order lists. |
||
441 | */ |
||
442 | hlp = buddy_system_alloc(z, i + 1); |
||
443 | |||
444 | |||
445 | * The request could not be satisfied |
||
446 | * from higher order lists. |
||
447 | */ |
||
448 | if (!hlp) |
||
449 | return NULL; |
||
450 | |||
451 | |||
452 | |||
453 | |||
454 | * Bisect the block and set order of both of its parts to i. |
||
455 | */ |
||
456 | hlp = buddy_bisect(z, res); |
||
457 | buddy_set_order(z, res, i); |
||
458 | buddy_set_order(z, hlp, i); |
||
459 | |||
460 | |||
461 | * Return the other half to buddy system. Mark the first part |
||
462 | * full, so that it won't coalesce again. |
||
463 | */ |
||
464 | buddy_mark_busy(z, res); |
||
465 | buddy_system_free(z, hlp); |
||
466 | |||
467 | |||
468 | |||
469 | |||
470 | |||
471 | |||
472 | |||
473 | { |
||
474 | pfn_t v; |
||
475 | link_t *tmp; |
||
476 | frame_t *frame; |
||
477 | |||
478 | |||
479 | |||
480 | tmp = buddy_system_alloc(zone, order); |
||
481 | |||
482 | |||
483 | |||
484 | |||
485 | zone->free_count -= (1 << order); |
||
486 | zone->busy_count += (1 << order); |
||
487 | |||
488 | |||
489 | frame = (frame_t*)tmp; |
||
490 | |||
491 | |||
492 | v = make_frame_index(zone, frame); |
||
493 | |||
859 | serge | 494 | |
854 | serge | 495 | } |
496 | |||
497 | |||
498 | |||
499 | void __fastcall frame_set_parent(pfn_t pfn, void *data) |
||
500 | { |
||
501 | /* zone_t *zone = find_zone_and_lock(pfn, &hint); |
||
502 | ASSERT(zone); |
||
503 | */ |
||
504 | |||
505 | |||
506 | zone_get_frame(&z_core, pfn-z_core.base)->parent = data; |
||
507 | spinlock_unlock(&z_core.lock); |
||
508 | } |
||
509 | |||
510 | |||
859 | serge | 511 | { |
512 | // zone_t *zone = find_zone_and_lock(pfn, &hint); |
||
513 | void *res; |
||
514 | |||
854 | serge | 515 | |
859 | serge | 516 | res = zone_get_frame(&z_core, pfn)->parent; |
517 | spinlock_unlock(&z_core.lock); |
||
518 | |||
519 | |||
520 | } |
||
521 | |||
522 | |||
854 | serge | 523 | { |
524 | int n; |
||
525 | asm volatile ( |
||
526 | "xor eax, eax \n\t" |
||
527 | "bsr eax, edx \n\t" |
||
528 | "inc eax" |
||
529 | :"=a" (n) |
||
530 | :"d"(arg) |
||
531 | ); |
||
532 | return n; |
||
533 | } |
||
534 | |||
535 | |||
536 | |||
537 | { |
||
538 | eflags_t efl; |
||
539 | pfn_t v; |
||
540 | |||
541 | |||
542 | spinlock_lock(&zone->lock); |
||
543 | v = zone_frame_alloc(zone, order); |
||
544 | v += zone->base; |
||
545 | spinlock_unlock(&zone->lock); |
||
546 | safe_sti(efl); |
||
547 | |||
548 | |||
549 | } |
||
550 | |||
551 | |||
859 | serge | 552 | { |
854 | serge | 553 | eflags_t efl; |
554 | pfn_t v; |
||
555 | |||
556 | |||
557 | spinlock_lock(&z_core.lock); |
||
558 | v = zone_frame_alloc(&z_core, order); |
||
559 | spinlock_unlock(&z_core.lock); |
||
560 | safe_sti(efl); |
||
561 | |||
562 | |||
563 | }; |
||
564 | |||
565 | |||
859 | serge | 566 | { |
854 | serge | 567 | eflags_t efl; |
568 | |||
859 | serge | 569 | |
570 | spinlock_lock(&z_core.lock); |
||
571 | zone_free(&z_core, frame>>12); |
||
572 | spinlock_unlock(&z_core.lock); |
||
573 | safe_sti(efl); |
||
574 | } |
||
575 | |||
576 | |||
577 | { |
||
578 | eflags_t efl; |
||
579 | u32_t edx; |
||
854 | serge | 580 | pfn_t v; |
581 | |||
582 | |||
583 | efl = safe_cli(); |
||
584 | spinlock_lock(&z_core.lock); |
||
585 | v = zone_frame_alloc(&z_core, 0); |
||
586 | spinlock_unlock(&z_core.lock); |
||
587 | safe_sti(efl); |
||
588 | |||
861 | serge | 589 | |
862 | serge | 590 | |
861 | serge | 591 | |
854 | serge | 592 | return (v << FRAME_WIDTH); |
593 | }; |
||
594 | |||
595 | |||
596 | { |
||
597 | eflags_t efl; |
||
598 | u32_t edx; |
||
599 | pfn_t v; |
||
600 | |||
601 | |||
602 | |||
603 | |||
604 | efl = safe_cli(); |
||
605 | spinlock_lock(&z_core.lock); |
||
606 | v = zone_frame_alloc(&z_core, to_order(count)); |
||
607 | spinlock_unlock(&z_core.lock); |
||
608 | safe_sti(efl); |
||
609 | |||
861 | serge | 610 | |
862 | serge | 611 | |
861 | serge | 612 | |
854 | serge | 613 | |
614 | |||
615 | }; |
||
616 | |||
617 | |||
618 | |||
619 | { |
||
620 | frame_t *frame; |
||
621 | u32_t order; |
||
622 | |||
623 | |||
624 | |||
625 | |||
626 | order = frame->buddy_order; |
||
627 | |||
628 | |||
629 | |||
630 | |||
631 | buddy_system_free(zone, &frame->buddy_link); |
||
632 | |||
633 | |||
634 | zone->free_count += (1 << order); |
||
635 | zone->busy_count -= (1 << order); |
||
636 | } |
||
637 | } |
||
638 | |||
639 | |||
640 | { |
||
641 | eflags_t efl; |
||
642 | zone_t *zone; |
||
643 | |||
644 | |||
645 | spinlock_lock(&z_core.lock); |
||
646 | zone_free(&z_core, frame>>12); |
||
647 | spinlock_unlock(&z_core.lock); |
||
648 | safe_sti(efl); |
||
649 | } |
||
650 | |||
651 | |||
859 | serge | 652 | { |
653 | return z_core.free_count; |
||
654 | }><>><>><>><>><>><>><>><>><>><>=>>=>><>><>><>>><>>>>>>>>>=>>> |
||
655 |