Subversion Repositories Kolibri OS

Rev

Rev 861 | Rev 864 | 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