Changeset a35b458 in mainline for kernel/generic/src/adt/cht.c


Ignore:
Timestamp:
2018-03-02T20:10:49Z (7 years ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f1380b7
Parents:
3061bc1
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2018-02-28 17:38:31)
git-committer:
Jiří Zárevúcky <zarevucky.jiri@…> (2018-03-02 20:10:49)
Message:

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/adt/cht.c

    r3061bc1 ra35b458  
    531531        if (!op || !op->hash || !op->key_hash || !op->equal || !op->key_equal)
    532532                return false;
    533        
     533
    534534        size_t min_order = size_to_order(min_size, CHT_MIN_ORDER);
    535535        size_t order = size_to_order(init_size, min_order);
    536        
     536
    537537        h->b = alloc_buckets(order, false, can_block);
    538        
     538
    539539        if (!h->b)
    540540                return false;
    541        
     541
    542542        h->max_load = (max_load == 0) ? CHT_MAX_LOAD : max_load;
    543543        h->min_order = min_order;
     
    546546        atomic_set(&h->item_cnt, 0);
    547547        atomic_set(&h->resize_reqs, 0);
    548        
     548
    549549        if (NULL == op->remove_callback) {
    550550                h->op->remove_callback = dummy_remove_callback;
    551551        }
    552        
     552
    553553        /*
    554554         * Cached item hashes are stored in item->rcu_link.func. Once the item
     
    556556         */
    557557        h->invalid_hash = (uintptr_t)h->op->remove_callback;
    558        
     558
    559559        /* Ensure the initialization takes place before we start using the table. */
    560560        write_barrier();
    561        
     561
    562562        return true;
    563563}
     
    581581                sizeof(cht_buckets_t) + (bucket_cnt - 1) * sizeof(marked_ptr_t);
    582582        cht_buckets_t *b = malloc(bytes, can_block ? 0 : FRAME_ATOMIC);
    583        
     583
    584584        if (!b)
    585585                return NULL;
    586        
     586
    587587        b->order = order;
    588        
     588
    589589        marked_ptr_t head_link = set_invalid
    590590                ? make_link(&sentinel, N_INVALID)
    591591                : make_link(&sentinel, N_NORMAL);
    592        
     592
    593593        for (size_t i = 0; i < bucket_cnt; ++i) {
    594594                b->head[i] = head_link;
    595595        }
    596        
     596
    597597        return b;
    598598}
     
    607607                if (bucket_cnt <= ((size_t)1 << order))
    608608                        return order;
    609                
     609
    610610                ++order;
    611611        } while (order < CHT_MAX_ORDER);
    612        
     612
    613613        return order;
    614614}
     
    623623{
    624624        cht_destroy_unsafe(h);
    625        
     625
    626626        /* You must clear the table of items. Otherwise cht_destroy will leak. */
    627627        assert(atomic_get(&h->item_cnt) == 0);
     
    635635                rcu_barrier();
    636636        }
    637        
     637
    638638        /* Wait for all remove_callback()s to complete. */
    639639        rcu_barrier();
    640        
     640
    641641        free(h->b);
    642642        h->b = NULL;
     
    688688        /* See docs to cht_find() and cht_find_lazy(). */
    689689        assert(rcu_read_locked());
    690        
     690
    691691        size_t hash = calc_key_hash(h, key);
    692        
     692
    693693        cht_buckets_t *b = rcu_access(h->b);
    694694        size_t idx = calc_bucket_idx(hash, b->order);
     
    698698         */
    699699        marked_ptr_t head = b->head[idx];
    700        
     700
    701701        /* Undergoing a resize - take the slow path. */
    702702        if (N_INVALID == get_mark(head))
    703703                return find_resizing(h, key, hash, head, idx);
    704        
     704
    705705        return search_bucket(h, head, key, hash);
    706706}
     
    734734        assert(rcu_read_locked());
    735735        assert(item);
    736        
     736
    737737        return find_duplicate(h, item, calc_node_hash(h, item), get_next(item->link));
    738738}
     
    758758                prev = cur->link;
    759759        } while (node_hash(h, cur) < search_hash);
    760        
     760
    761761        /*
    762762         * Only search for an item with an equal key if cur is not the sentinel
     
    768768                                return cur;
    769769                }
    770                
     770
    771771                cur = get_next(cur->link);
    772772                assert(cur);
    773773        }
    774        
     774
    775775        /*
    776776         * In the unlikely case that we have encountered a node whose cached
     
    782782                goto try_again;
    783783        }
    784        
     784
    785785        return NULL;
    786786}
     
    792792        assert(N_INVALID == get_mark(old_head));
    793793        assert(h->new_b);
    794        
     794
    795795        size_t new_idx = calc_bucket_idx(hash, h->new_b->order);
    796796        marked_ptr_t new_head = h->new_b->head[new_idx];
    797797        marked_ptr_t search_head = new_head;
    798        
     798
    799799        /* Growing. */
    800800        if (h->b->order < h->new_b->order) {
     
    818818                                new_head = h->new_b->head[grow_idx(old_idx)];
    819819                        }
    820                        
     820
    821821                        /* new_head is now the moved bucket, either valid or invalid. */
    822                        
     822
    823823                        /*
    824824                         * The old bucket was definitely moved to new_head but the
     
    845845                        }
    846846                }
    847                
     847
    848848                return search_bucket(h, search_head, key, hash);
    849849        } else if (h->b->order > h->new_b->order) {
    850850                /* Shrinking. */
    851                
     851
    852852                /* Index of the bucket in the old table that was moved. */
    853853                size_t move_src_idx = grow_idx(new_idx);
    854854                marked_ptr_t moved_old_head = h->b->head[move_src_idx];
    855                
     855
    856856                /*
    857857                 * h->b->head[move_src_idx] had already been moved to new_head
     
    883883                        search_head = moved_old_head;
    884884                }
    885                
     885
    886886                cht_link_t *ret = search_bucket(h, search_head, key, hash);
    887                
     887
    888888                if (ret)
    889889                        return ret;
     
    906906                        return search_bucket(h, old_head, key, hash);
    907907                }
    908                
     908
    909909                return NULL;
    910910        } else {
     
    979979        bool resizing = false;
    980980        bool inserted = false;
    981        
     981
    982982        do {
    983983                walk_mode_t walk_mode = WM_NORMAL;
    984984                bool join_finishing;
    985                
     985
    986986                resizing = resizing || (N_NORMAL != get_mark(*phead));
    987                
     987
    988988                /* The table is resizing. Get the correct bucket head. */
    989989                if (resizing) {
    990990                        upd_resizing_head(h, hash, &phead, &join_finishing, &walk_mode);
    991991                }
    992                
     992
    993993                wnd_t wnd = {
    994994                        .ppred = phead,
     
    996996                        .last = NULL
    997997                };
    998                
     998
    999999                if (!find_wnd_and_gc(h, hash, walk_mode, &wnd, &resizing)) {
    10001000                        /* Could not GC a node; or detected an unexpected resize. */
    10011001                        continue;
    10021002                }
    1003                
     1003
    10041004                if (dup_item && has_duplicate(h, item, hash, wnd.cur, dup_item)) {
    10051005                        rcu_read_unlock();
    10061006                        return false;
    10071007                }
    1008                
     1008
    10091009                inserted = insert_at(item, &wnd, walk_mode, &resizing);
    10101010        } while (!inserted);
    1011        
     1011
    10121012        rcu_read_unlock();
    10131013
     
    10321032{
    10331033        marked_ptr_t ret;
    1034        
     1034
    10351035        if (walk_mode == WM_NORMAL) {
    10361036                item->link = make_link(wnd->cur, N_NORMAL);
    10371037                /* Initialize the item before adding it to a bucket. */
    10381038                memory_barrier();
    1039                
     1039
    10401040                /* Link a clean/normal predecessor to the item. */
    10411041                ret = cas_link(wnd->ppred, wnd->cur, N_NORMAL, item, N_NORMAL);
    1042                
     1042
    10431043                if (ret == make_link(wnd->cur, N_NORMAL)) {
    10441044                        return true;
     
    10541054                /* Initialize the item before adding it to a bucket. */
    10551055                memory_barrier();
    1056                
     1056
    10571057                /* Link the not-deleted predecessor to the item. Move its JF mark. */
    10581058                ret = cas_link(wnd->ppred, wnd->cur, jf_mark, item, N_NORMAL);
    1059                
     1059
    10601060                return ret == make_link(wnd->cur, jf_mark);
    10611061        } else {
     
    10651065                /* Initialize the item before adding it to a bucket. */
    10661066                memory_barrier();
    1067                
     1067
    10681068                mark_t pred_mark = get_mark(*wnd->ppred);
    10691069                /* If the predecessor is a join node it may be marked deleted.*/
     
    10901090        assert(cur == &sentinel || hash <= node_hash(h, cur)
    10911091                || node_hash(h, cur) == h->invalid_hash);
    1092        
     1092
    10931093        /* hash < node_hash(h, cur) */
    10941094        if (hash != node_hash(h, cur) && h->invalid_hash != node_hash(h, cur))
     
    11011101         */
    11021102        read_barrier();
    1103        
     1103
    11041104        *dup_item = find_duplicate(h, item, hash, cur);
    11051105        return NULL != *dup_item;
     
    11131113
    11141114        cht_link_t *cur = start;
    1115        
     1115
    11161116try_again:
    11171117        assert(cur);
     
    11191119        while (node_hash(h, cur) == hash) {
    11201120                assert(cur != &sentinel);
    1121                
     1121
    11221122                bool deleted = (N_DELETED & get_mark(cur->link));
    1123                
     1123
    11241124                /* Skip logically deleted nodes. */
    11251125                if (!deleted && h->op->equal(item, cur))
    11261126                        return cur;
    1127                
     1127
    11281128                cur = get_next(cur->link);
    11291129                assert(cur);
     
    11351135                goto try_again;
    11361136        }
    1137        
     1137
    11381138        return NULL;
    11391139}
     
    11431143{
    11441144        assert(h);
    1145        
     1145
    11461146        size_t hash = calc_key_hash(h, key);
    11471147        size_t removed = 0;
    1148        
     1148
    11491149        while (remove_pred(h, hash, h->op->key_equal, key))
    11501150                ++removed;
    1151        
     1151
    11521152        return removed;
    11531153}
     
    11811181{
    11821182        rcu_read_lock();
    1183        
     1183
    11841184        bool resizing = false;
    11851185        bool deleted = false;
    11861186        bool deleted_but_gc = false;
    1187        
     1187
    11881188        cht_buckets_t *b = rcu_access(h->b);
    11891189        size_t idx = calc_bucket_idx(hash, b->order);
    11901190        marked_ptr_t *phead = &b->head[idx];
    1191        
     1191
    11921192        do {
    11931193                walk_mode_t walk_mode = WM_NORMAL;
    11941194                bool join_finishing = false;
    1195                
     1195
    11961196                resizing = resizing || (N_NORMAL != get_mark(*phead));
    1197                
     1197
    11981198                /* The table is resizing. Get the correct bucket head. */
    11991199                if (resizing) {
    12001200                        upd_resizing_head(h, hash, &phead, &join_finishing, &walk_mode);
    12011201                }
    1202                
     1202
    12031203                wnd_t wnd = {
    12041204                        .ppred = phead,
     
    12061206                        .last = NULL
    12071207                };
    1208                
     1208
    12091209                if (!find_wnd_and_gc_pred(
    12101210                        h, hash, walk_mode, pred, pred_arg, &wnd, &resizing)) {
     
    12121212                        continue;
    12131213                }
    1214                
     1214
    12151215                /*
    12161216                 * The item lookup is affected by a bucket join but effects of
     
    12251225                        continue;
    12261226                }
    1227                
     1227
    12281228                /* Already deleted, but delete_at() requested one GC pass. */
    12291229                if (deleted_but_gc)
    12301230                        break;
    1231                
     1231
    12321232                bool found = (wnd.cur != &sentinel && pred(pred_arg, wnd.cur));
    1233                
     1233
    12341234                if (!found) {
    12351235                        rcu_read_unlock();
    12361236                        return false;
    12371237                }
    1238                
     1238
    12391239                deleted = delete_at(h, &wnd, walk_mode, &deleted_but_gc, &resizing);
    12401240        } while (!deleted || deleted_but_gc);
    1241        
     1241
    12421242        rcu_read_unlock();
    12431243        return true;
     
    12631263{
    12641264        assert(wnd->cur && wnd->cur != &sentinel);
    1265        
     1265
    12661266        *deleted_but_gc = false;
    1267        
     1267
    12681268        if (!mark_deleted(wnd->cur, walk_mode, resizing)) {
    12691269                /* Already deleted, or unexpectedly marked as JOIN/JOIN_FOLLOWS. */
    12701270                return false;
    12711271        }
    1272        
     1272
    12731273        /* Marked deleted. Unlink from the bucket. */
    1274        
     1274
    12751275        /* Never unlink join nodes. */
    12761276        if (walk_mode == WM_LEAVE_JOIN && (N_JOIN & get_mark(wnd->cur->link)))
    12771277                return true;
    1278        
     1278
    12791279        cas_order_barrier();
    1280        
     1280
    12811281        if (unlink_from_pred(wnd, walk_mode, resizing)) {
    12821282                free_later(h, wnd->cur);
     
    12841284                *deleted_but_gc = true;
    12851285        }
    1286        
     1286
    12871287        return true;
    12881288}
     
    12931293{
    12941294        assert(cur && cur != &sentinel);
    1295        
     1295
    12961296        /*
    12971297         * Btw, we could loop here if the cas fails but let's not complicate
    12981298         * things and let's retry from the head of the bucket.
    12991299         */
    1300        
     1300
    13011301        cht_link_t *next = get_next(cur->link);
    1302        
     1302
    13031303        if (walk_mode == WM_NORMAL) {
    13041304                /* Only mark clean/normal nodes - JF/JN is used only during resize. */
    13051305                marked_ptr_t ret = cas_link(&cur->link, next, N_NORMAL, next, N_DELETED);
    1306                
     1306
    13071307                if (ret != make_link(next, N_NORMAL)) {
    13081308                        *resizing = (N_JOIN | N_JOIN_FOLLOWS) & get_mark(ret);
     
    13111311        } else {
    13121312                static_assert(N_JOIN == N_JOIN_FOLLOWS, "");
    1313                
     1313
    13141314                /* Keep the N_JOIN/N_JOIN_FOLLOWS mark but strip N_DELETED. */
    13151315                mark_t cur_mark = get_mark(cur->link) & N_JOIN_FOLLOWS;
    1316                
     1316
    13171317                marked_ptr_t ret =
    13181318                        cas_link(&cur->link, next, cur_mark, next, cur_mark | N_DELETED);
    1319                
     1319
    13201320                if (ret != make_link(next, cur_mark))
    13211321                        return false;
    13221322        }
    1323        
     1323
    13241324        return true;
    13251325}
     
    13311331        assert(wnd->cur != &sentinel);
    13321332        assert(wnd->cur && (N_DELETED & get_mark(wnd->cur->link)));
    1333        
     1333
    13341334        cht_link_t *next = get_next(wnd->cur->link);
    1335                
     1335
    13361336        if (walk_mode == WM_LEAVE_JOIN) {
    13371337                /* Never try to unlink join nodes. */
     
    13411341                /* Succeed only if the predecessor is clean/normal or a join node. */
    13421342                mark_t exp_pred_mark = (N_JOIN & pred_mark) ? pred_mark : N_NORMAL;
    1343                
     1343
    13441344                marked_ptr_t pred_link = make_link(wnd->cur, exp_pred_mark);
    13451345                marked_ptr_t next_link = make_link(next, exp_pred_mark);
    1346                
     1346
    13471347                if (pred_link != _cas_link(wnd->ppred, pred_link, next_link))
    13481348                        return false;
     
    13511351                /* Move the JF mark if set. Clear DEL mark. */
    13521352                mark_t cur_mark = N_JOIN_FOLLOWS & get_mark(wnd->cur->link);
    1353                
     1353
    13541354                /* The predecessor must be clean/normal. */
    13551355                marked_ptr_t pred_link = make_link(wnd->cur, N_NORMAL);
    13561356                /* Link to cur's successor keeping/copying cur's JF mark. */
    13571357                marked_ptr_t next_link = make_link(next, cur_mark);
    1358                
     1358
    13591359                marked_ptr_t ret = _cas_link(wnd->ppred, pred_link, next_link);
    1360                
     1360
    13611361                if (pred_link != ret) {
    13621362                        /* If we're not resizing the table there are no JF/JN nodes. */
     
    13661366                }
    13671367        }
    1368        
     1368
    13691369        return true;
    13701370}
     
    13991399{
    14001400        assert(wnd->cur);
    1401        
     1401
    14021402        if (wnd->cur == &sentinel)
    14031403                return true;
    1404        
     1404
    14051405        /*
    14061406         * A read barrier is not needed here to bring up the most recent
     
    14081408         * an already deleted node; fail in delete_at(); and retry.
    14091409         */
    1410        
     1410
    14111411        size_t cur_hash;
    14121412
    14131413try_again:
    14141414        cur_hash = node_hash(h, wnd->cur);
    1415                
     1415
    14161416        while (cur_hash <= hash) {
    14171417                assert(wnd->cur && wnd->cur != &sentinel);
    1418                
     1418
    14191419                /* GC any deleted nodes on the way. */
    14201420                if (N_DELETED & get_mark(wnd->cur->link)) {
     
    14271427                        if (cur_hash == hash && pred(pred_arg, wnd->cur))
    14281428                                return true;
    1429                        
     1429
    14301430                        next_wnd(wnd);
    14311431                }
    1432                
     1432
    14331433                cur_hash = node_hash(h, wnd->cur);
    14341434        }
    1435        
     1435
    14361436        if (cur_hash == h->invalid_hash) {
    14371437                next_wnd(wnd);
     
    14391439                goto try_again;
    14401440        }
    1441        
     1441
    14421442        /* The searched for node is not in the current bucket. */
    14431443        return true;
     
    14811481                        next_wnd(wnd);
    14821482                }
    1483                
     1483
    14841484                assert(wnd->cur);
    14851485        }
    1486        
     1486
    14871487        if (node_hash(h, wnd->cur) == h->invalid_hash) {
    14881488                next_wnd(wnd);
     
    15201520                wnd->cur = get_next(wnd->cur->link);
    15211521        }
    1522        
     1522
    15231523        return true;
    15241524}
     
    15391539         * is visible and if not, make it visible to this cpu.
    15401540         */
    1541        
     1541
    15421542        /*
    15431543         * Resizer ensures h->b->order stays the same for the duration of this
     
    15481548        assert(h->b->order > h->new_b->order);
    15491549        assert(wnd->cur);
    1550        
     1550
    15511551        /* Either we did not need the joining link or we have already followed it.*/
    15521552        if (wnd->cur != &sentinel)
    15531553                return true;
    1554        
     1554
    15551555        /* We have reached the end of a bucket. */
    1556        
     1556
    15571557        if (wnd->last != &sentinel) {
    15581558                size_t last_seen_hash = node_hash(h, wnd->last);
    1559                
     1559
    15601560                if (last_seen_hash == h->invalid_hash) {
    15611561                        last_seen_hash = calc_node_hash(h, wnd->last);
    15621562                }
    1563                
     1563
    15641564                size_t last_old_idx = calc_bucket_idx(last_seen_hash, h->b->order);
    15651565                size_t move_src_idx = grow_idx(shrink_idx(last_old_idx));
    1566                
     1566
    15671567                /*
    15681568                 * Last node seen was in the joining bucket - if the searched
     
    15721572                        return true;
    15731573        }
    1574        
     1574
    15751575        /*
    15761576         * Reached the end of the bucket but no nodes from the joining bucket
     
    16031603        size_t old_idx = calc_bucket_idx(hash, b->order);
    16041604        size_t new_idx = calc_bucket_idx(hash, h->new_b->order);
    1605        
     1605
    16061606        marked_ptr_t *pold_head = &b->head[old_idx];
    16071607        marked_ptr_t *pnew_head = &h->new_b->head[new_idx];
    1608        
     1608
    16091609        /* In any case, use the bucket in the new table. */
    16101610        *phead = pnew_head;
     
    16141614                size_t move_dest_idx = grow_idx(old_idx);
    16151615                marked_ptr_t *pmoved_head = &h->new_b->head[move_dest_idx];
    1616                
     1616
    16171617                /* Complete moving the bucket from the old to the new table. */
    16181618                help_head_move(pold_head, pmoved_head);
    1619                
     1619
    16201620                /* The hash belongs to the moved bucket. */
    16211621                if (move_dest_idx == new_idx) {
     
    16341634                         * half of the split/old/moved bucket.
    16351635                         */
    1636                        
     1636
    16371637                        /* The moved bucket has not yet been split. */
    16381638                        if (N_NORMAL != get_mark(*pnew_head)) {
     
    16451645                                assert(N_NORMAL == get_mark(*pnew_head));
    16461646                        }
    1647                        
     1647
    16481648                        *walk_mode = WM_LEAVE_JOIN;
    16491649                }
    16501650        } else if (h->new_b->order < b->order ) {
    16511651                /* Shrinking the table. */
    1652                
     1652
    16531653                size_t move_src_idx = grow_idx(new_idx);
    1654                
     1654
    16551655                /*
    16561656                 * Complete moving the bucket from the old to the new table.
     
    16581658                 */
    16591659                help_head_move(&b->head[move_src_idx], pnew_head);
    1660                
     1660
    16611661                /* Hash belongs to the bucket to be joined with the moved bucket. */
    16621662                if (move_src_idx != old_idx) {
     
    16661666                                join_buckets(h, pold_head, pnew_head, split_hash);
    16671667                        }
    1668                        
     1668
    16691669                        /*
    16701670                         * The resizer sets pold_head to &sentinel when all cpus are
     
    16731673                        *join_finishing = (&sentinel != get_next(*pold_head));
    16741674                }
    1675                
     1675
    16761676                /* move_head() or join_buckets() makes it so or makes the mark visible.*/
    16771677                assert(N_INVALID == get_mark(*pold_head));
     
    17131713        /* Head move has to in progress already when calling this func. */
    17141714        assert(N_CONST & get_mark(*psrc_head));
    1715        
     1715
    17161716        /* Head already moved. */
    17171717        if (N_INVALID == get_mark(*psrc_head)) {
     
    17241724                complete_head_move(psrc_head, pdest_head);
    17251725        }
    1726        
     1726
    17271727        assert(!(N_CONST & get_mark(*pdest_head)));
    17281728}
     
    17421742{
    17431743        marked_ptr_t ret, src_link;
    1744        
     1744
    17451745        /* Mark src head immutable. */
    17461746        do {
    17471747                cht_link_t *next = get_next(*psrc_head);
    17481748                src_link = make_link(next, N_NORMAL);
    1749                
     1749
    17501750                /* Mark the normal/clean src link immutable/const. */
    17511751                ret = cas_link(psrc_head, next, N_NORMAL, next, N_CONST);
     
    17581758        assert(N_JOIN_FOLLOWS != get_mark(*psrc_head));
    17591759        assert(N_CONST & get_mark(*psrc_head));
    1760        
     1760
    17611761        cht_link_t *next = get_next(*psrc_head);
    17621762
     
    17651765        assert(ret == make_link(&sentinel, N_INVALID) || (N_NORMAL == get_mark(ret)));
    17661766        cas_order_barrier();
    1767        
     1767
    17681768        DBG(ret = )
    17691769                cas_link(psrc_head, next, N_CONST, next, N_INVALID);
     
    17911791        if (N_NORMAL == get_mark(*pdest_head))
    17921792                return;
    1793        
     1793
    17941794        /*
    17951795         * L == Last node of the first part of the split bucket. That part
     
    18361836         */
    18371837        wnd_t wnd;
    1838        
     1838
    18391839        rcu_read_lock();
    1840        
     1840
    18411841        /* Mark the last node of the first part of the split bucket as JF. */
    18421842        mark_join_follows(h, psrc_head, split_hash, &wnd);
    18431843        cas_order_barrier();
    1844        
     1844
    18451845        /* There are nodes in the dest bucket, ie the second part of the split. */
    18461846        if (wnd.cur != &sentinel) {
     
    18571857                 */
    18581858        }
    1859        
     1859
    18601860        /* Link the dest head to the second part of the split. */
    18611861        DBG(marked_ptr_t ret = )
     
    18631863        assert(ret == make_link(&sentinel, N_INVALID) || (N_NORMAL == get_mark(ret)));
    18641864        cas_order_barrier();
    1865        
     1865
    18661866        rcu_read_unlock();
    18671867}
     
    18881888{
    18891889        /* See comment in split_bucket(). */
    1890        
     1890
    18911891        bool done = false;
    18921892
     
    18951895                wnd->ppred = psrc_head;
    18961896                wnd->cur = get_next(*psrc_head);
    1897                
     1897
    18981898                /*
    18991899                 * Find the split window, ie the last node of the first part of
     
    19031903                if (!find_wnd_and_gc(h, split_hash, WM_MOVE_JOIN_FOLLOWS, wnd, &resizing))
    19041904                        continue;
    1905                
     1905
    19061906                /* Must not report that the table is resizing if WM_MOVE_JOIN_FOLLOWS.*/
    19071907                assert(!resizing);
     
    19261926{
    19271927        /* See comment in split_bucket(). */
    1928        
     1928
    19291929        bool done;
    19301930        do {
    19311931                cht_link_t *next = get_next(join_node->link);
    19321932                mark_t mark = get_mark(join_node->link);
    1933                
     1933
    19341934                /*
    19351935                 * May already be marked as deleted, but it won't be unlinked
     
    19381938                marked_ptr_t ret
    19391939                        = cas_link(&join_node->link, next, mark, next, mark | N_JOIN);
    1940                
     1940
    19411941                /* Successfully marked or already marked as a join node. */
    19421942                done = (ret == make_link(next, mark))
     
    20232023         *  [src_head | Inv]-----------> [JN] -> ..
    20242024         */
    2025        
     2025
    20262026        rcu_read_lock();
    2027        
     2027
    20282028        /* Mark src_head immutable - signals updaters that bucket join started. */
    20292029        mark_const(psrc_head);
    20302030        cas_order_barrier();
    2031        
     2031
    20322032        cht_link_t *join_node = get_next(*psrc_head);
    20332033
     
    20352035                mark_join_node(join_node);
    20362036                cas_order_barrier();
    2037                
     2037
    20382038                link_to_join_node(h, pdest_head, join_node, split_hash);
    20392039                cas_order_barrier();
    20402040        }
    2041        
     2041
    20422042        DBG(marked_ptr_t ret = )
    20432043                cas_link(psrc_head, join_node, N_CONST, join_node, N_INVALID);
    20442044        assert(ret == make_link(join_node, N_CONST) || (N_INVALID == get_mark(ret)));
    20452045        cas_order_barrier();
    2046        
     2046
    20472047        rcu_read_unlock();
    20482048}
     
    20672067                        .cur = get_next(*pdest_head)
    20682068                };
    2069                
     2069
    20702070                bool resizing = false;
    2071                
     2071
    20722072                if (!find_wnd_and_gc(h, split_hash, WM_LEAVE_JOIN, &wnd, &resizing))
    20732073                        continue;
    20742074
    20752075                assert(!resizing);
    2076                
     2076
    20772077                if (wnd.cur != &sentinel) {
    20782078                        /* Must be from the new appended bucket. */
     
    20812081                        return;
    20822082                }
    2083                
     2083
    20842084                /* Reached the tail of pdest_head - link it to the join node. */
    20852085                marked_ptr_t ret =
    20862086                        cas_link(wnd.ppred, &sentinel, N_NORMAL, join_node, N_NORMAL);
    2087                
     2087
    20882088                done = (ret == make_link(&sentinel, N_NORMAL));
    20892089        } while (!done);
     
    20972097{
    20982098        assert(item != &sentinel);
    2099        
     2099
    21002100        /*
    21012101         * remove_callback only works as rcu_func_t because rcu_link is the first
     
    21032103         */
    21042104        rcu_call(&item->rcu_link, (rcu_func_t)h->op->remove_callback);
    2105        
     2105
    21062106        item_removed(h);
    21072107}
     
    21162116        size_t items = (size_t) atomic_predec(&h->item_cnt);
    21172117        size_t bucket_cnt = (1 << h->b->order);
    2118        
     2118
    21192119        bool need_shrink = (items == h->max_load * bucket_cnt / 4);
    21202120        bool missed_shrink = (items == h->max_load * bucket_cnt / 8);
    2121        
     2121
    21222122        if ((need_shrink || missed_shrink) && h->b->order > h->min_order) {
    21232123                atomic_count_t resize_reqs = atomic_preinc(&h->resize_reqs);
     
    21372137        size_t items = (size_t) atomic_preinc(&h->item_cnt);
    21382138        size_t bucket_cnt = (1 << h->b->order);
    2139        
     2139
    21402140        bool need_grow = (items == h->max_load * bucket_cnt);
    21412141        bool missed_grow = (items == 2 * h->max_load * bucket_cnt);
    2142        
     2142
    21432143        if ((need_grow || missed_grow) && h->b->order < CHT_MAX_ORDER) {
    21442144                atomic_count_t resize_reqs = atomic_preinc(&h->resize_reqs);
     
    21542154{
    21552155        cht_t *h = member_to_inst(arg, cht_t, resize_work);
    2156        
     2156
    21572157#ifdef CONFIG_DEBUG
    21582158        assert(h->b);
     
    21882188        if (h->b->order >= CHT_MAX_ORDER)
    21892189                return;
    2190        
     2190
    21912191        h->new_b = alloc_buckets(h->b->order + 1, true, false);
    21922192
     
    21982198        rcu_synchronize();
    21992199        size_t old_bucket_cnt = (1 << h->b->order);
    2200        
     2200
    22012201        /*
    22022202         * Give updaters a chance to help out with the resize. Do the minimum
     
    22062206                start_head_move(&h->b->head[idx]);
    22072207        }
    2208        
     2208
    22092209        /* Order start_head_move() wrt complete_head_move(). */
    22102210        cas_order_barrier();
    2211        
     2211
    22122212        /* Complete moving heads and split any buckets not yet split by updaters. */
    22132213        for (size_t old_idx = 0; old_idx < old_bucket_cnt; ++old_idx) {
     
    22262226                split_bucket(h, move_dest_head, split_dest_head, split_hash);
    22272227        }
    2228        
     2228
    22292229        /*
    22302230         * Wait for all updaters to notice the new heads. Once everyone sees
     
    22332233         */
    22342234        rcu_synchronize();
    2235        
     2235
    22362236        /* Clear the JOIN_FOLLOWS mark and remove the link between the split buckets.*/
    22372237        for (size_t old_idx = 0; old_idx < old_bucket_cnt; ++old_idx) {
    22382238                size_t new_idx = grow_idx(old_idx);
    2239                
     2239
    22402240                cleanup_join_follows(h, &h->new_b->head[new_idx]);
    22412241        }
     
    22462246         */
    22472247        rcu_synchronize();
    2248        
     2248
    22492249        /* Clear the JOIN mark and GC any deleted join nodes. */
    22502250        for (size_t old_idx = 0; old_idx < old_bucket_cnt; ++old_idx) {
    22512251                size_t new_idx = grow_to_split_idx(old_idx);
    2252                
     2252
    22532253                cleanup_join_node(h, &h->new_b->head[new_idx]);
    22542254        }
     
    22562256        /* Wait for everyone to see that the table is clear of any resize marks. */
    22572257        rcu_synchronize();
    2258        
     2258
    22592259        cht_buckets_t *old_b = h->b;
    22602260        rcu_assign(h->b, h->new_b);
     
    22622262        /* Wait for everyone to start using the new table. */
    22632263        rcu_synchronize();
    2264        
     2264
    22652265        free(old_b);
    2266        
     2266
    22672267        /* Not needed; just for increased readability. */
    22682268        h->new_b = NULL;
     
    22742274        if (h->b->order <= h->min_order)
    22752275                return;
    2276        
     2276
    22772277        h->new_b = alloc_buckets(h->b->order - 1, true, false);
    22782278
     
    22832283        /* Wait for all readers and updaters to see the initialized new table. */
    22842284        rcu_synchronize();
    2285        
     2285
    22862286        size_t old_bucket_cnt = (1 << h->b->order);
    2287        
     2287
    22882288        /*
    22892289         * Give updaters a chance to help out with the resize. Do the minimum
     
    22922292        for (size_t old_idx = 0; old_idx < old_bucket_cnt; ++old_idx) {
    22932293                size_t new_idx = shrink_idx(old_idx);
    2294                
     2294
    22952295                /* This bucket should be moved. */
    22962296                if (grow_idx(new_idx) == old_idx) {
     
    23002300                }
    23012301        }
    2302        
     2302
    23032303        /* Order start_head_move() wrt to complete_head_move(). */
    23042304        cas_order_barrier();
    2305        
     2305
    23062306        /* Complete moving heads and join buckets with the moved buckets. */
    23072307        for (size_t old_idx = 0; old_idx < old_bucket_cnt; ++old_idx) {
    23082308                size_t new_idx = shrink_idx(old_idx);
    23092309                size_t move_src_idx = grow_idx(new_idx);
    2310                
     2310
    23112311                /* This bucket should be moved. */
    23122312                if (move_src_idx == old_idx) {
     
    23222322                }
    23232323        }
    2324        
     2324
    23252325        /*
    23262326         * Wait for all updaters to notice the new heads. Once everyone sees
     
    23292329         */
    23302330        rcu_synchronize();
    2331        
     2331
    23322332        /* Let everyone know joins are complete and fully visible. */
    23332333        for (size_t old_idx = 0; old_idx < old_bucket_cnt; ++old_idx) {
    23342334                size_t move_src_idx = grow_idx(shrink_idx(old_idx));
    2335        
     2335
    23362336                /* Set the invalid joinee head to NULL. */
    23372337                if (old_idx != move_src_idx) {
    23382338                        assert(N_INVALID == get_mark(h->b->head[old_idx]));
    2339                        
     2339
    23402340                        if (&sentinel != get_next(h->b->head[old_idx]))
    23412341                                h->b->head[old_idx] = make_link(&sentinel, N_INVALID);
    23422342                }
    23432343        }
    2344        
     2344
    23452345        /* todo comment join node vs reset joinee head*/
    23462346        rcu_synchronize();
    23472347
    23482348        size_t new_bucket_cnt = (1 << h->new_b->order);
    2349                
     2349
    23502350        /* Clear the JOIN mark and GC any deleted join nodes. */
    23512351        for (size_t new_idx = 0; new_idx < new_bucket_cnt; ++new_idx) {
     
    23552355        /* Wait for everyone to see that the table is clear of any resize marks. */
    23562356        rcu_synchronize();
    2357        
     2357
    23582358        cht_buckets_t *old_b = h->b;
    23592359        rcu_assign(h->b, h->new_b);
    2360        
     2360
    23612361        /* Wait for everyone to start using the new table. */
    23622362        rcu_synchronize();
    2363        
     2363
    23642364        free(old_b);
    2365        
     2365
    23662366        /* Not needed; just for increased readability. */
    23672367        h->new_b = NULL;
     
    23742374
    23752375        cht_link_t *cur = get_next(*new_head);
    2376                
     2376
    23772377        while (cur != &sentinel) {
    23782378                /* Clear the join node's JN mark - even if it is marked as deleted. */
     
    23812381                        break;
    23822382                }
    2383                
     2383
    23842384                cur = get_next(cur->link);
    23852385        }
    2386        
     2386
    23872387        rcu_read_unlock();
    23882388}
     
    23942394        assert(join_node != &sentinel);
    23952395        assert(join_node && (N_JOIN & get_mark(join_node->link)));
    2396        
     2396
    23972397        bool done;
    2398        
     2398
    23992399        /* Clear the JN mark. */
    24002400        do {
     
    24112411                assert(ret == jn_link || (get_mark(ret) & N_JOIN));
    24122412        } while (!done);
    2413        
     2413
    24142414        if (!(N_DELETED & get_mark(join_node->link)))
    24152415                return;
     
    24192419        /* Clear the JOIN mark before trying to unlink the deleted join node.*/
    24202420        cas_order_barrier();
    2421        
     2421
    24222422        size_t jn_hash = node_hash(h, join_node);
    24232423        do {
    24242424                bool resizing = false;
    2425                
     2425
    24262426                wnd_t wnd = {
    24272427                        .ppred = new_head,
    24282428                        .cur = get_next(*new_head)
    24292429                };
    2430                
     2430
    24312431                done = find_wnd_and_gc_pred(h, jn_hash, WM_NORMAL, same_node_pred,
    24322432                        join_node, &wnd, &resizing);
    2433                
     2433
    24342434                assert(!resizing);
    24352435        } while (!done);
     
    24402440{
    24412441        assert(new_head);
    2442        
     2442
    24432443        rcu_read_lock();
    24442444
     
    24482448        };
    24492449        marked_ptr_t *cur_link = new_head;
    2450                
     2450
    24512451        /*
    24522452         * Find the non-deleted node with a JF mark and clear the JF mark.
     
    24612461        while (true) {
    24622462                bool is_jf_node = N_JOIN_FOLLOWS & get_mark(*cur_link);
    2463                
     2463
    24642464                /* GC any deleted nodes on the way - even deleted JOIN_FOLLOWS. */
    24652465                if (N_DELETED & get_mark(*cur_link)) {
     
    24832483                                marked_ptr_t ret =
    24842484                                        cas_link(cur_link, next, N_JOIN_FOLLOWS, &sentinel, N_NORMAL);
    2485                                
     2485
    24862486                                assert(next == &sentinel
    24872487                                        || ((N_JOIN | N_JOIN_FOLLOWS) & get_mark(ret)));
     
    25082508                cur_link = &wnd.cur->link;
    25092509        }
    2510        
     2510
    25112511        rcu_read_unlock();
    25122512}
     
    25612561                || item->hash == sentinel.hash
    25622562                || item->hash == calc_node_hash(h, item));
    2563        
     2563
    25642564        return item->hash;
    25652565}
     
    25862586{
    25872587        marked_ptr_t ptr = (marked_ptr_t) next;
    2588        
     2588
    25892589        assert(!(ptr & N_MARK_MASK));
    25902590        assert(!((unsigned)mark & ~N_MARK_MASK));
    2591        
     2591
    25922592        return ptr | mark;
    25932593}
     
    26902690         */
    26912691        void *expected = (void*)cur;
    2692        
     2692
    26932693        /*
    26942694         * Use the acquire-release model, although we could probably
     
    26982698        __atomic_compare_exchange_n((void**)link, &expected, (void *)new, false,
    26992699                __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
    2700        
     2700
    27012701        return (marked_ptr_t) expected;
    27022702}
Note: See TracChangeset for help on using the changeset viewer.