00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <malloc.h>
00032 #include <as.h>
00033 #include <adt/list.h>
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <errno.h>
00037 #include "../tester.h"
00038 #include "common.h"
00039
00040
00041
00042
00043
00044
00045 bool error_flag = false;
00046
00047
00048
00049
00050
00051 size_t mem_allocated;
00052 size_t mem_blocks_count;
00053
00054 static LIST_INITIALIZE(mem_blocks);
00055 static LIST_INITIALIZE(mem_areas);
00056
00060 void init_mem(void)
00061 {
00062 mem_allocated = 0;
00063 mem_blocks_count = 0;
00064 }
00065
00071 void done_mem(void)
00072 {
00073 link_t *link;
00074
00075 while ((link = list_head(&mem_blocks)) != NULL) {
00076 mem_block_t *block = list_get_instance(link, mem_block_t, link);
00077 free_block(block);
00078 }
00079
00080 while ((link = list_head(&mem_areas)) != NULL) {
00081 mem_area_t *area = list_get_instance(link, mem_area_t, link);
00082 unmap_area(area);
00083 }
00084 }
00085
00086 static bool overlap_match(link_t *link, void *addr, size_t size)
00087 {
00088 mem_block_t *block = list_get_instance(link, mem_block_t, link);
00089
00090
00091 uint8_t *mbeg = (uint8_t *) block;
00092 uint8_t *mend = (uint8_t *) block + sizeof(mem_block_t);
00093
00094
00095 uint8_t *bbeg = (uint8_t *) block->addr;
00096 uint8_t *bend = (uint8_t *) block->addr + block->size;
00097
00098
00099 uint8_t *dbeg = (uint8_t *) addr;
00100 uint8_t *dend = (uint8_t *) addr + size;
00101
00102
00103 if (((mbeg >= dbeg) && (mbeg < dend)) ||
00104 ((mend > dbeg) && (mend <= dend)) ||
00105 ((bbeg >= dbeg) && (bbeg < dend)) ||
00106 ((bend > dbeg) && (bend <= dend)))
00107 return true;
00108
00109 return false;
00110 }
00111
00123 static int test_overlap(void *addr, size_t size)
00124 {
00125 bool fnd = false;
00126
00127 list_foreach(mem_blocks, link) {
00128 if (overlap_match(link, addr, size)) {
00129 fnd = true;
00130 break;
00131 }
00132 }
00133
00134 return fnd;
00135 }
00136
00137 static void check_consistency(const char *loc)
00138 {
00139
00140 void *prob = heap_check();
00141 if (prob != NULL) {
00142 TPRINTF("\nError: Heap inconsistency at %p in %s.\n",
00143 prob, loc);
00144 TSTACKTRACE();
00145 error_flag = true;
00146 }
00147 }
00148
00161 static void *checked_malloc(size_t size)
00162 {
00163 void *data;
00164
00165
00166 data = malloc(size);
00167 check_consistency("checked_malloc");
00168 if (data == NULL)
00169 return NULL;
00170
00171
00172 if (test_overlap(data, size)) {
00173 TPRINTF("\nError: Allocated block overlaps with another "
00174 "previously allocated block.\n");
00175 TSTACKTRACE();
00176 error_flag = true;
00177 }
00178
00179 return data;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 mem_block_t *alloc_block(size_t size)
00197 {
00198
00199 if (mem_allocated >= MAX_ALLOC)
00200 return NULL;
00201
00202
00203 mem_block_t *block =
00204 (mem_block_t *) checked_malloc(sizeof(mem_block_t));
00205 if (block == NULL)
00206 return NULL;
00207
00208 link_initialize(&block->link);
00209
00210
00211 block->addr = checked_malloc(size);
00212 if (block->addr == NULL) {
00213 free(block);
00214 check_consistency("alloc_block");
00215 return NULL;
00216 }
00217
00218 block->size = size;
00219
00220
00221 list_append(&block->link, &mem_blocks);
00222 mem_allocated += size + sizeof(mem_block_t);
00223 mem_blocks_count++;
00224
00225 return block;
00226 }
00227
00236 void free_block(mem_block_t *block)
00237 {
00238
00239 list_remove(&block->link);
00240 mem_allocated -= block->size + sizeof(mem_block_t);
00241 mem_blocks_count--;
00242
00243
00244 free(block->addr);
00245 check_consistency("free_block (a)");
00246 free(block);
00247 check_consistency("free_block (b)");
00248 }
00249
00259 static inline uint8_t block_expected_value(mem_block_t *block, uint8_t *pos)
00260 {
00261 return ((uintptr_t) block ^ (uintptr_t) pos) & 0xff;
00262 }
00263
00271 void fill_block(mem_block_t *block)
00272 {
00273 for (uint8_t *pos = block->addr, *end = pos + block->size;
00274 pos < end; pos++)
00275 *pos = block_expected_value(block, pos);
00276
00277 check_consistency("fill_block");
00278 }
00279
00288 void check_block(mem_block_t *block)
00289 {
00290 for (uint8_t *pos = block->addr, *end = pos + block->size;
00291 pos < end; pos++) {
00292 if (*pos != block_expected_value(block, pos)) {
00293 TPRINTF("\nError: Corrupted content of a data block.\n");
00294 TSTACKTRACE();
00295 error_flag = true;
00296 return;
00297 }
00298 }
00299 }
00300
00308 mem_block_t *get_random_block(void)
00309 {
00310 if (mem_blocks_count == 0)
00311 return NULL;
00312
00313 unsigned int idx = rand() % mem_blocks_count;
00314 link_t *entry = list_nth(&mem_blocks, idx);
00315
00316 if (entry == NULL) {
00317 TPRINTF("\nError: Corrupted list of allocated memory blocks.\n");
00318 TSTACKTRACE();
00319 error_flag = true;
00320 }
00321
00322 return list_get_instance(entry, mem_block_t, link);
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 mem_area_t *map_area(size_t size)
00335 {
00336
00337 mem_area_t *area =
00338 (mem_area_t *) checked_malloc(sizeof(mem_area_t));
00339 if (area == NULL)
00340 return NULL;
00341
00342 link_initialize(&area->link);
00343
00344
00345 void *addr = as_get_mappable_page(size);
00346 if (addr == NULL) {
00347 free(area);
00348 check_consistency("map_area (a)");
00349 return NULL;
00350 }
00351
00352 area->addr = as_area_create(addr, size, AS_AREA_WRITE | AS_AREA_READ);
00353 if (area->addr == (void *) -1) {
00354 free(area);
00355 check_consistency("map_area (b)");
00356 return NULL;
00357 }
00358
00359 area->size = size;
00360
00361
00362 list_append(&area->link, &mem_areas);
00363
00364 return area;
00365 }
00366
00375 void unmap_area(mem_area_t *area)
00376 {
00377
00378 list_remove(&area->link);
00379
00380
00381 int ret = as_area_destroy(area->addr);
00382 if (ret != EOK)
00383 error_flag = true;
00384
00385 free(area);
00386 check_consistency("unmap_area");
00387 }
00388
00398 static inline uint8_t area_expected_value(mem_area_t *area, uint8_t *pos)
00399 {
00400 return ((uintptr_t) area ^ (uintptr_t) pos) & 0xaa;
00401 }
00402
00410 void fill_area(mem_area_t *area)
00411 {
00412 for (uint8_t *pos = area->addr, *end = pos + area->size;
00413 pos < end; pos++)
00414 *pos = area_expected_value(area, pos);
00415
00416 check_consistency("fill_area");
00417 }