|
10 | 10 | #include <zephyr/kernel.h>
|
11 | 11 | #include <zephyr/ztest.h>
|
12 | 12 | #include <zephyr/drivers/counter.h>
|
| 13 | +#include <zephyr/ztress.h> |
| 14 | +#include <zephyr/random/random.h> |
13 | 15 |
|
14 | 16 | #include <dmm.h>
|
15 | 17 |
|
@@ -383,6 +385,182 @@ ZTEST_USER_F(dmm, test_check_multiple_alloc_and_free)
|
383 | 385 | }
|
384 | 386 | }
|
385 | 387 |
|
| 388 | +struct dmm_stress_data { |
| 389 | + void *mem_reg; |
| 390 | + void *alloc_ptr[32]; |
| 391 | + uint8_t alloc_token[32]; |
| 392 | + size_t alloc_len[32]; |
| 393 | + atomic_t alloc_mask; |
| 394 | + atomic_t busy_mask; |
| 395 | + atomic_t fails; |
| 396 | + atomic_t cnt; |
| 397 | + bool cached; |
| 398 | +}; |
| 399 | + |
| 400 | +static void stress_free_op(struct dmm_stress_data *data, int prio, int id) |
| 401 | +{ |
| 402 | + /* buffer is allocated. */ |
| 403 | + uint8_t token = data->alloc_token[id]; |
| 404 | + size_t len = data->alloc_len[id]; |
| 405 | + uint8_t *ptr = data->alloc_ptr[id]; |
| 406 | + int rv; |
| 407 | + |
| 408 | + for (int j = 0; j < len; j++) { |
| 409 | + uint8_t exp_val = (uint8_t)(token + j); |
| 410 | + |
| 411 | + if (ptr[j] != exp_val) { |
| 412 | + for (int k = 0; k < len; k++) { |
| 413 | + printk("%02x ", ptr[k]); |
| 414 | + } |
| 415 | + } |
| 416 | + zassert_equal(ptr[j], exp_val, "At %d got:%d exp:%d, len:%d id:%d, alloc_cnt:%d", |
| 417 | + j, ptr[j], exp_val, len, id, (uint32_t)data->cnt); |
| 418 | + } |
| 419 | + |
| 420 | + rv = dmm_buffer_in_release(data->mem_reg, ptr, len, ptr); |
| 421 | + zassert_ok(rv); |
| 422 | + /* Indicate that buffer is released. */ |
| 423 | + atomic_and(&data->alloc_mask, ~BIT(id)); |
| 424 | +} |
| 425 | + |
| 426 | +static bool stress_alloc_op(struct dmm_stress_data *data, int prio, int id) |
| 427 | +{ |
| 428 | + uint32_t r32 = sys_rand32_get(); |
| 429 | + size_t len = r32 % 512; |
| 430 | + uint8_t *ptr = data->alloc_ptr[id]; |
| 431 | + int rv; |
| 432 | + |
| 433 | + /* Rarely allocate bigger buffer. */ |
| 434 | + if ((r32 & 0x7) == 0) { |
| 435 | + len += 512; |
| 436 | + } |
| 437 | + |
| 438 | + rv = dmm_buffer_in_prepare(data->mem_reg, &r32/*dummy*/, len, (void **)&ptr); |
| 439 | + if (rv < 0) { |
| 440 | + atomic_inc(&data->fails); |
| 441 | + return true; |
| 442 | + } |
| 443 | + |
| 444 | + uint8_t token = r32 >> 24; |
| 445 | + |
| 446 | + data->alloc_ptr[id] = ptr; |
| 447 | + data->alloc_len[id] = len; |
| 448 | + data->alloc_token[id] = token; |
| 449 | + for (int j = 0; j < len; j++) { |
| 450 | + ptr[j] = (uint8_t)(j + token); |
| 451 | + } |
| 452 | + if (data->cached) { |
| 453 | + sys_cache_data_flush_range(ptr, len); |
| 454 | + } |
| 455 | + atomic_inc(&data->cnt); |
| 456 | + return false; |
| 457 | +} |
| 458 | + |
| 459 | +bool stress_func(void *user_data, uint32_t cnt, bool last, int prio) |
| 460 | +{ |
| 461 | + struct dmm_stress_data *data = user_data; |
| 462 | + uint32_t r = sys_rand32_get(); |
| 463 | + int rpt = r & 0x3; |
| 464 | + |
| 465 | + r >>= 2; |
| 466 | + |
| 467 | + for (int i = 0; i < rpt + 1; i++) { |
| 468 | + int id = r % 32; |
| 469 | + int key; |
| 470 | + bool free_op; |
| 471 | + bool clear_bit; |
| 472 | + |
| 473 | + key = irq_lock(); |
| 474 | + if ((data->busy_mask & BIT(id)) == 0) { |
| 475 | + data->busy_mask |= BIT(id); |
| 476 | + if (data->alloc_mask & BIT(id)) { |
| 477 | + free_op = true; |
| 478 | + } else { |
| 479 | + data->alloc_mask |= BIT(id); |
| 480 | + free_op = false; |
| 481 | + } |
| 482 | + } else { |
| 483 | + irq_unlock(key); |
| 484 | + continue; |
| 485 | + } |
| 486 | + |
| 487 | + irq_unlock(key); |
| 488 | + r >>= 5; |
| 489 | + |
| 490 | + if (free_op) { |
| 491 | + stress_free_op(data, prio, id); |
| 492 | + clear_bit = true; |
| 493 | + } else { |
| 494 | + clear_bit = stress_alloc_op(data, prio, id); |
| 495 | + } |
| 496 | + |
| 497 | + key = irq_lock(); |
| 498 | + data->busy_mask &= ~BIT(id); |
| 499 | + if (clear_bit) { |
| 500 | + data->alloc_mask &= ~BIT(id); |
| 501 | + } |
| 502 | + irq_unlock(key); |
| 503 | + } |
| 504 | + |
| 505 | + return true; |
| 506 | +} |
| 507 | + |
| 508 | +static void free_all(struct dmm_stress_data *data) |
| 509 | +{ |
| 510 | + while (data->alloc_mask) { |
| 511 | + int id = 31 - __builtin_clz(data->alloc_mask); |
| 512 | + |
| 513 | + stress_free_op(data, 0, id); |
| 514 | + data->alloc_mask &= ~BIT(id); |
| 515 | + } |
| 516 | +} |
| 517 | + |
| 518 | +static void stress_allocator(void *mem_reg, bool cached) |
| 519 | +{ |
| 520 | + uint32_t timeout = 3000; |
| 521 | + struct dmm_stress_data ctx; |
| 522 | + int rv; |
| 523 | + uint32_t curr_use; |
| 524 | + |
| 525 | + memset(&ctx, 0, sizeof(ctx)); |
| 526 | + ctx.mem_reg = mem_reg; |
| 527 | + ctx.cached = cached; |
| 528 | + |
| 529 | + if (IS_ENABLED(CONFIG_DMM_STATS)) { |
| 530 | + rv = dmm_stats_get(ctx.mem_reg, NULL, &curr_use, NULL); |
| 531 | + zassert_ok(rv); |
| 532 | + } |
| 533 | + |
| 534 | + ztress_set_timeout(K_MSEC(timeout)); |
| 535 | + |
| 536 | + ZTRESS_EXECUTE(ZTRESS_THREAD(stress_func, &ctx, INT32_MAX, INT32_MAX, Z_TIMEOUT_TICKS(4)), |
| 537 | + ZTRESS_THREAD(stress_func, &ctx, INT32_MAX, INT32_MAX, Z_TIMEOUT_TICKS(4)), |
| 538 | + ZTRESS_THREAD(stress_func, &ctx, INT32_MAX, INT32_MAX, Z_TIMEOUT_TICKS(4))); |
| 539 | + |
| 540 | + free_all(&ctx); |
| 541 | + TC_PRINT("Executed %d allocation operation. Failed to allocate %d times.\n", |
| 542 | + (uint32_t)ctx.cnt, (uint32_t)ctx.fails); |
| 543 | + |
| 544 | + if (IS_ENABLED(CONFIG_DMM_STATS)) { |
| 545 | + uint32_t curr_use2; |
| 546 | + |
| 547 | + rv = dmm_stats_get(ctx.mem_reg, NULL, &curr_use2, NULL); |
| 548 | + zassert_ok(rv); |
| 549 | + zassert_equal(curr_use, curr_use2, "Unexpected usage got:%d exp:%d", |
| 550 | + curr_use2, curr_use); |
| 551 | + } |
| 552 | +} |
| 553 | + |
| 554 | +ZTEST_F(dmm, test_stress_allocator_nocache) |
| 555 | +{ |
| 556 | + stress_allocator(fixture->regions[DMM_TEST_REGION_NOCACHE].mem_reg, false); |
| 557 | +} |
| 558 | + |
| 559 | +ZTEST_F(dmm, test_stress_allocator_cache) |
| 560 | +{ |
| 561 | + stress_allocator(fixture->regions[DMM_TEST_REGION_CACHE].mem_reg, true); |
| 562 | +} |
| 563 | + |
386 | 564 | ZTEST_SUITE(dmm, NULL, test_setup, NULL, test_cleanup, NULL);
|
387 | 565 |
|
388 | 566 | int dmm_test_prepare(void)
|
|
0 commit comments