Subversion Repositories Kolibri OS

Rev

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