Subversion Repositories HelenOS

Rev

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

Rev 3972 Rev 3973
Line 46... Line 46...
46
#include <mm/frame.h>
46
#include <mm/frame.h>
47
#include <mm/as.h>
47
#include <mm/as.h>
48
#include <panic.h>
48
#include <panic.h>
49
#include <debug.h>
49
#include <debug.h>
50
#include <adt/list.h>
50
#include <adt/list.h>
51
#include <synch/spinlock.h>
-
 
52
#include <synch/mutex.h>
51
#include <synch/mutex.h>
53
#include <synch/condvar.h>
52
#include <synch/condvar.h>
54
#include <arch/asm.h>
53
#include <arch/asm.h>
55
#include <arch.h>
54
#include <arch.h>
56
#include <print.h>
55
#include <print.h>
Line 58... Line 57...
58
#include <mm/slab.h>
57
#include <mm/slab.h>
59
#include <bitops.h>
58
#include <bitops.h>
60
#include <macros.h>
59
#include <macros.h>
61
#include <config.h>
60
#include <config.h>
62
 
61
 
63
typedef struct {
-
 
64
    count_t refcount;     /**< Tracking of shared frames */
-
 
65
    uint8_t buddy_order;  /**< Buddy system block order */
-
 
66
    link_t buddy_link;    /**< Link to the next free block inside
-
 
67
                               one order */
-
 
68
    void *parent;         /**< If allocated by slab, this points there */
-
 
69
} frame_t;
-
 
70
 
-
 
71
typedef struct {
-
 
72
    pfn_t base;                    /**< Frame_no of the first frame
-
 
73
                                        in the frames array */
-
 
74
    count_t count;                 /**< Size of zone */
-
 
75
    count_t free_count;            /**< Number of free frame_t
-
 
76
                                        structures */
-
 
77
    count_t busy_count;            /**< Number of busy frame_t
-
 
78
                                        structures */
-
 
79
    zone_flags_t flags;            /**< Type of the zone */
-
 
80
   
-
 
81
    frame_t *frames;               /**< Array of frame_t structures
-
 
82
                                        in this zone */
-
 
83
    buddy_system_t *buddy_system;  /**< Buddy system for the zone */
-
 
84
} zone_t;
-
 
85
 
-
 
86
/*
-
 
87
 * The zoneinfo.lock must be locked when accessing zoneinfo structure.
-
 
88
 * Some of the attributes in zone_t structures are 'read-only'
-
 
89
 */
-
 
90
typedef struct {
-
 
91
    SPINLOCK_DECLARE(lock);
-
 
92
    count_t count;
-
 
93
    zone_t info[ZONES_MAX];
-
 
94
} zones_t;
-
 
95
 
-
 
96
static zones_t zones;
62
zones_t zones;
97
 
63
 
98
/*
64
/*
99
 * Synchronization primitives used to sleep when there is no memory
65
 * Synchronization primitives used to sleep when there is no memory
100
 * available.
66
 * available.
101
 */
67
 */
Line 126... Line 92...
126
static inline index_t make_frame_index(zone_t *zone, frame_t *frame)
92
static inline index_t make_frame_index(zone_t *zone, frame_t *frame)
127
{
93
{
128
    return (frame - zone->frames);
94
    return (frame - zone->frames);
129
}
95
}
130
 
96
 
131
static inline bool zone_flags_available(zone_flags_t flags)
-
 
132
{
-
 
133
    return ((flags & (ZONE_RESERVED | ZONE_FIRMWARE)) == 0);
-
 
134
}
-
 
135
 
-
 
136
/** Initialize frame structure.
97
/** Initialize frame structure.
137
 *
98
 *
138
 * @param frame Frame structure to be initialized.
99
 * @param frame Frame structure to be initialized.
139
 *
100
 *
140
 */
101
 */
Line 178... Line 139...
178
            break;
139
            break;
179
    }
140
    }
180
   
141
   
181
    /* Move other zones up */
142
    /* Move other zones up */
182
    count_t j;
143
    count_t j;
183
    for (j = i; j < zones.count; j++)
