Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/rcu.c

    rab6edb6 r1433ecda  
    8282#include <thread.h>
    8383
    84 #include "private/fibril.h"
    85 
    8684
    8785/** RCU sleeps for RCU_SLEEP_MS before polling an active RCU reader again. */
     
    150148
    151149
    152 static void wait_for_readers(size_t reader_group);
     150static void wait_for_readers(size_t reader_group, blocking_mode_t blocking_mode);
    153151static void force_mb_in_all_threads(void);
    154152static bool is_preexisting_reader(const fibril_rcu_data_t *fib, size_t group);
    155153
    156 static void lock_sync(void);
     154static void lock_sync(blocking_mode_t blocking_mode);
    157155static void unlock_sync(void);
    158 static void sync_sleep(void);
     156static void sync_sleep(blocking_mode_t blocking_mode);
    159157
    160158static bool is_in_group(size_t nesting_cnt, size_t group);
     
    172170        assert(!fibril_rcu.registered);
    173171
    174         futex_lock(&rcu.list_futex);
     172        futex_down(&rcu.list_futex);
    175173        list_append(&fibril_rcu.link, &rcu.fibrils_list);
    176         futex_unlock(&rcu.list_futex);
     174        futex_up(&rcu.list_futex);
    177175
    178176        fibril_rcu.registered = true;
     
    197195        fibril_rcu.nesting_cnt = 0;
    198196
    199         futex_lock(&rcu.list_futex);
     197        futex_down(&rcu.list_futex);
    200198        list_remove(&fibril_rcu.link);
    201         futex_unlock(&rcu.list_futex);
     199        futex_up(&rcu.list_futex);
    202200
    203201        fibril_rcu.registered = false;
     
    242240
    243241/** Blocks until all preexisting readers exit their critical sections. */
    244 void rcu_synchronize(void)
     242void _rcu_synchronize(blocking_mode_t blocking_mode)
    245243{
    246244        assert(!rcu_read_locked());
     
    252250        size_t gp_in_progress = ACCESS_ONCE(rcu.cur_gp);
    253251
    254         lock_sync();
     252        lock_sync(blocking_mode);
    255253
    256254        /*
     
    300298
    301299        size_t new_reader_group = get_other_group(rcu.reader_group);
    302         wait_for_readers(new_reader_group);
     300        wait_for_readers(new_reader_group, blocking_mode);
    303301
    304302        /* Separates waiting for readers in new_reader_group from group flip. */
     
    312310        memory_barrier();
    313311
    314         wait_for_readers(old_reader_group);
     312        wait_for_readers(old_reader_group, blocking_mode);
    315313
    316314        /* MB_FORCE_U  */
     
    332330
    333331/** Waits for readers of reader_group to exit their readers sections. */
    334 static void wait_for_readers(size_t reader_group)
    335 {
    336         futex_lock(&rcu.list_futex);
     332static void wait_for_readers(size_t reader_group, blocking_mode_t blocking_mode)
     333{
     334        futex_down(&rcu.list_futex);
    337335
    338336        list_t quiescent_fibrils;
     
    345343
    346344                        if (is_preexisting_reader(fib, reader_group)) {
    347                                 futex_unlock(&rcu.list_futex);
    348                                 sync_sleep();
    349                                 futex_lock(&rcu.list_futex);
     345                                futex_up(&rcu.list_futex);
     346                                sync_sleep(blocking_mode);
     347                                futex_down(&rcu.list_futex);
    350348                                /* Break to while loop. */
    351349                                break;
     
    358356
    359357        list_concat(&rcu.fibrils_list, &quiescent_fibrils);
    360         futex_unlock(&rcu.list_futex);
    361 }
    362 
    363 static void lock_sync(void)
    364 {
    365         futex_lock(&rcu.sync_lock.futex);
     358        futex_up(&rcu.list_futex);
     359}
     360
     361static void lock_sync(blocking_mode_t blocking_mode)
     362{
     363        futex_down(&rcu.sync_lock.futex);
    366364        if (rcu.sync_lock.locked) {
    367                 blocked_fibril_t blocked_fib;
    368                 blocked_fib.id = fibril_get_id();
    369 
    370                 list_append(&blocked_fib.link, &rcu.sync_lock.blocked_fibrils);
    371 
    372                 do {
    373                         blocked_fib.is_ready = false;
    374                         futex_unlock(&rcu.sync_lock.futex);
    375                         futex_lock(&async_futex);
    376                         fibril_switch(FIBRIL_FROM_BLOCKED);
    377                         futex_unlock(&async_futex);
    378                         futex_lock(&rcu.sync_lock.futex);
    379                 } while (rcu.sync_lock.locked);
    380 
    381                 list_remove(&blocked_fib.link);
    382                 rcu.sync_lock.locked = true;
     365                if (blocking_mode == BM_BLOCK_FIBRIL) {
     366                        blocked_fibril_t blocked_fib;
     367                        blocked_fib.id = fibril_get_id();
     368
     369                        list_append(&blocked_fib.link, &rcu.sync_lock.blocked_fibrils);
     370
     371                        do {
     372                                blocked_fib.is_ready = false;
     373                                futex_up(&rcu.sync_lock.futex);
     374                                fibril_switch(FIBRIL_TO_MANAGER);
     375                                futex_down(&rcu.sync_lock.futex);
     376                        } while (rcu.sync_lock.locked);
     377
     378                        list_remove(&blocked_fib.link);
     379                        rcu.sync_lock.locked = true;
     380                } else {
     381                        assert(blocking_mode == BM_BLOCK_THREAD);
     382                        rcu.sync_lock.blocked_thread_cnt++;
     383                        futex_up(&rcu.sync_lock.futex);
     384                        futex_down(&rcu.sync_lock.futex_blocking_threads);
     385                }
    383386        } else {
    384387                rcu.sync_lock.locked = true;
     
    396399        if (0 < rcu.sync_lock.blocked_thread_cnt) {
    397400                --rcu.sync_lock.blocked_thread_cnt;
    398                 futex_unlock(&rcu.sync_lock.futex_blocking_threads);
     401                futex_up(&rcu.sync_lock.futex_blocking_threads);
    399402        } else {
    400403                /* Unlock but wake up any fibrils waiting for the lock. */
     
    411414
    412415                rcu.sync_lock.locked = false;
    413                 futex_unlock(&rcu.sync_lock.futex);
    414         }
    415 }
    416 
    417 static void sync_sleep(void)
     416                futex_up(&rcu.sync_lock.futex);
     417        }
     418}
     419
     420static void sync_sleep(blocking_mode_t blocking_mode)
    418421{
    419422        assert(rcu.sync_lock.locked);
     
    422425         * but keep sync locked.
    423426         */
    424         futex_unlock(&rcu.sync_lock.futex);
    425         async_usleep(RCU_SLEEP_MS * 1000);
    426         futex_lock(&rcu.sync_lock.futex);
     427        futex_up(&rcu.sync_lock.futex);
     428
     429        if (blocking_mode == BM_BLOCK_FIBRIL) {
     430                async_usleep(RCU_SLEEP_MS * 1000);
     431        } else {
     432                thread_usleep(RCU_SLEEP_MS * 1000);
     433        }
     434
     435        futex_down(&rcu.sync_lock.futex);
    427436}
    428437
Note: See TracChangeset for help on using the changeset viewer.