Subversion Repositories HelenOS

Rev

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

Rev 3187 Rev 3188
Line 107... Line 107...
107
 
107
 
108
/*
108
/*
109
 * Synchronization primitives used to sleep when there is no memory
109
 * Synchronization primitives used to sleep when there is no memory
110
 * available.
110
 * available.
111
 */
111
 */
112
mutex_t zones_mtx;
112
mutex_t mem_avail_mtx;
113
condvar_t zones_cv;
113
condvar_t mem_avail_cv;
-
 
114
unsigned long mem_avail_frames = 0; /**< Number of available frames. */
114
int new_freed_mem = false;
115
unsigned long mem_avail_gen = 0;    /**< Generation counter. */
115
 
116
 
116
/********************/
117
/********************/
117
/* Helper functions */
118
/* Helper functions */
118
/********************/
119
/********************/
119
 
120
 
Line 138... Line 139...
138
    return (frame - zone->frames);
139
    return (frame - zone->frames);
139
}
140
}
140
 
141
 
141
/** Initialize frame structure.
142
/** Initialize frame structure.
142
 *
143
 *
143
 * @param framei    Frame structure to be initialized.
144
 * @param frame     Frame structure to be initialized.
144
 */
145
 */
145
static void frame_initialize(frame_t *frame)
146
static void frame_initialize(frame_t *frame)
146
{
147
{
147
    frame->refcount = 1;
148
    frame->refcount = 1;
148
    frame->buddy_order = 0;
149
    frame->buddy_order = 0;
Line 537... Line 538...
537
        zone->busy_count -= (1 << order);
538
        zone->busy_count -= (1 << order);
538
    }
539
    }
539
}
540
}
540
 
541
 
541
/** Return frame from zone. */
542
/** Return frame from zone. */
542
static frame_t * zone_get_frame(zone_t *zone, index_t frame_idx)
543
static frame_t *zone_get_frame(zone_t *zone, index_t frame_idx)
543
{
544
{
544
    ASSERT(frame_idx < zone->count);
545
    ASSERT(frame_idx < zone->count);
545
    return &zone->frames[frame_idx];
546
    return &zone->frames[frame_idx];
546
}
547
}
547
 
548
 
Line 556... Line 557...
556
        return;
557
        return;
557
    link = buddy_system_alloc_block(zone->buddy_system,
558
    link = buddy_system_alloc_block(zone->buddy_system,
558
        &frame->buddy_link);
559
        &frame->buddy_link);
559
    ASSERT(link);
560
    ASSERT(link);
560
    zone->free_count--;
561
    zone->free_count--;
-
 
562
 
-
 
563
    mutex_lock(&mem_avail_mtx);
-
 
564
    mem_avail_frames--;
-
 
565
    mutex_unlock(&mem_avail_mtx);
561
}
566
}
562
 
567
 
563
/** Join two zones.
568
/** Join two zones.
564
 *
569
 *
565
 * Expect zone_t *z to point to space at least zone_conf_size large.
570
 * Expect zone_t *z to point to space at least zone_conf_size large.
Line 733... Line 738...
733
    spinlock_lock(&zones.lock);
738
    spinlock_lock(&zones.lock);
734
 
739
 
735
    if ((z1 >= zones.count) || (z2 >= zones.count))
740
    if ((z1 >= zones.count) || (z2 >= zones.count))
736
        goto errout;
741
        goto errout;
737
    /* We can join only 2 zones with none existing inbetween */
742
    /* We can join only 2 zones with none existing inbetween */
738
    if (z2-z1 != 1)
743
    if (z2 - z1 != 1)
739
        goto errout;
744
        goto errout;
740
 
745
 
741
    zone1 = zones.info[z1];
746
    zone1 = zones.info[z1];
742
    zone2 = zones.info[z2];
747
    zone2 = zones.info[z2];
743
    spinlock_lock(&zone1->lock);
748
    spinlock_lock(&zone1->lock);
Line 794... Line 799...
794
void zone_merge_all(void)
799
void zone_merge_all(void)
795
{
800
{
796
    int count = zones.count;
801
    int count = zones.count;
797
 
802
 
798
    while (zones.count > 1 && --count) {
803
    while (zones.count > 1 && --count) {
799
        zone_merge(0,1);
804
        zone_merge(0, 1);
800
        break;
805
        break;
801
    }
806
    }
802
}
807
}
803
 
808
 
804
/** Create new frame zone.
809
/** Create new frame zone.
Line 891... Line 896...
891
    ASSERT(confframe);
896
    ASSERT(confframe);
892
    /* If conframe is supposed to be inside our zone, then make sure
897
    /* If conframe is supposed to be inside our zone, then make sure
893
     * it does not span kernel & init
898
     * it does not span kernel & init
894
     */