144
    for (j = zones.count; j > i; j--) {
184
        zones.info[j + 1] = zones.info[j];
145
        zones.info[j] = zones.info[j - 1];
-
 
146
        zones.info[j].buddy_system->data =
-
 
147
            (void *) &zones.info[j - 1];
-
 
148
    }
185
   
149
   
186
    zones.count++;
150
    zones.count++;
187
   
151
   
188
    return i;
152
    return i;
189
}
153
}
Line 204... Line 168...
204
        total += zones.info[i].free_count;
168
        total += zones.info[i].free_count;
205
   
169
   
206
    return total;
170
    return total;
207
}
171
}
208
 
172
 
209
/** Find a zone with a given frame.
173
/** Find a zone with a given frames.
210
 *
174
 *
211
 * Assume interrupts are disabled and zones lock is
175
 * Assume interrupts are disabled and zones lock is
212
 * locked.
176
 * locked.
213
 *
177
 *
214
 * @param frame Frame number contained in zone.
178
 * @param frame Frame number contained in zone.
-
 
179
 * @param count Number of frames to look for.
215
 * @param hint  Used as zone hint.
180
 * @param hint  Used as zone hint.
216
 *
181
 *
217
 * @return Zone index or -1 if not found.
182
 * @return Zone index or -1 if not found.
218
 *
183
 *
219
 */
184
 */
