Subversion Repositories Kolibri OS

Rev

Rev 888 | Rev 908 | 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 ("movl %%edx, %0":"=r"(val));
886 serge 19
  return val;
854 serge 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;
889 serge 165
    pfn_t top = base+count;
166
854 serge 167
 
889 serge 168
        return;
169
854 serge 170
 
889 serge 171
        base = z->base;
172
854 serge 173
 
889 serge 174
        top = z->base+z->count;
175
854 serge 176
 
889 serge 177
854 serge 178
 
889 serge 179
        z->frames[i-z->base].refcount = 0;
180
        buddy_system_free(z, &z->frames[i-z->base].buddy_link);
181
    }
854 serge 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;
889 serge 263
	frame->refcount = 1;
854 serge 264
}
265
266
 
267
    frame_t *frame = (frame_t*)block;
889 serge 268
	frame->refcount = 0;
854 serge 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;
889 serge 284
854 serge 285
 
889 serge 286
    ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame),frame->buddy_order));
287
854 serge 288
 
289
	is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame);
290
291
 
889 serge 292
	if (is_left) {
854 serge 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;
889 serge 312
854 serge 313
 
889 serge 314
    ASSERT(left);
315
	list_remove(left);
854 serge 316
	while (1) {
317
        if (! buddy_get_order(z,left)) {
889 serge 318
            buddy_mark_busy(z, left);
319
			return left;
854 serge 320
		}
321
322
 
889 serge 323
854 serge 324
 
889 serge 325
        buddy_set_order(z, left, order-1);
326
        buddy_set_order(z, right, order-1);
327
854 serge 328
 
889 serge 329
854 serge 330
 
889 serge 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
	}
854 serge 339
}
340
341
 
342
{
343
    link_t *buddy, *hlp;
889 serge 344
    u8_t i;
345
854 serge 346
 
889 serge 347
	 * Determine block's order.
854 serge 348
	 */
349
    i = buddy_get_order(z, block);
889 serge 350
854 serge 351
 
889 serge 352
854 serge 353
 
889 serge 354
		/*
854 serge 355
		 * See if there is any buddy in the list of order i.
356
		 */
357
        buddy = find_buddy(z, block);
889 serge 358
		if (buddy) {
854 serge 359
360
 
889 serge 361
			/*
854 serge 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);
889 serge 370
            buddy_set_order(z, buddy, BUDDY_SYSTEM_INNER_BLOCK);
371
854 serge 372
 
373
			 * Coalesce block and buddy into one block.
374
			 */
375
            hlp = buddy_coalesce(z, block, buddy);
889 serge 376
854 serge 377
 
378
			 * Set order of the coalesced block to i + 1.
379
			 */
380
            buddy_set_order(z, hlp, i + 1);
889 serge 381
854 serge 382
 
383
			 * Recursively add the coalesced block to the list of order i + 1.
384
			 */
385
            buddy_system_free(z, hlp);
889 serge 386
			return;
854 serge 387
		}
388
	}
389
	/*
390
	 * Insert block into the list of order i.
391
	 */
392
    list_append(block, &z->order[i]);
889 serge 393
}
854 serge 394
395
 
396
{
397
    ASSERT(frame_idx < zone->count);
889 serge 398
	return &zone->frames[frame_idx];
854 serge 399
}
400
401
 
402
{
403
	frame_t *frame;
404
	link_t *link;
405
406
 
407
	if (frame->refcount)
408
		return;
409
    link = buddy_system_alloc_block(zone, &frame->buddy_link);
889 serge 410
    ASSERT(link);
411
	zone->free_count--;
854 serge 412
}
413
414
 
