Better:

    rcu_read_lock();
    do {
        pgtbl = d->cur_pgtbl;
        smp_rmb();
        root = d->cur_root;
        smp_rmb();

        /* d->cur_pgtbl == d->next_pgtbl only during an update.  */
    } while (pgtbl == d->next_pgtbl);
    ...
    rcu_read_unlock();

And in the writer:

    old_pgtbl = d->cur_pgtbl;

    /* Point to the new page table, tell readers cur_root is invalid.  */
    smp_wmb();
    d->cur_pgtbl = d->next_pgtbl;

    /* Write the root before updating the page table.  */
    smp_wmb();
    d->cur_root = d->next_root;

    /* Write cur_root before telling readers it is valid.  */
    smp_wmb();
    d->next_pgtbl = NULL;

    /* Drop reference once readers will be done with it.  */
    call_rcu(page_table_unref, old_pgtbl, rcu);

Paolo

Reply via email to