Changeset d04e46e in mainline for uspace/app/rcutest/rcutest.c


Ignore:
Timestamp:
2012-11-24T00:26:11Z (12 years ago)
Author:
Adam Hraska <adam.hraska+hos@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
3ac5086
Parents:
a879d73
Message:

urcu: Expanded tests to support multiple threads.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/rcutest/rcutest.c

    ra879d73 rd04e46e  
    4848#include <rcu.h>
    4949
     50#include "fibril_synch.h"
     51
    5052
    5153#define USECS_PER_SEC (1000 * 1000)
    5254#define USECS_PER_MS  1000
    5355
     56/* fwd decl. */
     57struct test_info;
    5458
    5559typedef struct test_desc {
     
    6165                T_STRESS
    6266        } type;
    63         bool (*func)(void);
     67        bool (*func)(struct test_info*);
    6468        const char *name;
    6569        const char *desc;
     
    6771
    6872
    69 static bool run_all_tests(void);
    70 static bool run_sanity_tests(void);
    71 static bool run_stress_tests(void);
    72 
    73 static bool wait_for_one_reader(void);
    74 static bool basic_sanity_check(void);
    75 static bool dont_wait_for_new_reader(void);
    76 static bool wait_for_exiting_reader(void);
     73typedef struct test_info {
     74        size_t thread_cnt;
     75        test_desc_t *desc;
     76} test_info_t;
     77
     78
     79
     80static bool run_all_tests(struct test_info*);
     81static bool run_sanity_tests(struct test_info*);
     82static bool run_stress_tests(struct test_info*);
     83
     84static bool wait_for_one_reader(struct test_info*);
     85static bool basic_sanity_check(struct test_info*);
     86static bool dont_wait_for_new_reader(struct test_info*);
     87static bool wait_for_exiting_reader(struct test_info*);
    7788
    7889static test_desc_t test_desc[] = {
     
    157168/*--------------------------------------------------------------------*/
    158169
    159 static bool run_tests(bool (*include_filter)(test_desc_t *))
     170static bool run_tests(test_info_t *info, bool (*include_filter)(test_desc_t *))
    160171{
    161172        size_t failed_cnt = 0;
     
    167178                if (t->func && !t->aggregate && include_filter(t)) {
    168179                        printf("Running \'%s\'...\n", t->name);
    169                         bool ok = test_desc[i].func();
     180                        bool ok = test_desc[i].func(info);
    170181                       
    171182                        if (ok) {
     
    198209
    199210/* Runs all available tests tests one-by-one. */
    200 static bool run_all_tests(void)
     211static bool run_all_tests(test_info_t *test_info)
    201212{
    202213        printf("Running all tests...\n");
    203         return run_tests(all_tests_include_filter);
     214        return run_tests(test_info, all_tests_include_filter);
    204215}
    205216
     
    212223
    213224/* Runs all available stress tests one-by-one. */
    214 static bool run_stress_tests(void)
     225static bool run_stress_tests(test_info_t *test_info)
    215226{
    216227        printf("Running stress tests...\n");
    217         return run_tests(stress_tests_include_filter);
     228        return run_tests(test_info, stress_tests_include_filter);
    218229}
    219230
     
    226237
    227238/* Runs all available sanity tests one-by-one. */
    228 static bool run_sanity_tests(void)
     239static bool run_sanity_tests(test_info_t *test_info)
    229240{
    230241        printf("Running sanity tests...\n");
    231         return run_tests(sanity_tests_include_filter);
     242        return run_tests(test_info, sanity_tests_include_filter);
    232243}
    233244
     
    235246
    236247/* Locks/unlocks rcu and synchronizes without contention in a single fibril. */
    237 static bool basic_sanity_check(void)
     248static bool basic_sanity_check(test_info_t *test_info)
    238249{
    239250        rcu_read_lock();
     
    309320}
    310321
    311 static bool wait_for_one_reader(void)
     322static bool wait_for_one_reader(test_info_t *test_info)
    312323{
    313324        one_reader_info_t info = { 0 };
     
    446457}
    447458
    448 static bool dont_wait_for_new_reader(void)
     459static bool dont_wait_for_new_reader(test_info_t *test_info)
    449460{
    450461        two_reader_info_t info = { 0 };
     
    553564
    554565
    555 static bool wait_for_exiting_reader(void)
     566static bool wait_for_exiting_reader(test_info_t *test_info)
    556567{
    557568        exit_reader_info_t info = { 0 };
     
    588599
    589600/*--------------------------------------------------------------------*/
     601
     602static FIBRIL_MUTEX_INITIALIZE(blocking_mtx);
     603
     604static void dummy_fibril(void *arg)
     605{
     606        /* Block on an already locked mutex - enters the fibril manager. */
     607        fibril_mutex_lock(&blocking_mtx);
     608        assert(false);
     609}
     610
     611static bool create_threads(size_t cnt)
     612{
     613        /* Sanity check. */
     614        assert(cnt < 1024);
     615       
     616        /* Keep this mutex locked so that dummy fibrils never exit. */
     617        bool success = fibril_mutex_trylock(&blocking_mtx);
     618        assert(success);
     619       
     620        for (size_t k = 0; k < cnt; ++k) {
     621                thread_id_t tid;
     622               
     623                int ret = thread_create(dummy_fibril, NULL, "urcu-test-worker", &tid);
     624                if (EOK != ret) {
     625                        printf("Failed to create thread '%zu' (error: %d)\n", k + 1, ret);
     626                        return false;
     627                }
     628        }
     629       
     630        return true;
     631}
     632
    590633/*--------------------------------------------------------------------*/
    591634static test_desc_t *find_test(const char *name)
     
    604647        if (EOK == str_uint32_t(name, NULL, 0, true, &test_num)) {
    605648                if (test_num < test_desc_cnt && test_desc[test_num].func) {
    606                         printf("[%u]\n", test_num);
    607649                        return &test_desc[test_num];
    608650                }
     
    636678static void print_usage(void)
    637679{
    638         printf("Usage: rcutest [test_name|test_number]\n");
     680        printf("Usage: rcutest [test_name|test_number] {number_of_threads}\n");
    639681        list_tests();
    640682       
     
    645687
    646688
     689static bool parse_cmd_line(int argc, char **argv, test_info_t *info)
     690{
     691        if (argc != 2 && argc != 3) {
     692                print_usage();
     693                return false;
     694        }
     695       
     696        info->desc = find_test(argv[1]);
     697
     698        if (!info->desc) {
     699                printf("Non-existent test '%s'.\n", argv[1]);
     700                list_tests();
     701                return false;
     702        }
     703       
     704        if (argc == 3) {
     705                uint32_t thread_cnt = 0;
     706                int ret = str_uint32_t(argv[2], NULL, 0, true, &thread_cnt);
     707               
     708                if (ret == EOK && 1 <= thread_cnt && thread_cnt <= 64) {
     709                        info->thread_cnt = thread_cnt;
     710                } else {
     711                        info->thread_cnt = 1;
     712                        printf("Err: Invalid number of threads '%s'; using 1.\n", argv[2]);
     713                }
     714        }
     715       
     716        return true;
     717}
     718
    647719int main(int argc, char **argv)
    648720{
    649721        rcu_register_fibril();
    650722       
    651         if (argc != 2) {
    652                 print_usage();
    653                
     723        test_info_t info;
     724       
     725        bool ok = parse_cmd_line(argc, argv, &info);
     726        ok = ok && create_threads(info.thread_cnt - 1);
     727       
     728        if (ok) {
     729                assert(1 <= info.thread_cnt);
     730                test_desc_t *t = info.desc;
     731               
     732                printf("Running '%s' (in %zu threads)...\n", t->name, info.thread_cnt);
     733                ok = t->func(&info);
     734
     735                printf("%s: '%s'\n", ok ? "Passed" : "FAILED", t->name);
     736
     737                rcu_deregister_fibril();
     738               
     739                /* Let the kernel clean up the created background threads. */
     740                return ok ? 0 : 1;
     741        } else {
    654742                rcu_deregister_fibril();
    655743                return 2;
    656         }
    657        
    658         test_desc_t *t = find_test(argv[1]);
    659        
    660         if (t) {
    661                 printf("Running '%s'...\n", t->name);
    662                 bool ok = t->func();
    663                
    664                 printf("%s: '%s'\n", ok ? "Passed" : "FAILED", t->name);
    665                
    666                 rcu_deregister_fibril();
    667                 return ok ? 0 : 1;
    668         } else {
    669                 printf("Non-existent test name.\n");
    670                 list_tests();
    671                
    672                 rcu_deregister_fibril();
    673                 return 3;
    674744        }
    675745}
Note: See TracChangeset for help on using the changeset viewer.