Subversion Repositories HelenOS

Rev

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

Rev 2121 Rev 2122
Line 91... Line 91...
91
 * Some of the attributes in zone_t structures are 'read-only'
91
 * Some of the attributes in zone_t structures are 'read-only'
92
 */
92
 */
93
 
93
 
94
typedef struct {
94
typedef struct {
95
    SPINLOCK_DECLARE(lock);
95
    SPINLOCK_DECLARE(lock);
96
    int count;
96
    unsigned int count;
97
    zone_t *info[ZONES_MAX];
97
    zone_t *info[ZONES_MAX];
98
} zones_t;
98
} zones_t;
99
 
99
 
100
static zones_t zones;
100
static zones_t zones;
101
 
101
 
Line 142... Line 142...
142
 * @param newzone New zone to be inserted into zone list
142
 * @param newzone New zone to be inserted into zone list
143
 * @return zone number on success, -1 on error
143
 * @return zone number on success, -1 on error
144
 */
144
 */
145
static int zones_add_zone(zone_t *newzone)
145
static int zones_add_zone(zone_t *newzone)
146
{
146
{
147
    int i,j;
147
    unsigned int i, j;
148
    ipl_t ipl;
148
    ipl_t ipl;
149
    zone_t *z;
149
    zone_t *z;
150
 
150
 
151
    ipl = interrupts_disable();
151
    ipl = interrupts_disable();
152
    spinlock_lock(&zones.lock);
152
    spinlock_lock(&zones.lock);
Line 183... Line 183...
183
 * @param frame Frame number contained in zone
183
 * @param frame Frame number contained in zone
184
 * @param pzone If not null, it is used as zone hint. Zone index
184
 * @param pzone If not null, it is used as zone hint. Zone index
185
 *              is filled into the variable on success.
185
 *              is filled into the variable on success.
186
 * @return Pointer to locked zone containing frame
186
 * @return Pointer to locked zone containing frame
187
 */
187
 */
188
static zone_t * find_zone_and_lock(pfn_t frame, int *pzone)
188
static zone_t * find_zone_and_lock(pfn_t frame, unsigned int *pzone)
189
{
189
{
190
    int i;
190
    unsigned int i;
191
    int hint = pzone ? *pzone : 0;
191
    unsigned int hint = pzone ? *pzone : 0;
192
    zone_t *z;
192
    zone_t *z;
193
   
193
   
194
    spinlock_lock(&zones.lock);
194
    spinlock_lock(&zones.lock);
195
 
195
 
196
    if (hint >= zones.count || hint < 0)
196
    if (hint >= zones.count || hint < 0)
Line 230... Line 230...
230
 * @param order Size (2^order) of free space we are trying to find
230
 * @param order Size (2^order) of free space we are trying to find
231
 * @param pzone Pointer to preferred zone or NULL, on return contains zone number
231
 * @param pzone Pointer to preferred zone or NULL, on return contains zone number
232
 */
232
 */
233
static zone_t * find_free_zone_and_lock(uint8_t order, int *pzone)
233
static zone_t * find_free_zone_and_lock(uint8_t order, int *pzone)
234
{
234
{
235
    int i;
235
    unsigned int i;
236
    zone_t *z;
236
    zone_t *z;
237
    int hint = pzone ? *pzone : 0;
237
    unsigned int hint = pzone ? *pzone : 0;
238
   
238
   
239
    spinlock_lock(&zones.lock);
239
    spinlock_lock(&zones.lock);
240
    if (hint >= zones.count)
240
    if (hint >= zones.count)
241
        hint = 0;
241
        hint = 0;
242
    i = hint;
242
    i = hint;
Line 537... Line 537...
537
 * @param z2 Zone to merge
537
 * @param z2 Zone to merge
538
 */
538
 */
539
static void _zone_merge(zone_t *z, zone_t *z1, zone_t *z2)
539
static void _zone_merge(zone_t *z, zone_t *z1, zone_t *z2)
540
{
540
{
541
    uint8_t max_order;
541
    uint8_t max_order;
-
 
542
    unsigned int i;
542
    int i, z2idx;
543
    int z2idx;
543
    pfn_t frame_idx;
544
    pfn_t frame_idx;
544
    frame_t *frame;
545
    frame_t *frame;
545
 
546
 
546
    ASSERT(!overlaps(z1->base,z1->count,z2->base,z2->count));
547
    ASSERT(!overlaps(z1->base,z1->count,z2->base,z2->count));
547
    ASSERT(z1->base < z2->base);
548
    ASSERT(z1->base < z2->base);
Line 559... Line 560...
559
    z->buddy_system = (buddy_system_t *)&z[1];
560
    z->buddy_system = (buddy_system_t *)&z[1];
560
    buddy_system_create(z->buddy_system, max_order,
561
    buddy_system_create(z->buddy_system, max_order,
561
                &zone_buddy_system_operations,
562
                &zone_buddy_system_operations,
562
                (void *) z);
563
                (void *) z);
563
 
564
 
564
    z->frames = (frame_t *)((void *)z->buddy_system+buddy_conf_size(max_order));
565
    z->frames = (frame_t *)((uint8_t *) z->buddy_system + buddy_conf_size(max_order));
565
    for (i = 0; i < z->count; i++) {
566
    for (i = 0; i < z->count; i++) {
566
        /* This marks all frames busy */
567
        /* This marks all frames busy */
567
        frame_initialize(&z->frames[i]);
568
        frame_initialize(&z->frames[i]);
568
    }
569
    }
569
    /* Copy frames from both zones to preserve full frame orders,
570
    /* Copy frames from both zones to preserve full frame orders,
Line 571... Line 572...
571
     * we add all free frames to buddy allocator later again, clear
572
     * we add all free frames to buddy allocator later again, clear
572
     * order to 0. Don't set busy frames with refcount=0, as they
573
     * order to 0. Don't set busy frames with refcount=0, as they
573
     * will not be reallocated during merge and it would make later
574
     * will not be reallocated during merge and it would make later
574
     * problems with allocation/free.
575
     * problems with allocation/free.
575
     */
576
     */
576
    for (i=0; i<z1->count; i++)
577
    for (i = 0; i < z1->count; i++)
577
        z->frames[i] = z1->frames[i];
578
        z->frames[i] = z1->frames[i];
578
    for (i=0; i < z2->count; i++) {
579
    for (i = 0; i < z2->count; i++) {
579
        z2idx = i + (z2->base - z1->base);
580
        z2idx = i + (z2->base - z1->base);
580
        z->frames[z2idx] = z2->frames[i];
581
        z->frames[z2idx] = z2->frames[i];
581
    }
582
    }
582
    i = 0;
583
    i = 0;
583
    while (i < z->count) {
584
    while (i < z->count) {
Line 621... Line 622...
621
static void return_config_frames(zone_t *newzone, zone_t *oldzone)
622
static void return_config_frames(zone_t *newzone, zone_t *oldzone)
622
{
623
{
623
    pfn_t pfn;
624
    pfn_t pfn;
624
    frame_t *frame;
625
    frame_t *frame;
625
    count_t cframes;
626
    count_t cframes;
626
    int i;
627
    unsigned int i;
627
 
628
 
628
    pfn = ADDR2PFN((uintptr_t)KA2PA(oldzone));
629
    pfn = ADDR2PFN((uintptr_t)KA2PA(oldzone));
629
    cframes = SIZE2FRAMES(zone_conf_size(oldzone->count));
630
    cframes = SIZE2FRAMES(zone_conf_size(oldzone->count));
630
   
631
   
631
    if (pfn < newzone->base || pfn >= newzone->base + newzone->count)
632
    if (pfn < newzone->base || pfn >= newzone->base + newzone->count)
632
        return;
633
        return;
633
 
634
 
634
    frame = &newzone->frames[pfn - newzone->base];
635
    frame = &newzone->frames[pfn - newzone->base];
635
    ASSERT(!frame->buddy_order);
636
    ASSERT(!frame->buddy_order);
636
 
637
 
637
    for (i=0; i < cframes; i++) {
638
    for (i = 0; i < cframes; i++) {
638
        newzone->busy_count++;
639
        newzone->busy_count++;
639
        zone_frame_free(newzone, pfn+i-newzone->base);
640
        zone_frame_free(newzone, pfn+i-newzone->base);
640
    }
641
    }
641
}
642
}
642
 
643
 
Line 655... Line 656...
655
{
656
{
656
    count_t i;
657
    count_t i;
657
    uint8_t order;
658
    uint8_t order;
658
    frame_t *frame;
659
    frame_t *frame;
659
   
660
   
660
    ASSERT(frame_idx+count < zone->count);
661
    ASSERT(frame_idx + count < zone->count);
661
 
662
 
662
    order = zone->frames[frame_idx].buddy_order;
663
    order = zone->frames[frame_idx].buddy_order;
663
    ASSERT((1 << order) >= count);
664
    ASSERT((count_t) (1 << order) >= count);
664
 
665
 
665
    /* Reduce all blocks to order 0 */
666
    /* Reduce all blocks to order 0 */
666
    for (i=0; i < (1 << order); i++) {
667
    for (i = 0; i < (count_t) (1 << order); i++) {
667
        frame = &zone->frames[i + frame_idx];
668
        frame = &zone->frames[i + frame_idx];
668
        frame->buddy_order = 0;
669
        frame->buddy_order = 0;
669
        if (! frame->refcount)
670
        if (! frame->refcount)
670
            frame->refcount = 1;
671
            frame->refcount = 1;
671
        ASSERT(frame->refcount == 1);
672
        ASSERT(frame->refcount == 1);
672
    }
673
    }
673
    /* Free unneeded frames */
674
    /* Free unneeded frames */
674
    for (i=count; i < (1 << order); i++) {
675
    for (i = count; i < (count_t) (1 << order); i++) {
675
        zone_frame_free(zone, i + frame_idx);
676
        zone_frame_free(zone, i + frame_idx);
676
    }
677
    }
677
}
678
}
678
 
679
 
679
/** Merge zones z1 and z2
680
/** Merge zones z1 and z2
Line 683... Line 684...
683
 *
684
 *
684
 * - When you create a new zone, the frame allocator configuration does
685
 * - When you create a new zone, the frame allocator configuration does
685
 *   not to be 2^order size. Once the allocator is running it is no longer
686
 *   not to be 2^order size. Once the allocator is running it is no longer
686
 *   possible, merged configuration data occupies more space :-/
687
 *   possible, merged configuration data occupies more space :-/
687
 */
688
 */
688
void zone_merge(int z1, int z2)
689
void zone_merge(unsigned int z1, unsigned int z2)
689
{
690
{
690
    ipl_t ipl;
691
    ipl_t ipl;
691
    zone_t *zone1, *zone2, *newzone;
692
    zone_t *zone1, *zone2, *newzone;
692
    int cframes;
693
    unsigned int cframes;
693
    uint8_t order;
694
    uint8_t order;
694
    int i;
695
    unsigned int i;
695
    pfn_t pfn;
696
    pfn_t pfn;
696
 
697
 
697
    ipl = interrupts_disable();
698
    ipl = interrupts_disable();
698
    spinlock_lock(&zones.lock);
699
    spinlock_lock(&zones.lock);
699
 
700
 
Line 720... Line 721...
720
    else if (zone_can_alloc(zone2, order))
721
    else if (zone_can_alloc(zone2, order))
721
        pfn = zone2->base + zone_frame_alloc(zone2, order);
722
        pfn = zone2->base + zone_frame_alloc(zone2, order);
722
    else
723
    else
723
        goto errout2;
724
        goto errout2;
724
 
725
 
725
    newzone = (zone_t *)PA2KA(PFN2ADDR(pfn));
726
    newzone = (zone_t *) PA2KA(PFN2ADDR(pfn));
726
 
727
 
727
    _zone_merge(newzone, zone1, zone2);
728
    _zone_merge(newzone, zone1, zone2);
728
 
729
 
729
    /* Free unneeded config frames */
730
    /* Free unneeded config frames */
730
    zone_reduce_region(newzone, pfn - newzone->base,  cframes);
731
    zone_reduce_region(newzone, pfn - newzone->base,  cframes);
Line 777... Line 778...
777
 *
778
 *
778
 * @return Initialized zone.
779
 * @return Initialized zone.
779
 */
780
 */
780
static void zone_construct(pfn_t start, count_t count, zone_t *z, int flags)
781
static void zone_construct(pfn_t start, count_t count, zone_t *z, int flags)
781
{
782
{
782
    int i;
783
    unsigned int i;
783
    uint8_t max_order;
784
    uint8_t max_order;
784
 
785
 
785
    spinlock_initialize(&z->lock, "zone_lock");
786
    spinlock_initialize(&z->lock, "zone_lock");
786
    z->base = start;
787
    z->base = start;
787
    z->count = count;
788
    z->count = count;
Line 799... Line 800...
799
                &zone_buddy_system_operations,
800
                &zone_buddy_system_operations,
800
                (void *) z);
801
                (void *) z);
801
   
802
   
802
    /* Allocate frames _after_ the conframe */
803
    /* Allocate frames _after_ the conframe */
803
    /* Check sizes */
804
    /* Check sizes */
804
    z->frames = (frame_t *)((void *)z->buddy_system+buddy_conf_size(max_order));
805
    z->frames = (frame_t *)((uint8_t *) z->buddy_system + buddy_conf_size(max_order));
805
    for (i = 0; i<count; i++) {
806
    for (i = 0; i < count; i++) {
806
        frame_initialize(&z->frames[i]);
807
        frame_initialize(&z->frames[i]);
807
    }
808
    }
808
   
809
   
809
    /* Stuffing frames */
810
    /* Stuffing frames */
810
    for (i = 0; i < count; i++) {
811
    for (i = 0; i < count; i++) {
Line 846... Line 847...
846
int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags)
847
int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags)
847
{
848
{
848
    zone_t *z;
849
    zone_t *z;
849
    uintptr_t addr;
850
    uintptr_t addr;
850
    count_t confcount;
851
    count_t confcount;
851
    int i;
852
    unsigned int i;
852
    int znum;
853
    int znum;
853
 
854
 
854
    /* Theoretically we could have here 0, practically make sure
855
    /* Theoretically we could have here 0, practically make sure
855
     * nobody tries to do that. If some platform requires, remove
856
     * nobody tries to do that. If some platform requires, remove
856
     * the assert
857
     * the assert
Line 890... Line 891...
890
    znum = zones_add_zone(z);
891
    znum = zones_add_zone(z);
891
    if (znum == -1)
892
    if (znum == -1)
892
        return -1;
893
        return -1;
893
 
894
 
894
    /* If confdata in zone, mark as unavailable */
895
    /* If confdata in zone, mark as unavailable */
895
    if (confframe >= start && confframe < start+count)
896
    if (confframe >= start && confframe < start + count)
896
        for (i=confframe; i<confframe+confcount; i++) {
897
        for (i = confframe; i < confframe + confcount; i++) {
897
            zone_mark_unavailable(z, i - z->base);
898
            zone_mark_unavailable(z, i - z->base);
898
        }
899
        }
899
    return znum;
900
    return znum;
900
}
901
}
901
 
902
 
902
/***************************************/
903
/***************************************/
903
/* Frame functions */
904
/* Frame functions */
904
 
905
 
905
/** Set parent of frame */
906
/** Set parent of frame */
906
void frame_set_parent(pfn_t pfn, void *data, int hint)
907
void frame_set_parent(pfn_t pfn, void *data, unsigned int hint)
907
{
908
{
908
    zone_t *zone = find_zone_and_lock(pfn, &hint);
909
    zone_t *zone = find_zone_and_lock(pfn, &hint);
909
 
910
 
910
    ASSERT(zone);
911
    ASSERT(zone);
911
 
912
 
912
    zone_get_frame(zone, pfn-zone->base)->parent = data;
913
    zone_get_frame(zone, pfn-zone->base)->parent = data;
913
    spinlock_unlock(&zone->lock);
914
    spinlock_unlock(&zone->lock);
914
}
915
}
915
 
916
 
916
void * frame_get_parent(pfn_t pfn, int hint)
917
void * frame_get_parent(pfn_t pfn, unsigned int hint)
917
{
918
{
918
    zone_t *zone = find_zone_and_lock(pfn, &hint);
919
    zone_t *zone = find_zone_and_lock(pfn, &hint);
919
    void *res;
920
    void *res;
920
 
921
 
921
    ASSERT(zone);
922
    ASSERT(zone);
Line 1042... Line 1043...
1042
}
1043
}
1043
 
1044
 
1044
/** Mark given range unavailable in frame zones */
1045
/** Mark given range unavailable in frame zones */
1045
void frame_mark_unavailable(pfn_t start, count_t count)
1046
void frame_mark_unavailable(pfn_t start, count_t count)
1046
{
1047
{
1047
    int i;
1048
    unsigned int i;
1048
    zone_t *zone;
1049
    zone_t *zone;
1049
    int prefzone = 0;
1050
    unsigned int prefzone = 0;
1050
   
1051
   
1051
    for (i=0; i < count; i++) {
1052
    for (i = 0; i < count; i++) {
1052
        zone = find_zone_and_lock(start + i, &prefzone);
1053
        zone = find_zone_and_lock(start + i, &prefzone);
1053
        if (!zone) /* PFN not found */
1054
        if (!zone) /* PFN not found */
1054
            continue;
1055
            continue;
1055
        zone_mark_unavailable(zone, start + i - zone->base);
1056
        zone_mark_unavailable(zone, start + i - zone->base);
1056
 
1057
 
Line 1092... Line 1093...
1092
/** Prints list of zones
1093
/** Prints list of zones
1093
 *
1094
 *
1094
 */
1095
 */
1095
void zone_print_list(void) {
1096
void zone_print_list(void) {
1096
    zone_t *zone = NULL;
1097
    zone_t *zone = NULL;
1097
    int i;
1098
    unsigned int i;
1098
    ipl_t ipl;
1099
    ipl_t ipl;
1099
 
1100
 
1100
    ipl = interrupts_disable();
1101
    ipl = interrupts_disable();
1101
    spinlock_lock(&zones.lock);
1102
    spinlock_lock(&zones.lock);
1102
    printf("#  base address free frames  busy frames\n");
1103
    printf("#  base address free frames  busy frames\n");
Line 1113... Line 1114...
1113
 
1114
 
1114
/** Prints zone details.
1115
/** Prints zone details.
1115
 *
1116
 *
1116
 * @param num Zone base address or zone number.
1117
 * @param num Zone base address or zone number.
1117
 */
1118
 */
1118
void zone_print_one(int num) {
1119
void zone_print_one(unsigned int num) {
1119
    zone_t *zone = NULL;
1120
    zone_t *zone = NULL;
1120
    ipl_t ipl;
1121
    ipl_t ipl;
1121
    int i;
1122
    unsigned int i;
1122
 
1123
 
1123
    ipl = interrupts_disable();
1124
    ipl = interrupts_disable();
1124
    spinlock_lock(&zones.lock);
1125
    spinlock_lock(&zones.lock);
1125
 
1126
 
1126
    for (i = 0; i < zones.count; i++) {
1127
    for (i = 0; i < zones.count; i++) {