Ignore:
File:
1 edited

Legend:

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

    r1b20da0 ra35b458  
    174174{
    175175        fid_t fid = fibril_create(func, arg);
    176        
     176
    177177        if (0 == fid) {
    178178                printf("Failed to create a fibril!\n");
    179179                return false;
    180180        }
    181        
     181
    182182        fibril_add_ready(fid);
    183183        return true;
     
    190190        size_t failed_cnt = 0;
    191191        size_t ok_cnt = 0;
    192        
     192
    193193        for (size_t i = 0; i < test_desc_cnt; ++i) {
    194194                test_desc_t *t = &test_desc[i];
    195                
     195
    196196                if (t->func && !t->aggregate && include_filter(t)) {
    197197                        printf("Running \'%s\'...\n", t->name);
    198198                        bool ok = test_desc[i].func(info);
    199                        
     199
    200200                        if (ok) {
    201201                                ++ok_cnt;
     
    207207                }
    208208        }
    209        
     209
    210210        printf("\n");
    211211
     
    215215                printf("%zu tests failed\n", failed_cnt);
    216216        }
    217        
     217
    218218        return 0 == failed_cnt;
    219219}
     
    273273        /* nop */
    274274        rcu_read_unlock();
    275        
     275
    276276        rcu_synchronize();
    277277
     
    284284        fibril_yield();
    285285        rcu_read_unlock();
    286        
     286
    287287        fibril_yield();
    288288        rcu_synchronize();
    289289        rcu_synchronize();
    290        
     290
    291291        rcu_read_lock();
    292292        /* nop */
     
    295295
    296296        rcu_read_unlock();
    297        
     297
    298298        return !rcu_read_locked();
    299299}
     
    312312{
    313313        rcu_register_fibril();
    314        
     314
    315315        printf("lock{");
    316316        rcu_read_lock();
     
    324324        ++arg->done_sleeps_cnt;
    325325        printf("}");
    326        
     326
    327327        if (arg->synched) {
    328328                arg->failed = 1;
    329329                printf("Error: rcu_sync exited prematurely.\n");
    330330        }
    331        
     331
    332332        arg->exited_cs = true;
    333333        rcu_read_unlock();
    334334        printf("}");
    335        
     335
    336336        rcu_deregister_fibril();
    337337        return 0;
     
    341341{
    342342        one_reader_info_t info = { 0 };
    343        
     343
    344344        if (!create_fibril((fibril_func_t) sleeping_reader, &info))
    345345                return false;
    346        
     346
    347347        /* 1 sec, waits for the reader to enter its critical section and sleep. */
    348348        async_usleep(1 * USECS_PER_SEC);
    349        
     349
    350350        if (!info.entered_cs || info.exited_cs) {
    351351                printf("Error: reader is unexpectedly outside of critical section.\n");
    352352                return false;
    353353        }
    354        
     354
    355355        info.synching = true;
    356356        printf("sync[");
     
    361361        /* Load info.exited_cs */
    362362        memory_barrier();
    363        
     363
    364364        if (!info.exited_cs || info.failed) {
    365365                printf("Error: rcu_sync() returned before the reader exited its CS.\n");
     
    394394{
    395395        rcu_register_fibril();
    396        
     396
    397397        printf("old-lock{");
    398398        rcu_read_lock();
    399399        arg->old_entered_cs = true;
    400        
     400
    401401        printf("wait-for-sync{");
    402402        /* Wait for rcu_sync() to start waiting for us. */
     
    405405        }
    406406        printf(" }");
    407        
     407
    408408        /* A new reader starts while rcu_sync() is in progress. */
    409        
     409
    410410        printf("wait-for-new-R{");
    411411        /* Wait for the new reader to enter its reader section. */
     
    414414        }
    415415        printf(" }");
    416        
     416
    417417        arg->old_exited_cs = true;
    418        
     418
    419419        assert(!arg->new_exited_cs);
    420        
     420
    421421        if (arg->synched) {
    422422                arg->failed = 1;
    423423                printf("Error: rcu_sync() did not wait for preexisting reader.\n");
    424424        }
    425        
     425
    426426        rcu_read_unlock();
    427427        printf(" }");
    428        
     428
    429429        rcu_deregister_fibril();
    430430        return 0;
     
    434434{
    435435        rcu_register_fibril();
    436        
     436
    437437        /* Wait until rcu_sync() starts. */
    438438        while (!arg->synching) {
    439439                async_usleep(WAIT_STEP_US);
    440440        }
    441        
     441
    442442        /*
    443443         * synching is set when rcu_sync() is about to be entered so wait
     
    445445         */
    446446        async_usleep(WAIT_STEP_US);
    447        
     447
    448448        printf("new-lock(");
    449449        rcu_read_lock();
     
    454454                async_usleep(WAIT_STEP_US);
    455455        }
    456        
     456
    457457        arg->new_exited_cs = true;
    458458        /* Write new_exited_cs before exiting reader section. */
    459459        memory_barrier();
    460        
     460
    461461        /*
    462462         * Preexisting reader should have exited by now, so rcu_synchronize()
     
    467467                printf("Error: preexisting reader should have exited by now!\n");
    468468        }
    469        
     469
    470470        rcu_read_unlock();
    471471        printf(")");
     
    478478{
    479479        two_reader_info_t info = { 0 };
    480        
     480
    481481        if (!create_fibril((fibril_func_t) preexisting_reader, &info))
    482482                return false;
     
    484484        if (!create_fibril((fibril_func_t) new_reader, &info))
    485485                return false;
    486        
     486
    487487        /* Waits for the preexisting_reader to enter its CS.*/
    488488        while (!info.old_entered_cs) {
    489489                async_usleep(WAIT_STEP_US);
    490490        }
    491        
     491
    492492        assert(!info.old_exited_cs);
    493493        assert(!info.new_entered_cs);
    494494        assert(!info.new_exited_cs);
    495        
     495
    496496        printf("sync[");
    497497        info.synching = true;
    498498        rcu_synchronize();
    499499        printf(" ]");
    500        
     500
    501501        /* Load info.exited_cs */
    502502        memory_barrier();
    503        
     503
    504504        if (!info.old_exited_cs) {
    505505                printf("Error: rcu_sync() returned before preexisting reader exited.\n");
    506506                info.failed = 1;
    507507        }
    508        
     508
    509509        bool new_outside_cs = !info.new_entered_cs || info.new_exited_cs;
    510        
     510
    511511        /* Test if new reader is waiting in CS before setting synched. */
    512512        compiler_barrier();
    513513        info.synched = true;
    514                
     514
    515515        if (new_outside_cs) {
    516516                printf("Error: new reader CS held up rcu_sync(). (4)\n");
     
    519519                /* Wait for the new reader. */
    520520                rcu_synchronize();
    521                
     521
    522522                if (!info.new_exited_cs) {
    523523                        printf("Error: 2nd rcu_sync() returned before new reader exited.\n");
    524524                        info.failed = 1;
    525525                }
    526                
     526
    527527                printf("\n");
    528528        }
    529        
     529
    530530        if (info.failed) {
    531531                /*
     
    535535                async_usleep(WAIT_STEP_US);
    536536        }
    537        
     537
    538538        return 0 == info.failed;
    539539}
     
    555555{
    556556        rcu_register_fibril();
    557        
     557
    558558        printf("old-lock{");
    559559        rcu_read_lock();
     
    561561        rcu_read_lock();
    562562        arg->entered_cs = true;
    563        
     563
    564564        printf("wait-for-sync{");
    565565        /* Wait for rcu_sync() to start waiting for us. */
     
    568568        }
    569569        printf(" }");
    570        
     570
    571571        rcu_read_unlock();
    572572        printf(" }");
     
    575575        /* Store exited_cs before unlocking reader section in deregister. */
    576576        memory_barrier();
    577        
     577
    578578        /* Deregister forcefully unlocks the reader section. */
    579579        rcu_deregister_fibril();
     
    585585{
    586586        exit_reader_info_t info = { 0 };
    587        
     587
    588588        if (!create_fibril((fibril_func_t) exiting_locked_reader, &info))
    589589                return false;
    590        
     590
    591591        /* Waits for the preexisting_reader to enter its CS.*/
    592592        while (!info.entered_cs) {
    593593                async_usleep(WAIT_STEP_US);
    594594        }
    595        
     595
    596596        assert(!info.exited_cs);
    597        
     597
    598598        printf("sync[");
    599599        info.synching = true;
     
    601601        info.synched = true;
    602602        printf(" ]\n");
    603        
     603
    604604        /* Load info.exited_cs */
    605605        memory_barrier();
    606        
     606
    607607        if (!info.exited_cs) {
    608608                printf("Error: rcu_deregister_fibril did not unlock the CS.\n");
    609609                return false;
    610610        }
    611        
     611
    612612        return true;
    613613}
     
    621621        atomic_t time;
    622622        atomic_t max_start_time_of_done_sync;
    623        
     623
    624624        size_t total_workers;
    625625        size_t done_reader_cnt;
     
    630630        size_t read_iters;
    631631        size_t upd_iters;
    632        
     632
    633633        atomic_t seed;
    634634        int failed;
     
    640640        fibril_mutex_lock(&arg->done_cnt_mtx);
    641641        ++*cnt;
    642        
     642
    643643        if (arg->total_workers == arg->done_reader_cnt + arg->done_updater_cnt) {
    644644                fibril_condvar_signal(&arg->done_cnt_changed);
    645645        }
    646        
     646
    647647        fibril_mutex_unlock(&arg->done_cnt_mtx);
    648648}
     
    651651{
    652652        rcu_register_fibril();
    653        
     653
    654654        size_t seed = (size_t) atomic_preinc(&arg->seed);
    655655        bool first = (seed == 1);
    656        
     656
    657657        for (size_t k = 0; k < arg->read_iters; ++k) {
    658658                /* Print progress if the first reader fibril. */
     
    660660                        printf(".");
    661661                }
    662                
     662
    663663                rcu_read_lock();
    664664                atomic_count_t start_time = atomic_preinc(&arg->time);
    665                
     665
    666666                /* Do some work. */
    667667                seed = next_rand(seed);
    668668                size_t idle_iters = seed % 8;
    669                
     669
    670670                for (size_t i = 0; i < idle_iters; ++i) {
    671671                        fibril_yield();
    672672                }
    673                
     673
    674674                /*
    675675                 * Check if the most recently started rcu_sync of the already
     
    681681                        arg->failed = 1;
    682682                }
    683                
     683
    684684                rcu_read_unlock();
    685685        }
    686        
     686
    687687        rcu_deregister_fibril();
    688688
     
    694694{
    695695        rcu_register_fibril();
    696        
     696
    697697        for (size_t k = 0; k < arg->upd_iters; ++k) {
    698698                atomic_count_t start_time = atomic_get(&arg->time);
    699699                rcu_synchronize();
    700                
     700
    701701                /* This is prone to a race but if it happens it errs to the safe side.*/
    702702                if (atomic_get(&arg->max_start_time_of_done_sync) < start_time) {
     
    704704                }
    705705        }
    706        
     706
    707707        rcu_deregister_fibril();
    708        
     708
    709709        signal_seq_fibril_done(arg, &arg->done_updater_cnt);
    710710        return 0;
     
    715715        size_t reader_cnt = test_info->thread_cnt;
    716716        size_t updater_cnt = test_info->thread_cnt;
    717                
     717
    718718        seq_test_info_t info = {
    719719                .time = {0},
     
    729729                .failed = 0,
    730730        };
    731        
     731
    732732        /* Create and start worker fibrils. */
    733733        for (size_t k = 0; k + k < reader_cnt + updater_cnt; ++k) {
    734734                bool ok = create_fibril((fibril_func_t) seq_reader, &info);
    735735                ok = ok && create_fibril((fibril_func_t) seq_updater, &info);
    736                
     736
    737737                if (!ok) {
    738738                        /* Let the already created fibrils corrupt the stack. */
     
    740740                }
    741741        }
    742        
     742
    743743        /* Wait for all worker fibrils to complete their work. */
    744744        fibril_mutex_lock(&info.done_cnt_mtx);
    745        
     745
    746746        while (info.total_workers != info.done_reader_cnt + info.done_updater_cnt) {
    747747                fibril_condvar_wait(&info.done_cnt_changed, &info.done_cnt_mtx);
    748748        }
    749        
     749
    750750        fibril_mutex_unlock(&info.done_cnt_mtx);
    751        
     751
    752752        if (info.failed) {
    753753                printf("Error: rcu_sync() did not wait for a preexisting reader.");
    754754        }
    755        
     755
    756756        return 0 == info.failed;
    757757}
     
    772772        /* Sanity check. */
    773773        assert(cnt < 1024);
    774        
     774
    775775        /* Keep this mutex locked so that dummy fibrils never exit. */
    776776        bool success = fibril_mutex_trylock(&blocking_mtx);
    777777        assert(success);
    778        
     778
    779779        for (size_t k = 0; k < cnt; ++k) {
    780780                thread_id_t tid;
    781                
     781
    782782                errno_t ret = thread_create(dummy_fibril, NULL, "urcu-test-worker", &tid);
    783783                if (EOK != ret) {
     
    786786                }
    787787        }
    788        
     788
    789789        return true;
    790790}
     
    796796        for (size_t k = 0; k < test_desc_cnt; ++k) {
    797797                test_desc_t *t = &test_desc[k];
    798                
     798
    799799                if (t->func && 0 == str_cmp(t->name, name))
    800800                        return t;
    801801        }
    802        
     802
    803803        /* Try to match the test number. */
    804804        uint32_t test_num = 0;
    805        
     805
    806806        if (EOK == str_uint32_t(name, NULL, 0, true, &test_num)) {
    807807                if (test_num < test_desc_cnt && test_desc[test_num].func) {
     
    809809                }
    810810        }
    811        
     811
    812812        return NULL;
    813813}
     
    816816{
    817817        printf("Available tests: \n");
    818        
     818
    819819        for (size_t i = 0; i < test_desc_cnt; ++i) {
    820820                test_desc_t *t = &test_desc[i];
    821                
     821
    822822                if (!t->func)
    823823                        continue;
    824                
     824
    825825                const char *type = "";
    826                
     826
    827827                if (t->type == T_SANITY)
    828828                        type = " (sanity)";
     
    839839        printf("Usage: rcutest [test_name|test_number] {number_of_threads}\n");
    840840        list_tests();
    841        
     841
    842842        printf("\nExample usage:\n");
    843843        printf("\trcutest *\n");
     
    852852                return false;
    853853        }
    854        
     854
    855855        info->desc = find_test(argv[1]);
    856856
     
    860860                return false;
    861861        }
    862        
     862
    863863        if (argc == 3) {
    864864                uint32_t thread_cnt = 0;
    865865                errno_t ret = str_uint32_t(argv[2], NULL, 0, true, &thread_cnt);
    866                
     866
    867867                if (ret == EOK && 1 <= thread_cnt && thread_cnt <= 64) {
    868868                        info->thread_cnt = thread_cnt;
     
    874874                info->thread_cnt = 1;
    875875        }
    876        
     876
    877877        return true;
    878878}
     
    881881{
    882882        rcu_register_fibril();
    883        
     883
    884884        test_info_t info;
    885        
     885
    886886        bool ok = parse_cmd_line(argc, argv, &info);
    887887        ok = ok && create_threads(info.thread_cnt - 1);
    888        
     888
    889889        if (ok) {
    890890                assert(1 <= info.thread_cnt);
    891891                test_desc_t *t = info.desc;
    892                
     892
    893893                printf("Running '%s' (in %zu threads)...\n", t->name, info.thread_cnt);
    894894                ok = t->func(&info);
     
    897897
    898898                rcu_deregister_fibril();
    899                
     899
    900900                /* Let the kernel clean up the created background threads. */
    901901                return ok ? 0 : 1;
Note: See TracChangeset for help on using the changeset viewer.