220
static count_t find_zone(pfn_t frame, count_t hint)
185
count_t find_zone(pfn_t frame, count_t count, count_t hint)
221
{
186
{
222
    if (hint >= zones.count)
187
    if (hint >= zones.count)
223
        hint = 0;
188
        hint = 0;
224
   
189
   
225
    count_t i = hint;
190
    count_t i = hint;
226
    do {
191
    do {
227
        if ((zones.info[i].base <= frame)
192
        if ((zones.info[i].base <= frame)
228
            && (zones.info[i].base + zones.info[i].count > frame))
193
            && (zones.info[i].base + zones.info[i].count >= frame + count))
229
            return i;
194
            return i;
230
       
195
       
231
        i++;
196
        i++;
232
        if (i >= zones.count)
197
        if (i >= zones.count)
233
            i = 0;
198
            i = 0;
Line 763... Line 728...
763
        ADDR2PFN(KA2PA((uintptr_t) old_z1.frames)), old_z1.count);
728
        ADDR2PFN(KA2PA((uintptr_t) old_z1.frames)), old_z1.count);
764
    return_config_frames(z1,
729
    return_config_frames(z1,
765
        ADDR2PFN(KA2PA((uintptr_t) zones.info[z2].frames)),
730
        ADDR2PFN(KA2PA((uintptr_t) zones.info[z2].frames)),
766
        zones.info[z2].count);
731
        zones.info[z2].count);
767
   
732
   
768
    /* Shift existing zones */
733
    /* Move zones down */
769
    count_t i;
734
    count_t i;
770
    for (i = z2 + 1; i < zones.count; i++)
735
    for (i = z2 + 1; i < zones.count; i++) {
771
        zones.info[i - 1] = zones.info[i];
736
        zones.info[i - 1] = zones.info[i];
-
 
737
        zones.info[i - 1].buddy_system->data =
-
 
738
            (void *) &zones.info[i - 1];
-
 
739
    }
-
 
740
   
772
    zones.count--;
741
    zones.count--;
773
   
742
   
774
errout:
743
errout:
775
    spinlock_unlock(&zones.lock);
744
    spinlock_unlock(&zones.lock);
776
    interrupts_restore(ipl);
745
    interrupts_restore(ipl);
Line 962... Line 931...
962
void frame_set_parent(pfn_t pfn, void *data, count_t hint)
931
void frame_set_parent(pfn_t pfn, void *data, count_t hint)
963
{
932
{
964
    ipl_t ipl = interrupts_disable();
933
    ipl_t ipl = interrupts_disable();
965
    spinlock_lock(&zones.lock);
934
    spinlock_lock(&zones.lock);
966
   
935
   
967
    count_t znum = find_zone(pfn, hint);
936
    count_t znum = find_zone(pfn, 1, hint);
968
   
937
   
969
    ASSERT(znum != (count_t) -1);
938
    ASSERT(znum != (count_t) -1);
970
   
939
   
971
    zone_get_frame(&zones.info[znum],
940
    zone_get_frame(&zones.info[znum],
972
        pfn - zones.info[znum].base)->parent = data;
941
        pfn - zones.info[znum].base)->parent = data;
Line 978... Line 947...
978
void *frame_get_parent(pfn_t pfn, count_t hint)
947
void *frame_get_parent(pfn_t pfn, count_t hint)
979
{
948
{
980
    ipl_t ipl = interrupts_disable();
949
    ipl_t ipl = interrupts_disable();
981
    spinlock_lock(&zones.lock);
950
    spinlock_lock(&zones.lock);
982
   
951
   
983
    count_t znum = find_zone(pfn, hint);
952
    count_t znum = find_zone(pfn, 1, hint);
984
   
953
   
985
    ASSERT(znum != (count_t) -1);
954
    ASSERT(znum != (count_t) -1);
986
   
955
   
987
    void *res = zone_get_frame(&zones.info[znum],
956
    void *res = zone_get_frame(&zones.info[znum],
988
        pfn - zones.info[znum].base)->parent;
957
        pfn - zones.info[znum].base)->parent;
Line 1109... Line 1078...
1109
   
1078
   
1110
    /*
1079
    /*
1111
     * First, find host frame zone for addr.
1080
     * First, find host frame zone for addr.
1112
     */
1081
     */
1113
    pfn_t pfn = ADDR2PFN(frame);
1082
    pfn_t pfn = ADDR2PFN(frame);
1114
    count_t znum = find_zone(pfn, NULL);
1083
    count_t znum = find_zone(pfn, 1, NULL);
1115
   
1084
   
1116
    ASSERT(znum != (count_t) -1);
1085
    ASSERT(znum != (count_t) -1);
1117
   
1086
   
1118
    zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
1087
    zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
1119
   
1088
   
Line 1148... Line 1117...
1148
    spinlock_lock(&zones.lock);
1117
    spinlock_lock(&zones.lock);
1149
   
1118
   
1150
    /*
1119
    /*
1151
     * First, find host frame zone for addr.
1120
     * First, find host frame zone for addr.
1152
     */
1121
     */
1153
    count_t znum = find_zone(pfn, NULL);
1122
    count_t znum = find_zone(pfn, 1, NULL);
1154
   
1123
   
1155
    ASSERT(znum != (count_t) -1);
1124
    ASSERT(znum != (count_t) -1);
1156
   
1125
   
1157
    zones.info[znum].frames[pfn - zones.info[znum].base].refcount++;
1126
    zones.info[znum].frames[pfn - zones.info[znum].base].refcount++;
1158
   
1127
   
Line 1166... Line 1135...
1166
    ipl_t ipl = interrupts_disable();
1135
    ipl_t ipl = interrupts_disable();
1167
    spinlock_lock(&zones.lock);
1136
    spinlock_lock(&zones.lock);
1168
   
1137
   
1169
    count_t i;
1138
    count_t i;
1170
    for (i = 0; i < count; i++) {
1139
    for (i = 0; i < count; i++) {
1171
        count_t znum = find_zone(start + i, 0);
1140
        count_t znum = find_zone(start + i, 1, 0);
1172
        if (znum == (count_t) -1)  /* PFN not found */
1141
        if (znum == (count_t) -1)  /* PFN not found */
1173
            continue;
1142
            continue;
1174
       
1143
       
1175
        zone_mark_unavailable(&zones.info[znum],
1144
        zone_mark_unavailable(&zones.info[znum],
1176
            start + i - zones.info[znum].base);
1145
            start + i - zones.info[znum].base);
Line 1235... Line 1204...
1235
 
1204
 
1236
/** Prints list of zones. */
1205
/** Prints list of zones. */
1237
void zone_print_list(void)
1206
void zone_print_list(void)
1238
{
1207
{
1239
#ifdef __32_BITS__
1208
#ifdef __32_BITS__
1240
    printf("#  base address flags    free frames  busy frames\n");
1209
    printf("#  base address frames       flags    free frames  busy frames\n");
1241
    printf("-- ------------ -------- ------------ ------------\n");
1210
    printf("-- ------------ ------------ -------- ------------ ------------\n");
1242
#endif
1211
#endif
1243
 
1212
 
1244
#ifdef __64_BITS__
1213
#ifdef __64_BITS__
1245
    printf("#  base address         flags    free frames  busy frames\n");
1214
    printf("#  base address          frames      flags    free frames  busy frames\n");
1246
    printf("-- -------------------- -------- ------------ ------------\n");
1215
    printf("-- -------------------- ------------ -------- ------------ ------------\n");
1247
#endif
1216
#endif
1248
   
1217
   
1249
    /*
1218
    /*
1250
     * Because printing may require allocation of memory, we may not hold
1219
     * Because printing may require allocation of memory, we may not hold
1251
     * the frame allocator locks when printing zone statistics.  Therefore,
1220
     * the frame allocator locks when printing zone statistics.  Therefore,
Line 1267... Line 1236...
1267
            interrupts_restore(ipl);
1236
            interrupts_restore(ipl);
1268
            break;
1237
            break;
1269
        }
1238
        }
1270
       
1239
       
1271
        uintptr_t base = PFN2ADDR(zones.info[i].base);
1240
        uintptr_t base = PFN2ADDR(zones.info[i].base);
-
 
1241
        count_t count = zones.info[i].count;
1272
        zone_flags_t flags = zones.info[i].flags;
1242
        zone_flags_t flags = zones.info[i].flags;
1273
        count_t free_count = zones.info[i].free_count;
1243
        count_t free_count = zones.info[i].free_count;
1274
        count_t busy_count = zones.info[i].busy_count;
1244
        count_t busy_count = zones.info[i].busy_count;
1275
       
1245
       
1276
        spinlock_unlock(&zones.lock);
1246
        spinlock_unlock(&zones.lock);
1277
        interrupts_restore(ipl);
1247
        interrupts_restore(ipl);
1278
       
1248
       
1279
        bool available = zone_flags_available(flags);
1249
        bool available = zone_flags_available(flags);
1280
       
1250
       
-
 
1251
        printf("%-2" PRIc, i);
-
 
1252
       
1281
#ifdef __32_BITS__
1253
#ifdef __32_BITS__
1282
        printf("%-2" PRIc "   %10p %c%c%c      ", i, base,
1254
        printf("   %10p", base);
1283
            available ? 'A' : ' ',
-
 
1284
            (flags & ZONE_RESERVED) ? 'R' : ' ',
-
 
1285
            (flags & ZONE_FIRMWARE) ? 'F' : ' ');
-
 
1286
#endif
1255
#endif
1287
       
1256
       
1288
#ifdef __64_BITS__
1257
#ifdef __64_BITS__
-
 
1258
        printf("   %18p", base);
-
 
1259
#endif
-
 
1260
       
1289
        printf("%-2" PRIc "   %18p %c%c%c      ", i, base,
1261
        printf(" %12" PRIc " %c%c%c      ", count,
1290
            available ? 'A' : ' ',
1262
            available ? 'A' : ' ',
1291
            (flags & ZONE_RESERVED) ? 'R' : ' ',
1263
            (flags & ZONE_RESERVED) ? 'R' : ' ',
1292
            (flags & ZONE_FIRMWARE) ? 'F' : ' ');
1264
            (flags & ZONE_FIRMWARE) ? 'F' : ' ');
1293
#endif
-
 
1294
       
1265
       
1295
        if (available)
1266
        if (available)
1296
            printf("%12" PRIc " %12" PRIc,
1267
            printf("%12" PRIc " %12" PRIc,
1297
                free_count, busy_count);
1268
                free_count, busy_count);
-
 
1269
       
1298
        printf("\n");
1270
        printf("\n");
1299
    }
1271
    }
1300
}
1272
}
1301
 
1273
 
1302
/** Prints zone details.
1274
/** Prints zone details.