Changeset a2f42e5 in mainline for uspace/lib/urcu/rcu.c


Ignore:
Timestamp:
2012-11-23T19:57:38Z (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:
29b8138
Parents:
99022de
Message:

urcu: Fixed rcu_synchronize() early exit condition.

File:
1 edited

Legend:

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

    r99022de ra2f42e5  
    7272#include <compiler/barrier.h>
    7373#include <libarch/barrier.h>
    74 #include <adt/list.h>
    7574#include <futex.h>
    7675#include <macros.h>
    7776#include <async.h>
     77#include <adt/list.h>
    7878#include <smp_memory_barrier.h>
    79 
     79#include <assert.h>
     80
     81
     82/** RCU sleeps for RCU_SLEEP_MS before polling an active RCU reader again. */
    8083#define RCU_SLEEP_MS        10
    8184
     
    8790
    8891
    89 typedef struct rcu_fibril_data {
     92/** Fibril local RCU data. */
     93typedef struct fibril_rcu_data {
    9094        size_t nesting_cnt;
    9195        link_t link;
    92 } rcu_fibril_data_t;
    93 
     96        bool registered;
     97} fibril_rcu_data_t;
     98
     99/** Process global RCU data. */
    94100typedef struct rcu_data {
    95101        fibril_mutex_t mtx;
     
    101107
    102108
    103 static fibril_local rcu_fibril_data_t rcu_fibril = {
    104         .nesting_cnt = 0       
     109/** Fibril local RCU data. */
     110static fibril_local fibril_rcu_data_t fibril_rcu = {
     111        .nesting_cnt = 0,
     112        .link = {
     113                .next = NULL,
     114                .prev = NULL
     115        },
     116        .registered = false
    105117};
    106118
     119/** Process global RCU data. */
    107120static rcu_data_t rcu = {
    108121        .mtx = FIBRIL_MUTEX_INITIALIZER(rcu.mtx),
     
    116129static void wait_for_readers(size_t reader_group);
    117130static void force_mb_in_all_threads(void);
    118 static bool is_preexisting_reader(const rcu_fibril_data_t *fib, size_t group);
     131static bool is_preexisting_reader(const fibril_rcu_data_t *fib, size_t group);
    119132
    120133static bool is_in_group(size_t nesting_cnt, size_t group);
     
    130143void rcu_register_fibril(void)
    131144{
     145        assert(!fibril_rcu.registered);
     146       
    132147        futex_down(&rcu.list_futex);
    133         list_append(&rcu_fibril.link, &rcu.fibrils_list);
     148        list_append(&fibril_rcu.link, &rcu.fibrils_list);
    134149        futex_up(&rcu.list_futex);
     150       
     151        fibril_rcu.registered = true;
    135152}
    136153
     
    142159void rcu_deregister_fibril(void)
    143160{
     161        assert(fibril_rcu.registered);
     162       
    144163        /*
    145164         * Forcefully unlock any reader sections. The fibril is exiting
     
    149168         */
    150169        memory_barrier();
    151         rcu_fibril.nesting_cnt = 0;
     170        fibril_rcu.nesting_cnt = 0;
    152171       
    153172        futex_down(&rcu.list_futex);
    154         list_remove(&rcu_fibril.link);
     173        list_remove(&fibril_rcu.link);
    155174        futex_up(&rcu.list_futex);
     175
     176        fibril_rcu.registered = false;
    156177}
    157178
     
    162183void rcu_read_lock(void)
    163184{
    164         size_t nesting_cnt = ACCESS_ONCE(rcu_fibril.nesting_cnt);
     185        assert(fibril_rcu.registered);
     186       
     187        size_t nesting_cnt = ACCESS_ONCE(fibril_rcu.nesting_cnt);
    165188       
    166189        if (0 == (nesting_cnt >> RCU_NESTING_SHIFT)) {
    167                 ACCESS_ONCE(rcu_fibril.nesting_cnt) = ACCESS_ONCE(rcu.reader_group);
     190                ACCESS_ONCE(fibril_rcu.nesting_cnt) = ACCESS_ONCE(rcu.reader_group);
    168191                /* Required by MB_FORCE_L */
    169192                compiler_barrier(); /* CC_BAR_L */
    170193        } else {
    171                 ACCESS_ONCE(rcu_fibril.nesting_cnt) = nesting_cnt + RCU_NESTING_INC;
     194                ACCESS_ONCE(fibril_rcu.nesting_cnt) = nesting_cnt + RCU_NESTING_INC;
    172195        }
    173196}
     
    176199void rcu_read_unlock(void)
    177200{
     201        assert(fibril_rcu.registered);
     202       
    178203        /* Required by MB_FORCE_U */
    179204        compiler_barrier(); /* CC_BAR_U */
    180205        /* todo: ACCESS_ONCE(nesting_cnt) ? */
    181         rcu_fibril.nesting_cnt -= RCU_NESTING_INC;
     206        fibril_rcu.nesting_cnt -= RCU_NESTING_INC;
     207}
     208
     209/** Returns true if the current fibril is in an RCU reader section. */
     210bool rcu_read_locked(void)
     211{
     212        return 0 != (fibril_rcu.nesting_cnt >> RCU_NESTING_SHIFT);
    182213}
    183214
     
    185216void rcu_synchronize(void)
    186217{
     218        assert(!rcu_read_locked());
     219       
    187220        /* Contain load of rcu.cur_gp. */
    188221        memory_barrier();
     
    201234         * after that, gp_in_progress + 2, already started.
    202235         */
    203         if (rcu.cur_gp + 2 >= gp_in_progress) {
     236        /* rcu.cur_gp >= gp_in_progress + 2, but tolerates overflows. */
     237        if (rcu.cur_gp != gp_in_progress && rcu.cur_gp + 1 != gp_in_progress) {
    204238                fibril_mutex_unlock(&rcu.mtx);
    205239                return;
     
    280314        while (!list_empty(&rcu.fibrils_list)) {
    281315                list_foreach_safe(rcu.fibrils_list, fibril_it, next_fibril) {
    282                         rcu_fibril_data_t *fib = member_to_inst(fibril_it,
    283                                 rcu_fibril_data_t, link);
     316                        fibril_rcu_data_t *fib = member_to_inst(fibril_it,
     317                                fibril_rcu_data_t, link);
    284318                       
    285319                        if (is_preexisting_reader(fib, reader_group)) {
     
    299333}
    300334
    301 static bool is_preexisting_reader(const rcu_fibril_data_t *fib, size_t group)
     335static bool is_preexisting_reader(const fibril_rcu_data_t *fib, size_t group)
    302336{
    303337        size_t nesting_cnt = ACCESS_ONCE(fib->nesting_cnt);
Note: See TracChangeset for help on using the changeset viewer.