Changeset 5d230a30 in mainline
- Timestamp:
- 2012-11-24T02:11:38Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 69146b93
- Parents:
- 3ac5086
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/rcutest/rcutest.c
r3ac5086 r5d230a30 44 44 #include <async.h> 45 45 #include <fibril.h> 46 #include <fibril_synch.h> 46 47 #include <compiler/barrier.h> 48 #include <futex.h> 47 49 48 50 #include <rcu.h> 49 51 50 #include "fibril_synch.h"51 52 52 53 … … 86 87 static bool dont_wait_for_new_reader(struct test_info*); 87 88 static bool wait_for_exiting_reader(struct test_info*); 89 static bool seq_test(struct test_info*); 90 88 91 89 92 static test_desc_t test_desc[] = { … … 140 143 { 141 144 .aggregate = false, 145 .type = T_STRESS, 146 .func = seq_test, 147 .name = "seq", 148 .desc = "Checks lock/unlock/sync w/ global time sequence.", 149 }, 150 { 151 .aggregate = false, 142 152 .type = T_OTHER, 143 153 .func = NULL, … … 150 160 151 161 /*--------------------------------------------------------------------*/ 162 163 static size_t next_rand(size_t seed) 164 { 165 return (seed * 1103515245 + 12345) & ((1U << 31) - 1); 166 } 167 152 168 153 169 typedef int (*fibril_func_t)(void *); … … 600 616 /*--------------------------------------------------------------------*/ 601 617 618 typedef struct { 619 atomic_t time; 620 atomic_t max_start_time_of_done_sync; 621 622 size_t total_workers; 623 size_t done_reader_cnt; 624 size_t done_updater_cnt; 625 fibril_mutex_t done_cnt_mtx; 626 fibril_condvar_t done_cnt_changed; 627 628 size_t read_iters; 629 size_t upd_iters; 630 631 atomic_t seed; 632 int failed; 633 } seq_test_info_t; 634 635 636 static void signal_seq_fibril_done(seq_test_info_t *arg, size_t *cnt) 637 { 638 fibril_mutex_lock(&arg->done_cnt_mtx); 639 ++*cnt; 640 641 if (arg->total_workers == arg->done_reader_cnt + arg->done_updater_cnt) { 642 fibril_condvar_signal(&arg->done_cnt_changed); 643 } 644 645 fibril_mutex_unlock(&arg->done_cnt_mtx); 646 } 647 648 static int seq_reader(seq_test_info_t *arg) 649 { 650 rcu_register_fibril(); 651 652 size_t seed = (size_t) atomic_preinc(&arg->seed); 653 bool first = (seed == 1); 654 655 for (size_t k = 0; k < arg->read_iters; ++k) { 656 /* Print progress if the first reader fibril. */ 657 if (first && 0 == k % (arg->read_iters/100 + 1)) { 658 printf("."); 659 } 660 661 rcu_read_lock(); 662 atomic_count_t start_time = atomic_preinc(&arg->time); 663 664 /* Do some work. */ 665 seed = next_rand(seed); 666 size_t idle_iters = seed % 8; 667 668 for (size_t i = 0; i < idle_iters; ++i) { 669 fibril_yield(); 670 } 671 672 /* 673 * Check if the most recently started rcu_sync of the already 674 * finished rcu_syncs did not happen to start after this reader 675 * and, therefore, should have waited for this reader to exit 676 * (but did not - since it already announced it completed). 677 */ 678 if (start_time <= atomic_get(&arg->max_start_time_of_done_sync)) { 679 arg->failed = 1; 680 } 681 682 rcu_read_unlock(); 683 } 684 685 rcu_deregister_fibril(); 686 687 signal_seq_fibril_done(arg, &arg->done_reader_cnt); 688 return 0; 689 } 690 691 static int seq_updater(seq_test_info_t *arg) 692 { 693 rcu_register_fibril(); 694 695 for (size_t k = 0; k < arg->upd_iters; ++k) { 696 atomic_count_t start_time = atomic_get(&arg->time); 697 rcu_synchronize(); 698 699 /* This is prone to a race but if it happens it errs to the safe side.*/ 700 if (atomic_get(&arg->max_start_time_of_done_sync) < start_time) { 701 atomic_set(&arg->max_start_time_of_done_sync, start_time); 702 } 703 } 704 705 rcu_deregister_fibril(); 706 707 signal_seq_fibril_done(arg, &arg->done_updater_cnt); 708 return 0; 709 } 710 711 static bool seq_test(test_info_t *test_info) 712 { 713 size_t reader_cnt = test_info->thread_cnt; 714 size_t updater_cnt = test_info->thread_cnt; 715 716 seq_test_info_t info = { 717 .time = {0}, 718 .max_start_time_of_done_sync = {0}, 719 .read_iters = 10 * 1000, 720 .upd_iters = 5 * 1000, 721 .total_workers = updater_cnt + reader_cnt, 722 .done_reader_cnt = 0, 723 .done_updater_cnt = 0, 724 .done_cnt_mtx = FIBRIL_MUTEX_INITIALIZER(info.done_cnt_mtx), 725 .done_cnt_changed = FIBRIL_CONDVAR_INITIALIZER(info.done_cnt_changed), 726 .seed = {0}, 727 .failed = 0, 728 }; 729 730 /* Create and start worker fibrils. */ 731 for (size_t k = 0; k + k < reader_cnt + updater_cnt; ++k) { 732 bool ok = create_fibril((fibril_func_t) seq_reader, &info); 733 ok = ok && create_fibril((fibril_func_t) seq_updater, &info); 734 735 if (!ok) { 736 /* Let the already created fibrils corrupt the stack. */ 737 return false; 738 } 739 } 740 741 /* Wait for all worker fibrils to complete their work. */ 742 fibril_mutex_lock(&info.done_cnt_mtx); 743 744 while (info.total_workers != info.done_reader_cnt + info.done_updater_cnt) { 745 fibril_condvar_wait(&info.done_cnt_changed, &info.done_cnt_mtx); 746 } 747 748 fibril_mutex_unlock(&info.done_cnt_mtx); 749 750 if (info.failed) { 751 printf("Error: rcu_sync() did not wait for a preexisting reader."); 752 } 753 754 return 0 == info.failed; 755 } 756 757 /*--------------------------------------------------------------------*/ 758 602 759 static FIBRIL_MUTEX_INITIALIZE(blocking_mtx); 603 760 … … 712 869 printf("Err: Invalid number of threads '%s'; using 1.\n", argv[2]); 713 870 } 871 } else { 872 info->thread_cnt = 1; 714 873 } 715 874
Note:
See TracChangeset
for help on using the changeset viewer.