Changes in uspace/app/tester/mm/malloc1.c [faeb7cc:a000878c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/tester/mm/malloc1.c
rfaeb7cc ra000878c 30 30 31 31 #include <stdio.h> 32 #include <unistd.h> 32 33 #include <stdlib.h> 33 #include "common.h"34 #include <malloc.h> 34 35 #include "../tester.h" 35 36 … … 44 45 */ 45 46 47 /** 48 * sizeof_array 49 * @array array to determine the size of 50 * 51 * Returns the size of @array in array elements. 52 */ 53 #define sizeof_array(array) \ 54 (sizeof(array) / sizeof((array)[0])) 55 56 #define MAX_ALLOC (16 * 1024 * 1024) 57 58 /* 59 * Subphase control structures: subphase termination conditions, 60 * probabilities of individual actions, subphase control structure. 61 */ 62 63 typedef struct { 64 unsigned int max_cycles; 65 unsigned int no_memory; 66 unsigned int no_allocated; 67 } sp_term_cond_s; 68 69 typedef struct { 70 unsigned int alloc; 71 unsigned int free; 72 } sp_action_prob_s; 73 74 typedef struct { 75 const char *name; 76 sp_term_cond_s cond; 77 sp_action_prob_s prob; 78 } subphase_s; 79 80 81 /* 82 * Phase control structures: The minimum and maximum block size that 83 * can be allocated during the phase execution, phase control structure. 84 */ 85 86 typedef struct { 87 size_t min_block_size; 88 size_t max_block_size; 89 } ph_alloc_size_s; 90 91 typedef struct { 92 const char *name; 93 ph_alloc_size_s alloc; 94 subphase_s *subphases; 95 } phase_s; 96 97 46 98 /* 47 99 * Subphases are defined separately here. This is for two reasons: … … 49 101 * how many subphases a phase contains. 50 102 */ 51 static subphase_ tsubphases_32B[] = {103 static subphase_s subphases_32B[] = { 52 104 { 53 105 .name = "Allocation", … … 88 140 }; 89 141 90 static subphase_ tsubphases_128K[] = {142 static subphase_s subphases_128K[] = { 91 143 { 92 144 .name = "Allocation", … … 127 179 }; 128 180 129 static subphase_ tsubphases_default[] = {181 static subphase_s subphases_default[] = { 130 182 { 131 183 .name = "Allocation", … … 166 218 }; 167 219 220 168 221 /* 169 222 * Phase definitions. 170 223 */ 171 static phase_ tphases[] = {224 static phase_s phases[] = { 172 225 { 173 226 .name = "32 B memory blocks", … … 204 257 }; 205 258 206 static void do_subphase(phase_t *phase, subphase_t *subphase) 207 { 208 for (unsigned int cycles = 0; /* always */; cycles++) { 259 260 /* 261 * Global error flag. The flag is set if an error 262 * is encountered (overlapping blocks, inconsistent 263 * block data, etc.) 264 */ 265 static bool error_flag = false; 266 267 /* 268 * Memory accounting: the amount of allocated memory and the 269 * number and list of allocated blocks. 270 */ 271 static size_t mem_allocated; 272 static size_t mem_blocks_count; 273 274 static LIST_INITIALIZE(mem_blocks); 275 276 typedef struct { 277 /* Address of the start of the block */ 278 void *addr; 279 280 /* Size of the memory block */ 281 size_t size; 282 283 /* link to other blocks */ 284 link_t link; 285 } mem_block_s; 286 287 typedef mem_block_s *mem_block_t; 288 289 290 /** init_mem 291 * 292 * Initializes the memory accounting structures. 293 * 294 */ 295 static void init_mem(void) 296 { 297 mem_allocated = 0; 298 mem_blocks_count = 0; 299 } 300 301 302 static bool overlap_match(link_t *entry, void *addr, size_t size) 303 { 304 mem_block_t mblk = list_get_instance(entry, mem_block_s, link); 305 306 /* Entry block control structure <mbeg, mend) */ 307 uint8_t *mbeg = (uint8_t *) mblk; 308 uint8_t *mend = (uint8_t *) mblk + sizeof(mem_block_s); 309 310 /* Entry block memory <bbeg, bend) */ 311 uint8_t *bbeg = (uint8_t *) mblk->addr; 312 uint8_t *bend = (uint8_t *) mblk->addr + mblk->size; 313 314 /* Data block <dbeg, dend) */ 315 uint8_t *dbeg = (uint8_t *) addr; 316 uint8_t *dend = (uint8_t *) addr + size; 317 318 /* Check for overlaps */ 319 if (((mbeg >= dbeg) && (mbeg < dend)) || 320 ((mend > dbeg) && (mend <= dend)) || 321 ((bbeg >= dbeg) && (bbeg < dend)) || 322 ((bend > dbeg) && (bend <= dend))) 323 return true; 324 325 return false; 326 } 327 328 329 /** test_overlap 330 * 331 * Test whether a block starting at @addr overlaps with another, previously 332 * allocated memory block or its control structure. 333 * 334 * @param addr Initial address of the block 335 * @param size Size of the block 336 * 337 * @return false if the block does not overlap. 338 * 339 */ 340 static int test_overlap(void *addr, size_t size) 341 { 342 link_t *entry; 343 bool fnd = false; 344 345 for (entry = mem_blocks.next; entry != &mem_blocks; entry = entry->next) { 346 if (overlap_match(entry, addr, size)) { 347 fnd = true; 348 break; 349 } 350 } 351 352 return fnd; 353 } 354 355 356 /** checked_malloc 357 * 358 * Allocate @size bytes of memory and check whether the chunk comes 359 * from the non-mapped memory region and whether the chunk overlaps 360 * with other, previously allocated, chunks. 361 * 362 * @param size Amount of memory to allocate 363 * 364 * @return NULL if the allocation failed. Sets the global error_flag to 365 * true if the allocation succeeded but is illegal. 366 * 367 */ 368 static void *checked_malloc(size_t size) 369 { 370 void *data; 371 372 /* Allocate the chunk of memory */ 373 data = malloc(size); 374 if (data == NULL) 375 return NULL; 376 377 /* Check for overlaps with other chunks */ 378 if (test_overlap(data, size)) { 379 TPRINTF("\nError: Allocated block overlaps with another " 380 "previously allocated block.\n"); 381 error_flag = true; 382 } 383 384 return data; 385 } 386 387 388 /** alloc_block 389 * 390 * Allocate a block of memory of @size bytes and add record about it into 391 * the mem_blocks list. Return a pointer to the block holder structure or 392 * NULL if the allocation failed. 393 * 394 * If the allocation is illegal (e.g. the memory does not come from the 395 * right region or some of the allocated blocks overlap with others), 396 * set the global error_flag. 397 * 398 * @param size Size of the memory block 399 * 400 */ 401 static mem_block_t alloc_block(size_t size) 402 { 403 /* Check for allocation limit */ 404 if (mem_allocated >= MAX_ALLOC) 405 return NULL; 406 407 /* Allocate the block holder */ 408 mem_block_t block = (mem_block_t) checked_malloc(sizeof(mem_block_s)); 409 if (block == NULL) 410 return NULL; 411 412 link_initialize(&block->link); 413 414 /* Allocate the block memory */ 415 block->addr = checked_malloc(size); 416 if (block->addr == NULL) { 417 free(block); 418 return NULL; 419 } 420 421 block->size = size; 422 423 /* Register the allocated block */ 424 list_append(&block->link, &mem_blocks); 425 mem_allocated += size + sizeof(mem_block_s); 426 mem_blocks_count++; 427 428 return block; 429 } 430 431 432 /** free_block 433 * 434 * Free the block of memory and the block control structure allocated by 435 * alloc_block. Set the global error_flag if an error occurs. 436 * 437 * @param block Block control structure 438 * 439 */ 440 static void free_block(mem_block_t block) 441 { 442 /* Unregister the block */ 443 list_remove(&block->link); 444 mem_allocated -= block->size + sizeof(mem_block_s); 445 mem_blocks_count--; 446 447 /* Free the memory */ 448 free(block->addr); 449 free(block); 450 } 451 452 453 /** expected_value 454 * 455 * Compute the expected value of a byte located at @pos in memory 456 * block described by @blk. 457 * 458 * @param blk Memory block control structure 459 * @param pos Position in the memory block data area 460 * 461 */ 462 static inline uint8_t expected_value(mem_block_t blk, uint8_t *pos) 463 { 464 return ((unsigned long) blk ^ (unsigned long) pos) & 0xff; 465 } 466 467 468 /** fill_block 469 * 470 * Fill the memory block controlled by @blk with data. 471 * 472 * @param blk Memory block control structure 473 * 474 */ 475 static void fill_block(mem_block_t blk) 476 { 477 uint8_t *pos; 478 uint8_t *end; 479 480 for (pos = blk->addr, end = pos + blk->size; pos < end; pos++) 481 *pos = expected_value(blk, pos); 482 } 483 484 485 /** check_block 486 * 487 * Check whether the block @blk contains the data it was filled with. 488 * Set global error_flag if an error occurs. 489 * 490 * @param blk Memory block control structure 491 * 492 */ 493 static void check_block(mem_block_t blk) 494 { 495 uint8_t *pos; 496 uint8_t *end; 497 498 for (pos = blk->addr, end = pos + blk->size; pos < end; pos++) { 499 if (*pos != expected_value (blk, pos)) { 500 TPRINTF("\nError: Corrupted content of a data block.\n"); 501 error_flag = true; 502 return; 503 } 504 } 505 } 506 507 508 static link_t *list_get_nth(link_t *list, unsigned int i) 509 { 510 unsigned int cnt = 0; 511 link_t *entry; 512 513 for (entry = list->next; entry != list; entry = entry->next) { 514 if (cnt == i) 515 return entry; 209 516 210 if ((subphase->cond.max_cycles) && 211 (cycles >= subphase->cond.max_cycles)) { 517 cnt++; 518 } 519 520 return NULL; 521 } 522 523 524 /** get_random_block 525 * 526 * Select a random memory block from the list of allocated blocks. 527 * 528 * @return Block control structure or NULL if the list is empty. 529 * 530 */ 531 static mem_block_t get_random_block(void) 532 { 533 if (mem_blocks_count == 0) 534 return NULL; 535 536 unsigned int blkidx = rand() % mem_blocks_count; 537 link_t *entry = list_get_nth(&mem_blocks, blkidx); 538 539 if (entry == NULL) { 540 TPRINTF("\nError: Corrupted list of allocated memory blocks.\n"); 541 error_flag = true; 542 } 543 544 return list_get_instance(entry, mem_block_s, link); 545 } 546 547 548 #define RETURN_IF_ERROR \ 549 { \ 550 if (error_flag) \ 551 return; \ 552 } 553 554 555 static void do_subphase(phase_s *phase, subphase_s *subphase) 556 { 557 unsigned int cycles; 558 for (cycles = 0; /* always */; cycles++) { 559 560 if (subphase->cond.max_cycles && 561 cycles >= subphase->cond.max_cycles) { 212 562 /* 213 563 * We have performed the required number of … … 222 572 unsigned int rnd = rand() % 100; 223 573 if (rnd < subphase->prob.alloc) { 224 /* 225 * Compute a random number lying in interval 226 * <min_block_size, max_block_size> 227 */ 574 /* Compute a random number lying in interval <min_block_size, max_block_size> */ 228 575 int alloc = phase->alloc.min_block_size + 229 576 (rand() % (phase->alloc.max_block_size - phase->alloc.min_block_size + 1)); 230 577 231 mem_block_t *blk = alloc_block(alloc);578 mem_block_t blk = alloc_block(alloc); 232 579 RETURN_IF_ERROR; 233 580 … … 238 585 break; 239 586 } 587 240 588 } else { 241 589 TPRINTF("A"); 242 590 fill_block(blk); 243 RETURN_IF_ERROR;244 591 } 245 592 246 593 } else if (rnd < subphase->prob.free) { 247 mem_block_t *blk = get_random_block();594 mem_block_t blk = get_random_block(); 248 595 if (blk == NULL) { 249 596 TPRINTF("F(R)"); … … 252 599 break; 253 600 } 601 254 602 } else { 255 603 TPRINTF("R"); … … 266 614 } 267 615 268 static void do_phase(phase_t *phase) 269 { 270 for (unsigned int subno = 0; subno < 3; subno++) { 271 subphase_t *subphase = &phase->subphases[subno]; 616 617 static void do_phase(phase_s *phase) 618 { 619 unsigned int subno; 620 621 for (subno = 0; subno < 3; subno++) { 622 subphase_s *subphase = & phase->subphases [subno]; 272 623 273 624 TPRINTF(".. Sub-phase %u (%s)\n", subno + 1, subphase->name); … … 281 632 init_mem(); 282 633 283 for (unsigned int phaseno = 0; phaseno < sizeof_array(phases);284 285 phase_ t*phase = &phases[phaseno];634 unsigned int phaseno; 635 for (phaseno = 0; phaseno < sizeof_array(phases); phaseno++) { 636 phase_s *phase = &phases[phaseno]; 286 637 287 638 TPRINTF("Entering phase %u (%s)\n", phaseno + 1, phase->name); … … 294 645 } 295 646 296 TPRINTF("Cleaning up.\n");297 done_mem();298 647 if (error_flag) 299 648 return "Test failed";
Note:
See TracChangeset
for help on using the changeset viewer.