899
     */
895
    confcount = SIZE2FRAMES(zone_conf_size(count));
900
    confcount = SIZE2FRAMES(zone_conf_size(count));
896
    if (confframe >= start && confframe < start+count) {
901
    if (confframe >= start && confframe < start + count) {
897
        for (;confframe < start + count; confframe++) {
902
        for (; confframe < start + count; confframe++) {
898
            addr = PFN2ADDR(confframe);
903
            addr = PFN2ADDR(confframe);
899
            if (overlaps(addr, PFN2ADDR(confcount),
904
            if (overlaps(addr, PFN2ADDR(confcount),
900
                KA2PA(config.base), config.kernel_size))
905
                KA2PA(config.base), config.kernel_size))
901
                continue;
906
                continue;
902
           
907
           
Line 926... Line 931...
926
    zone_construct(start, count, z, flags);
931
    zone_construct(start, count, z, flags);
927
    znum = zones_add_zone(z);
932
    znum = zones_add_zone(z);
928
    if (znum == -1)
933
    if (znum == -1)
929
        return -1;
934
        return -1;
930
 
935
 
-
 
936
    mutex_lock(&mem_avail_mtx);
-
 
937
    mem_avail_frames += count;
-
 
938
    mutex_unlock(&mem_avail_mtx);
-
 
939
 
931
    /* If confdata in zone, mark as unavailable */
940
    /* If confdata in zone, mark as unavailable */
932
    if (confframe >= start && confframe < start + count)
941
    if (confframe >= start && confframe < start + count)
933
        for (i = confframe; i < confframe + confcount; i++) {
942
        for (i = confframe; i < confframe + confcount; i++) {
934
            zone_mark_unavailable(z, i - z->base);
943
            zone_mark_unavailable(z, i - z->base);
935
        }
944
        }
-
 
945
   
936
    return znum;
946
    return znum;
937
}
947
}
938
 
948
 
939
/***************************************/
949
/***************************************/
940
/* Frame functions */
950
/* Frame functions */
Line 944... Line 954...
944
{
954
{
945
    zone_t *zone = find_zone_and_lock(pfn, &hint);
955
    zone_t *zone = find_zone_and_lock(pfn, &hint);
946
 
956
 
947
    ASSERT(zone);
957
    ASSERT(zone);
948
 
958
 
949
    zone_get_frame(zone, pfn-zone->base)->parent = data;
959
    zone_get_frame(zone, pfn - zone->base)->parent = data;
950
    spinlock_unlock(&zone->lock);
960
    spinlock_unlock(&zone->lock);
951
}
961
}
952
 
962
 
953
void *frame_get_parent(pfn_t pfn, unsigned int hint)
963
void *frame_get_parent(pfn_t pfn, unsigned int hint)
954
{
964
{
Line 975... Line 985...
975
{
985
{
976
    ipl_t ipl;
986
    ipl_t ipl;
977
    int freed;
987
    int freed;
978
    pfn_t v;
988
    pfn_t v;
979
    zone_t *zone;
989
    zone_t *zone;
-
 
990
    unsigned long gen = 0;
980
   
991
   
981
loop:
992
loop:
982
    ipl = interrupts_disable();
993
    ipl = interrupts_disable();
983
   
994
   
984
    /*
995
    /*
Line 1006... Line 1017...
1006
            interrupts_restore(ipl);
1017
            interrupts_restore(ipl);
1007
            return 0;
1018
            return 0;
1008
        }
1019
        }
1009
       
1020
       
1010
#ifdef CONFIG_DEBUG
1021
#ifdef CONFIG_DEBUG
-
 
1022
        unsigned long avail;
-
 
1023
 
-
 
1024
        mutex_lock(&mem_avail_mtx);
-
 
1025
        avail = mem_avail_frames;
-
 
1026
        mutex_unlock(&mem_avail_mtx);
-
 
1027
 
1011
        printf("Thread %" PRIu64 " falling asleep, low memory.\n", THREAD->tid);
1028
        printf("Thread %" PRIu64 " waiting for %u frames, "
-
 
1029
            "%u available.\n", THREAD->tid, 1ULL << order, avail);
1012
#endif
1030
#endif
1013
 
1031
 
1014
        mutex_lock(&zones_mtx);
1032
        mutex_lock(&mem_avail_mtx);
-
 
1033
        while ((mem_avail_frames < (1ULL << order)) ||
1015
        if (!new_freed_mem)
1034
            gen == mem_avail_gen)
1016
            condvar_wait(&zones_cv, &zones_mtx);
1035
            condvar_wait(&mem_avail_cv, &mem_avail_mtx);
1017
        new_freed_mem = false;
1036
        gen = mem_avail_gen;
1018
        mutex_unlock(&zones_mtx);
1037
        mutex_unlock(&mem_avail_mtx);
1019
 
1038
 
1020
#ifdef CONFIG_DEBUG
1039
#ifdef CONFIG_DEBUG
-
 
1040
        mutex_lock(&mem_avail_mtx);
-
 
1041
        avail = mem_avail_frames;
-
 
1042
        mutex_unlock(&mem_avail_mtx);
-
 
1043
 
1021
        printf("Thread %" PRIu64 " woken up, memory available.\n", THREAD->tid);
1044
        printf("Thread %" PRIu64 " woken up, %u frames available.\n",
-
 
1045
            THREAD->tid, avail);
1022
#endif
1046
#endif
1023
 
1047
 
1024
        interrupts_restore(ipl);
1048
        interrupts_restore(ipl);
1025
        goto loop;
1049
        goto loop;
1026
    }
1050
    }
1027
   
1051
   
1028
    v = zone_frame_alloc(zone, order);
1052
    v = zone_frame_alloc(zone, order);
1029
    v += zone->base;
1053
    v += zone->base;
1030
 
1054
 
1031
    spinlock_unlock(&zone->lock);
1055
    spinlock_unlock(&zone->lock);
-
 
1056
   
-
 
1057
    mutex_lock(&mem_avail_mtx);
-
 
1058
    mem_avail_frames -= (1ULL << order);
-
 
1059
    mutex_unlock(&mem_avail_mtx);
-
 
1060
 
1032
    interrupts_restore(ipl);
1061
    interrupts_restore(ipl);
1033
 
1062
 
1034
    if (flags & FRAME_KA)
1063
    if (flags & FRAME_KA)
1035
        return (void *)PA2KA(PFN2ADDR(v));
1064
        return (void *)PA2KA(PFN2ADDR(v));
1036
    return (void *)PFN2ADDR(v);
1065
    return (void *)PFN2ADDR(v);
Line 1063... Line 1092...
1063
    spinlock_unlock(&zone->lock);
1092
    spinlock_unlock(&zone->lock);
1064
   
1093
   
1065
    /*
1094
    /*
1066
     * Signal that some memory has been freed.
1095
     * Signal that some memory has been freed.
1067
     */
1096
     */
1068
    mutex_lock(&zones_mtx);
1097
    mutex_lock(&mem_avail_mtx);
1069
    new_freed_mem = true;
1098
    mem_avail_frames++;
-
 
1099
    mem_avail_gen++;
1070
    condvar_broadcast(&zones_cv);
1100
    condvar_broadcast(&mem_avail_cv);
1071
    mutex_unlock(&zones_mtx);
1101
    mutex_unlock(&mem_avail_mtx);
1072
 
1102
 
1073
    interrupts_restore(ipl);
1103
    interrupts_restore(ipl);
1074
}
1104
}
1075
 
1105
 
1076
/** Add reference to frame.
1106
/** Add reference to frame.
Line 1122... Line 1152...
1122
void frame_init(void)
1152
void frame_init(void)
1123
{
1153
{
1124
    if (config.cpu_active == 1) {
1154
    if (config.cpu_active == 1) {
1125
        zones.count = 0;
1155
        zones.count = 0;
1126
        spinlock_initialize(&zones.lock, "zones.lock");
1156
        spinlock_initialize(&zones.lock, "zones.lock");
-
 
1157
        mutex_initialize(&mem_avail_mtx, MUTEX_ACTIVE);
-
 
1158
        condvar_initialize(&mem_avail_cv);
1127
    }
1159
    }
1128
    /* Tell the architecture to create some memory */
1160
    /* Tell the architecture to create some memory */
1129
    frame_arch_init();
1161
    frame_arch_init();
1130
    if (config.cpu_active == 1) {
1162
    if (config.cpu_active == 1) {
1131
        frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)),
1163
        frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)),
Line 1146... Line 1178...
1146
 
1178
 
1147
        /* Black list first frame, as allocating NULL would
1179
        /* Black list first frame, as allocating NULL would
1148
         * fail in some places */
1180
         * fail in some places */
1149
        frame_mark_unavailable(0, 1);
1181
        frame_mark_unavailable(0, 1);
1150
    }
1182
    }
1151
 
-
 
1152
    mutex_initialize(&zones_mtx, MUTEX_ACTIVE); /* mimic spinlock */
-
 
1153
    condvar_initialize(&zones_cv);
-
 
1154
}
1183
}
1155
 
1184
 
1156
 
1185
 
1157
/** Return total size of all zones. */
1186
/** Return total size of all zones. */
1158
uint64_t zone_total_size(void)
1187
uint64_t zone_total_size(void)