415
{
416
	link_t *res, *hlp;
417
418
 
889 serge 419
854 serge 420
 
421
	 * If the list of order i is not empty,
422
	 * the request can be immediatelly satisfied.
423
	 */
424
	if (!list_empty(&z->order[i])) {
425
		res = z->order[i].next;
426
		list_remove(res);
427
		buddy_mark_busy(z, res);
428
		return res;
429
	}
430
	/*
431
	 * If order i is already the maximal order,
432
	 * the request cannot be satisfied.
433
	 */
434
	if (i == z->max_order)
435
		return NULL;
436
437
 
438
	 * Try to recursively satisfy the request from higher order lists.
439
	 */
440
	hlp = buddy_system_alloc(z, i + 1);
441
442
 
443
	 * The request could not be satisfied
444
	 * from higher order lists.
445
	 */
446
	if (!hlp)
447
		return NULL;
448
449
 
450
451
 
452
	 * Bisect the block and set order of both of its parts to i.
453
	 */
454
	hlp = buddy_bisect(z, res);
455
	buddy_set_order(z, res, i);
456
	buddy_set_order(z, hlp, i);
457
458
 
459
	 * Return the other half to buddy system. Mark the first part
460
	 * full, so that it won't coalesce again.
461
	 */
462
	buddy_mark_busy(z, res);
463
	buddy_system_free(z, hlp);
464
465
 
466
467
 
468
469
 
470
 
471
{
472
	pfn_t v;
473
	link_t *tmp;
474
	frame_t *frame;
475
476
 
477
 
478
	tmp = buddy_system_alloc(zone, order);
479
480
 
889 serge 481
854 serge 482
 
483
	zone->free_count -= (1 << order);
484
	zone->busy_count += (1 << order);
485
486
 
487
	frame = (frame_t*)tmp;
488
489
 
490
	v = make_frame_index(zone, frame);
491
859 serge 492
 
854 serge 493
}
494
495
 
496
 
497
void __fastcall frame_set_parent(pfn_t pfn, void *data)
498
{
499
/*  zone_t *zone = find_zone_and_lock(pfn, &hint);
500
  ASSERT(zone);
501
 */
502
503
 
504
    zone_get_frame(&z_core, pfn-z_core.base)->parent = data;
505
  spinlock_unlock(&z_core.lock);
506
}
507
508
 
859 serge 509
{
510
//	zone_t *zone = find_zone_and_lock(pfn, &hint);
511
	void *res;
512
854 serge 513
 
859 serge 514
    res = zone_get_frame(&z_core, pfn)->parent;
515
  spinlock_unlock(&z_core.lock);
516
517
 
518
}
519
520
 
854 serge 521
{
522
  int n;
523
  asm volatile (
524
                "xorl %eax, %eax \n\t"
886 serge 525
                "bsr %edx, %eax \n\t"
526
                "incl %eax"
527
                :"=a" (n)
854 serge 528
                :"d"(arg)
529
                );
530
	return n;
531
}
532
533
 
534
 
535
{
536
   eflags_t efl;
537
   pfn_t v;
538
539
 
540
     spinlock_lock(&zone->lock);
541
       v = zone_frame_alloc(zone, order);
542
       v += zone->base;
543
     spinlock_unlock(&zone->lock);
544
   safe_sti(efl);
545
546
 
547
}
548
549
 
888 serge 550
{
854 serge 551
   eflags_t efl;
552
   pfn_t v;
553
554
 
555
     spinlock_lock(&z_core.lock);
556
       v = zone_frame_alloc(&z_core, order);
557
     spinlock_unlock(&z_core.lock);
558
   safe_sti(efl);
559
888 serge 560
 
561
        ((1<
562
563
 
854 serge 564
};
565
566
 
888 serge 567
{
854 serge 568
   eflags_t efl;
569
859 serge 570
 
571
     spinlock_lock(&z_core.lock);
572
       zone_free(&z_core, frame>>12);
573
     spinlock_unlock(&z_core.lock);
574
   safe_sti(efl);
575
888 serge 576
 
577
578
 
859 serge 579
580
 
581
{
582
   eflags_t efl;
583
   u32_t    edx;
854 serge 584
   pfn_t v;
585
586
 
587
   efl = safe_cli();
588
     spinlock_lock(&z_core.lock);
589
       v = zone_frame_alloc(&z_core, 0);
590
     spinlock_unlock(&z_core.lock);
591
   safe_sti(efl);
592
861 serge 593
 
888 serge 594
861 serge 595
 
854 serge 596
   return (v << FRAME_WIDTH);
597
};
598
599
 
600
{
601
	frame_t *frame;
602
    u32_t order;
889 serge 603
854 serge 604
 
605
606
 
607
	order = frame->buddy_order;
608
609
 
889 serge 610
854 serge 611
 
888 serge 612
    {
613
		buddy_system_free(zone, &frame->buddy_link);
854 serge 614
615
 
616
		zone->free_count += (1 << order);
617
		zone->busy_count -= (1 << order);
618
	}
619
}
620
621
 
622
{
623
   eflags_t efl;
624
   zone_t *zone;
625
626
 
627
     spinlock_lock(&z_core.lock);
628
       zone_free(&z_core, frame>>12);
629
     spinlock_unlock(&z_core.lock);
630
  safe_sti(efl);
631
}
632
633
 
859 serge 634
{
635
   return z_core.free_count;
636
}
637