Annotation of OSKit-Mach/ipc/ipc_splay.c, revision 1.1

1.1     ! root        1: /* 
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
        !             4:  * All Rights Reserved.
        !             5:  * 
        !             6:  * Permission to use, copy, modify and distribute this software and its
        !             7:  * documentation is hereby granted, provided that both the copyright
        !             8:  * notice and this permission notice appear in all copies of the
        !             9:  * software, derivative works or modified versions, and any portions
        !            10:  * thereof, and that both notices appear in supporting documentation.
        !            11:  * 
        !            12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            15:  * 
        !            16:  * Carnegie Mellon requests users of this software to return to
        !            17:  * 
        !            18:  *  Software Distribution Coordinator  or  [email protected]
        !            19:  *  School of Computer Science
        !            20:  *  Carnegie Mellon University
        !            21:  *  Pittsburgh PA 15213-3890
        !            22:  * 
        !            23:  * any improvements or extensions that they make and grant Carnegie Mellon
        !            24:  * the rights to redistribute these changes.
        !            25:  */
        !            26: /*
        !            27:  */
        !            28: /*
        !            29:  *     File:   ipc/ipc_splay.c
        !            30:  *     Author: Rich Draves
        !            31:  *     Date:   1989
        !            32:  *
        !            33:  *     Primitive splay tree operations.
        !            34:  */
        !            35: 
        !            36: #include <mach/port.h>
        !            37: #include <kern/assert.h>
        !            38: #include <kern/macro_help.h>
        !            39: #include <ipc/ipc_entry.h>
        !            40: #include <ipc/ipc_splay.h>
        !            41: 
        !            42: /*
        !            43:  *     Splay trees are self-adjusting binary search trees.
        !            44:  *     They have the following attractive properties:
        !            45:  *             1) Space efficient; only two pointers per entry.
        !            46:  *             2) Robust performance; amortized O(log n) per operation.
        !            47:  *             3) Recursion not needed.
        !            48:  *     This makes them a good fall-back data structure for those
        !            49:  *     entries that don't fit into the lookup table.
        !            50:  *
        !            51:  *     The paper by Sleator and Tarjan, JACM v. 32, no. 3, pp. 652-686,
        !            52:  *     describes the splaying operation.  ipc_splay_prim_lookup
        !            53:  *     and ipc_splay_prim_assemble implement the top-down splay
        !            54:  *     described on p. 669.
        !            55:  *
        !            56:  *     The tree is stored in an unassembled form.  If ist_root is null,
        !            57:  *     then the tree has no entries.  Otherwise, ist_name records
        !            58:  *     the value used for the last lookup.  ist_root points to the
        !            59:  *     middle tree obtained from the top-down splay.  ist_ltree and
        !            60:  *     ist_rtree point to left and right subtrees, whose entries
        !            61:  *     are all smaller (larger) than those in the middle tree.
        !            62:  *     ist_ltreep and ist_rtreep are pointers to fields in the
        !            63:  *     left and right subtrees.  ist_ltreep points to the rchild field
        !            64:  *     of the largest entry in ltree, and ist_rtreep points to the
        !            65:  *     lchild field of the smallest entry in rtree.  The pointed-to
        !            66:  *     fields aren't initialized.  If the left (right) subtree is null,
        !            67:  *     then ist_ltreep (ist_rtreep) points to the ist_ltree (ist_rtree)
        !            68:  *     field in the splay structure itself.
        !            69:  *
        !            70:  *     The primary advantage of the unassembled form is that repeated
        !            71:  *     unsuccessful lookups are efficient.  In particular, an unsuccessful
        !            72:  *     lookup followed by an insert only requires one splaying operation.
        !            73:  *
        !            74:  *     The traversal algorithm works via pointer inversion.
        !            75:  *     When descending down the tree, child pointers are reversed
        !            76:  *     to point back to the parent entry.  When ascending,
        !            77:  *     the pointers are restored to their original value.
        !            78:  *
        !            79:  *     The biggest potential problem with the splay tree implementation
        !            80:  *     is that the operations, even lookup, require an exclusive lock.
        !            81:  *     If IPC spaces are protected with exclusive locks, then
        !            82:  *     the splay tree doesn't require its own lock, and ist_lock/ist_unlock
        !            83:  *     needn't do anything.  If IPC spaces are protected with read/write
        !            84:  *     locks then ist_lock/ist_unlock should provide exclusive access.
        !            85:  *
        !            86:  *     If it becomes important to let lookups run in parallel,
        !            87:  *     or if the restructuring makes lookups too expensive, then
        !            88:  *     there is hope.  Use a read/write lock on the splay tree.
        !            89:  *     Keep track of the number of entries in the tree.  When doing
        !            90:  *     a lookup, first try a non-restructuring lookup with a read lock held,
        !            91:  *     with a bound (based on log of size of the tree) on the number of
        !            92:  *     entries to traverse.  If the lookup runs up against the bound,
        !            93:  *     then take a write lock and do a reorganizing lookup.
        !            94:  *     This way, if lookups only access roughly balanced parts
        !            95:  *     of the tree, then lookups run in parallel and do no restructuring.
        !            96:  *
        !            97:  *     The traversal algorithm currently requires an exclusive lock.
        !            98:  *     If that is a problem, the tree could be changed from an lchild/rchild
        !            99:  *     representation to a leftmost child/right sibling representation.
        !           100:  *     In conjunction with non-restructing lookups, this would let
        !           101:  *     lookups and traversals all run in parallel.  But this representation
        !           102:  *     is more complicated and would slow down the operations.
        !           103:  */
        !           104: 
        !           105: /*
        !           106:  *     Boundary values to hand to ipc_splay_prim_lookup:
        !           107:  */
        !           108: 
        !           109: #define        MACH_PORT_SMALLEST      ((mach_port_t) 0)
        !           110: #define MACH_PORT_LARGEST      ((mach_port_t) ~0)
        !           111: 
        !           112: /*
        !           113:  *     Routine:        ipc_splay_prim_lookup
        !           114:  *     Purpose:
        !           115:  *             Searches for the node labeled name in the splay tree.
        !           116:  *             Returns three nodes (treep, ltreep, rtreep) and
        !           117:  *             two pointers to nodes (ltreepp, rtreepp).
        !           118:  *
        !           119:  *             ipc_splay_prim_lookup splits the supplied tree into
        !           120:  *             three subtrees, left, middle, and right, returned
        !           121:  *             in ltreep, treep, and rtreep.
        !           122:  *
        !           123:  *             If name is present in the tree, then it is at
        !           124:  *             the root of the middle tree.  Otherwise, the root
        !           125:  *             of the middle tree is the last node traversed.
        !           126:  *
        !           127:  *             ipc_splay_prim_lookup returns a pointer into
        !           128:  *             the left subtree, to the rchild field of its
        !           129:  *             largest node, in ltreepp.  It returns a pointer
        !           130:  *             into the right subtree, to the lchild field of its
        !           131:  *             smallest node, in rtreepp.
        !           132:  */
        !           133: 
        !           134: static void
        !           135: ipc_splay_prim_lookup(
        !           136:        mach_port_t             name,
        !           137:        ipc_tree_entry_t        tree,
        !           138:        ipc_tree_entry_t        *treep,
        !           139:        ipc_tree_entry_t        *ltreep,
        !           140:        ipc_tree_entry_t        **ltreepp,
        !           141:        ipc_tree_entry_t        *rtreep,
        !           142:        ipc_tree_entry_t        **rtreepp)
        !           143: {
        !           144:        mach_port_t tname;                      /* temp name */
        !           145:        ipc_tree_entry_t lchild, rchild;        /* temp child pointers */
        !           146: 
        !           147:        assert(tree != ITE_NULL);
        !           148: 
        !           149: #define        link_left                                       \
        !           150: MACRO_BEGIN                                            \
        !           151:        *ltreep = tree;                                 \
        !           152:        ltreep = &tree->ite_rchild;                     \
        !           153:        tree = *ltreep;                                 \
        !           154: MACRO_END
        !           155: 
        !           156: #define        link_right                                      \
        !           157: MACRO_BEGIN                                            \
        !           158:        *rtreep = tree;                                 \
        !           159:        rtreep = &tree->ite_lchild;                     \
        !           160:        tree = *rtreep;                                 \
        !           161: MACRO_END
        !           162: 
        !           163: #define rotate_left                                    \
        !           164: MACRO_BEGIN                                            \
        !           165:        ipc_tree_entry_t temp = tree;                   \
        !           166:                                                        \
        !           167:        tree = temp->ite_rchild;                        \
        !           168:        temp->ite_rchild = tree->ite_lchild;            \
        !           169:        tree->ite_lchild = temp;                        \
        !           170: MACRO_END
        !           171: 
        !           172: #define rotate_right                                   \
        !           173: MACRO_BEGIN                                            \
        !           174:        ipc_tree_entry_t temp = tree;                   \
        !           175:                                                        \
        !           176:        tree = temp->ite_lchild;                        \
        !           177:        temp->ite_lchild = tree->ite_rchild;            \
        !           178:        tree->ite_rchild = temp;                        \
        !           179: MACRO_END
        !           180: 
        !           181:        while (name != (tname = tree->ite_name)) {
        !           182:                if (name < tname) {
        !           183:                        /* descend to left */
        !           184: 
        !           185:                        lchild = tree->ite_lchild;
        !           186:                        if (lchild == ITE_NULL)
        !           187:                                break;
        !           188:                        tname = lchild->ite_name;
        !           189: 
        !           190:                        if ((name < tname) &&
        !           191:                            (lchild->ite_lchild != ITE_NULL))
        !           192:                                rotate_right;
        !           193:                        link_right;
        !           194:                        if ((name > tname) &&
        !           195:                            (lchild->ite_rchild != ITE_NULL))
        !           196:                                link_left;
        !           197:                } else {
        !           198:                        /* descend to right */
        !           199: 
        !           200:                        rchild = tree->ite_rchild;
        !           201:                        if (rchild == ITE_NULL)
        !           202:                                break;
        !           203:                        tname = rchild->ite_name;
        !           204: 
        !           205:                        if ((name > tname) &&
        !           206:                            (rchild->ite_rchild != ITE_NULL))
        !           207:                                rotate_left;
        !           208:                        link_left;
        !           209:                        if ((name < tname) &&
        !           210:                            (rchild->ite_lchild != ITE_NULL))
        !           211:                                link_right;
        !           212:                }
        !           213: 
        !           214:                assert(tree != ITE_NULL);
        !           215:        }
        !           216: 
        !           217:        *treep = tree;
        !           218:        *ltreepp = ltreep;
        !           219:        *rtreepp = rtreep;
        !           220: 
        !           221: #undef link_left
        !           222: #undef link_right
        !           223: #undef rotate_left
        !           224: #undef rotate_right
        !           225: }
        !           226: 
        !           227: /*
        !           228:  *     Routine:        ipc_splay_prim_assemble
        !           229:  *     Purpose:
        !           230:  *             Assembles the results of ipc_splay_prim_lookup
        !           231:  *             into a splay tree with the found node at the root.
        !           232:  *
        !           233:  *             ltree and rtree are by-reference so storing
        !           234:  *             through ltreep and rtreep can change them.
        !           235:  */
        !           236: 
        !           237: static void
        !           238: ipc_splay_prim_assemble(
        !           239:        ipc_tree_entry_t        tree,
        !           240:        ipc_tree_entry_t        *ltree,
        !           241:        ipc_tree_entry_t        *ltreep,
        !           242:        ipc_tree_entry_t        *rtree,
        !           243:        ipc_tree_entry_t        *rtreep)
        !           244: {
        !           245:        assert(tree != ITE_NULL);
        !           246: 
        !           247:        *ltreep = tree->ite_lchild;
        !           248:        *rtreep = tree->ite_rchild;
        !           249: 
        !           250:        tree->ite_lchild = *ltree;
        !           251:        tree->ite_rchild = *rtree;
        !           252: }
        !           253: 
        !           254: /*
        !           255:  *     Routine:        ipc_splay_tree_init
        !           256:  *     Purpose:
        !           257:  *             Initialize a raw splay tree for use.
        !           258:  */
        !           259: 
        !           260: void
        !           261: ipc_splay_tree_init(
        !           262:        ipc_splay_tree_t        splay)
        !           263: {
        !           264:        splay->ist_root = ITE_NULL;
        !           265: }
        !           266: 
        !           267: /*
        !           268:  *     Routine:        ipc_splay_tree_pick
        !           269:  *     Purpose:
        !           270:  *             Picks and returns a random entry in a splay tree.
        !           271:  *             Returns FALSE if the splay tree is empty.
        !           272:  */
        !           273: 
        !           274: boolean_t
        !           275: ipc_splay_tree_pick(
        !           276:        ipc_splay_tree_t        splay,
        !           277:        mach_port_t             *namep,
        !           278:        ipc_tree_entry_t        *entryp)
        !           279: {
        !           280:        ipc_tree_entry_t root;
        !           281: 
        !           282:        ist_lock(splay);
        !           283: 
        !           284:        root = splay->ist_root;
        !           285:        if (root != ITE_NULL) {
        !           286:                *namep = root->ite_name;
        !           287:                *entryp = root;
        !           288:        }
        !           289: 
        !           290:        ist_unlock(splay);
        !           291: 
        !           292:        return root != ITE_NULL;
        !           293: }
        !           294: 
        !           295: /*
        !           296:  *     Routine:        ipc_splay_tree_lookup
        !           297:  *     Purpose:
        !           298:  *             Finds an entry in a splay tree.
        !           299:  *             Returns ITE_NULL if not found.
        !           300:  */
        !           301: 
        !           302: ipc_tree_entry_t
        !           303: ipc_splay_tree_lookup(
        !           304:        ipc_splay_tree_t        splay,
        !           305:        mach_port_t             name)
        !           306: {
        !           307:        ipc_tree_entry_t root;
        !           308: 
        !           309:        ist_lock(splay);
        !           310: 
        !           311:        root = splay->ist_root;
        !           312:        if (root != ITE_NULL) {
        !           313:                if (splay->ist_name != name) {
        !           314:                        ipc_splay_prim_assemble(root,
        !           315:                                &splay->ist_ltree, splay->ist_ltreep,
        !           316:                                &splay->ist_rtree, splay->ist_rtreep);
        !           317:                        ipc_splay_prim_lookup(name, root, &root,
        !           318:                                &splay->ist_ltree, &splay->ist_ltreep,
        !           319:                                &splay->ist_rtree, &splay->ist_rtreep);
        !           320:                        splay->ist_name = name;
        !           321:                        splay->ist_root = root;
        !           322:                }
        !           323: 
        !           324:                if (name != root->ite_name)
        !           325:                        root = ITE_NULL;
        !           326:        }
        !           327: 
        !           328:        ist_unlock(splay);
        !           329: 
        !           330:        return root;
        !           331: }
        !           332: 
        !           333: /*
        !           334:  *     Routine:        ipc_splay_tree_insert
        !           335:  *     Purpose:
        !           336:  *             Inserts a new entry into a splay tree.
        !           337:  *             The caller supplies a new entry.
        !           338:  *             The name can't already be present in the tree.
        !           339:  */
        !           340: 
        !           341: void
        !           342: ipc_splay_tree_insert(
        !           343:        ipc_splay_tree_t        splay,
        !           344:        mach_port_t             name,
        !           345:        ipc_tree_entry_t        entry)
        !           346: {
        !           347:        ipc_tree_entry_t root;
        !           348: 
        !           349:        assert(entry != ITE_NULL);
        !           350: 
        !           351:        ist_lock(splay);
        !           352: 
        !           353:        root = splay->ist_root;
        !           354:        if (root == ITE_NULL) {
        !           355:                entry->ite_lchild = ITE_NULL;
        !           356:                entry->ite_rchild = ITE_NULL;
        !           357:        } else {
        !           358:                if (splay->ist_name != name) {
        !           359:                        ipc_splay_prim_assemble(root,
        !           360:                                &splay->ist_ltree, splay->ist_ltreep,
        !           361:                                &splay->ist_rtree, splay->ist_rtreep);
        !           362:                        ipc_splay_prim_lookup(name, root, &root,
        !           363:                                &splay->ist_ltree, &splay->ist_ltreep,
        !           364:                                &splay->ist_rtree, &splay->ist_rtreep);
        !           365:                }
        !           366: 
        !           367:                assert(root->ite_name != name);
        !           368: 
        !           369:                if (name < root->ite_name) {
        !           370:                        assert(root->ite_lchild == ITE_NULL);
        !           371: 
        !           372:                        *splay->ist_ltreep = ITE_NULL;
        !           373:                        *splay->ist_rtreep = root;
        !           374:                } else {
        !           375:                        assert(root->ite_rchild == ITE_NULL);
        !           376: 
        !           377:                        *splay->ist_ltreep = root;
        !           378:                        *splay->ist_rtreep = ITE_NULL;
        !           379:                }
        !           380: 
        !           381:                entry->ite_lchild = splay->ist_ltree;
        !           382:                entry->ite_rchild = splay->ist_rtree;
        !           383:        }
        !           384: 
        !           385:        entry->ite_name = name;
        !           386:        splay->ist_root = entry;
        !           387:        splay->ist_name = name;
        !           388:        splay->ist_ltreep = &splay->ist_ltree;
        !           389:        splay->ist_rtreep = &splay->ist_rtree;
        !           390: 
        !           391:        ist_unlock(splay);
        !           392: }
        !           393: 
        !           394: /*
        !           395:  *     Routine:        ipc_splay_tree_delete
        !           396:  *     Purpose:
        !           397:  *             Deletes an entry from a splay tree.
        !           398:  *             The name must be present in the tree.
        !           399:  *             Frees the entry.
        !           400:  *
        !           401:  *             The "entry" argument isn't currently used.
        !           402:  *             Other implementations might want it, though.
        !           403:  */
        !           404: 
        !           405: void
        !           406: ipc_splay_tree_delete(
        !           407:        ipc_splay_tree_t        splay,
        !           408:        mach_port_t             name,
        !           409:        ipc_tree_entry_t        entry)
        !           410: {
        !           411:        ipc_tree_entry_t root, saved;
        !           412: 
        !           413:        ist_lock(splay);
        !           414: 
        !           415:        root = splay->ist_root;
        !           416:        assert(root != ITE_NULL);
        !           417: 
        !           418:        if (splay->ist_name != name) {
        !           419:                ipc_splay_prim_assemble(root,
        !           420:                        &splay->ist_ltree, splay->ist_ltreep,
        !           421:                        &splay->ist_rtree, splay->ist_rtreep);
        !           422:                ipc_splay_prim_lookup(name, root, &root,
        !           423:                        &splay->ist_ltree, &splay->ist_ltreep,
        !           424:                        &splay->ist_rtree, &splay->ist_rtreep);
        !           425:        }
        !           426: 
        !           427:        assert(root->ite_name == name);
        !           428:        assert(root == entry);
        !           429: 
        !           430:        *splay->ist_ltreep = root->ite_lchild;
        !           431:        *splay->ist_rtreep = root->ite_rchild;
        !           432:        ite_free(root);
        !           433: 
        !           434:        root = splay->ist_ltree;
        !           435:        saved = splay->ist_rtree;
        !           436: 
        !           437:        if (root == ITE_NULL)
        !           438:                root = saved;
        !           439:        else if (saved != ITE_NULL) {
        !           440:                /*
        !           441:                 *      Find the largest node in the left subtree, and splay it
        !           442:                 *      to the root.  Then add the saved right subtree.
        !           443:                 */
        !           444: 
        !           445:                ipc_splay_prim_lookup(MACH_PORT_LARGEST, root, &root,
        !           446:                        &splay->ist_ltree, &splay->ist_ltreep,
        !           447:                        &splay->ist_rtree, &splay->ist_rtreep);
        !           448:                ipc_splay_prim_assemble(root,
        !           449:                        &splay->ist_ltree, splay->ist_ltreep,
        !           450:                        &splay->ist_rtree, splay->ist_rtreep);
        !           451: 
        !           452:                assert(root->ite_rchild == ITE_NULL);
        !           453:                root->ite_rchild = saved;
        !           454:        }
        !           455: 
        !           456:        splay->ist_root = root;
        !           457:        if (root != ITE_NULL) {
        !           458:                splay->ist_name = root->ite_name;
        !           459:                splay->ist_ltreep = &splay->ist_ltree;
        !           460:                splay->ist_rtreep = &splay->ist_rtree;
        !           461:        }
        !           462: 
        !           463:        ist_unlock(splay);
        !           464: }
        !           465: 
        !           466: /*
        !           467:  *     Routine:        ipc_splay_tree_split
        !           468:  *     Purpose:
        !           469:  *             Split a splay tree.  Puts all entries smaller than "name"
        !           470:  *             into a new tree, "small".
        !           471:  *
        !           472:  *             Doesn't do locking on "small", because nobody else
        !           473:  *             should be fiddling with the uninitialized tree.
        !           474:  */
        !           475: 
        !           476: void
        !           477: ipc_splay_tree_split(
        !           478:        ipc_splay_tree_t        splay,
        !           479:        mach_port_t             name,
        !           480:        ipc_splay_tree_t        small)
        !           481: {
        !           482:        ipc_tree_entry_t root;
        !           483: 
        !           484:        ipc_splay_tree_init(small);
        !           485: 
        !           486:        ist_lock(splay);
        !           487: 
        !           488:        root = splay->ist_root;
        !           489:        if (root != ITE_NULL) {
        !           490:                /* lookup name, to get it (or last traversed) to the top */
        !           491: 
        !           492:                if (splay->ist_name != name) {
        !           493:                        ipc_splay_prim_assemble(root,
        !           494:                                &splay->ist_ltree, splay->ist_ltreep,
        !           495:                                &splay->ist_rtree, splay->ist_rtreep);
        !           496:                        ipc_splay_prim_lookup(name, root, &root,
        !           497:                                &splay->ist_ltree, &splay->ist_ltreep,
        !           498:                                &splay->ist_rtree, &splay->ist_rtreep);
        !           499:                }
        !           500: 
        !           501:                if (root->ite_name < name) {
        !           502:                        /* root goes into small */
        !           503: 
        !           504:                        *splay->ist_ltreep = root->ite_lchild;
        !           505:                        *splay->ist_rtreep = ITE_NULL;
        !           506:                        root->ite_lchild = splay->ist_ltree;
        !           507:                        assert(root->ite_rchild == ITE_NULL);
        !           508: 
        !           509:                        small->ist_root = root;
        !           510:                        small->ist_name = root->ite_name;
        !           511:                        small->ist_ltreep = &small->ist_ltree;
        !           512:                        small->ist_rtreep = &small->ist_rtree;
        !           513: 
        !           514:                        /* rtree goes into splay */
        !           515: 
        !           516:                        root = splay->ist_rtree;
        !           517:                        splay->ist_root = root;
        !           518:                        if (root != ITE_NULL) {
        !           519:                                splay->ist_name = root->ite_name;
        !           520:                                splay->ist_ltreep = &splay->ist_ltree;
        !           521:                                splay->ist_rtreep = &splay->ist_rtree;
        !           522:                        }
        !           523:                } else {
        !           524:                        /* root stays in splay */
        !           525: 
        !           526:                        *splay->ist_ltreep = root->ite_lchild;
        !           527:                        root->ite_lchild = ITE_NULL;
        !           528: 
        !           529:                        splay->ist_root = root;
        !           530:                        splay->ist_name = name;
        !           531:                        splay->ist_ltreep = &splay->ist_ltree;
        !           532: 
        !           533:                        /* ltree goes into small */
        !           534: 
        !           535:                        root = splay->ist_ltree;
        !           536:                        small->ist_root = root;
        !           537:                        if (root != ITE_NULL) {
        !           538:                                small->ist_name = root->ite_name;
        !           539:                                small->ist_ltreep = &small->ist_ltree;
        !           540:                                small->ist_rtreep = &small->ist_rtree;
        !           541:                        }
        !           542:                }               
        !           543:        }
        !           544: 
        !           545:        ist_unlock(splay);
        !           546: }
        !           547: 
        !           548: /*
        !           549:  *     Routine:        ipc_splay_tree_join
        !           550:  *     Purpose:
        !           551:  *             Joins two splay trees.  Merges the entries in "small",
        !           552:  *             which must all be smaller than the entries in "splay",
        !           553:  *             into "splay".
        !           554:  */
        !           555: 
        !           556: void
        !           557: ipc_splay_tree_join(
        !           558:        ipc_splay_tree_t        splay,
        !           559:        ipc_splay_tree_t        small)
        !           560: {
        !           561:        ipc_tree_entry_t sroot;
        !           562: 
        !           563:        /* pull entries out of small */
        !           564: 
        !           565:        ist_lock(small);
        !           566: 
        !           567:        sroot = small->ist_root;
        !           568:        if (sroot != ITE_NULL) {
        !           569:                ipc_splay_prim_assemble(sroot,
        !           570:                        &small->ist_ltree, small->ist_ltreep,
        !           571:                        &small->ist_rtree, small->ist_rtreep);
        !           572:                small->ist_root = ITE_NULL;
        !           573:        }
        !           574: 
        !           575:        ist_unlock(small);
        !           576: 
        !           577:        /* put entries, if any, into splay */
        !           578: 
        !           579:        if (sroot != ITE_NULL) {
        !           580:                ipc_tree_entry_t root;
        !           581: 
        !           582:                ist_lock(splay);
        !           583: 
        !           584:                root = splay->ist_root;
        !           585:                if (root == ITE_NULL) {
        !           586:                        root = sroot;
        !           587:                } else {
        !           588:                        /* get smallest entry in splay tree to top */
        !           589: 
        !           590:                        if (splay->ist_name != MACH_PORT_SMALLEST) {
        !           591:                                ipc_splay_prim_assemble(root,
        !           592:                                        &splay->ist_ltree, splay->ist_ltreep,
        !           593:                                        &splay->ist_rtree, splay->ist_rtreep);
        !           594:                                ipc_splay_prim_lookup(MACH_PORT_SMALLEST,
        !           595:                                        root, &root,
        !           596:                                        &splay->ist_ltree, &splay->ist_ltreep,
        !           597:                                        &splay->ist_rtree, &splay->ist_rtreep);
        !           598:                        }
        !           599: 
        !           600:                        ipc_splay_prim_assemble(root,
        !           601:                                &splay->ist_ltree, splay->ist_ltreep,
        !           602:                                &splay->ist_rtree, splay->ist_rtreep);
        !           603: 
        !           604:                        assert(root->ite_lchild == ITE_NULL);
        !           605:                        assert(sroot->ite_name < root->ite_name);
        !           606:                        root->ite_lchild = sroot;
        !           607:                }
        !           608: 
        !           609:                splay->ist_root = root;
        !           610:                splay->ist_name = root->ite_name;
        !           611:                splay->ist_ltreep = &splay->ist_ltree;
        !           612:                splay->ist_rtreep = &splay->ist_rtree;
        !           613: 
        !           614:                ist_unlock(splay);
        !           615:        }
        !           616: }
        !           617: 
        !           618: /*
        !           619:  *     Routine:        ipc_splay_tree_bounds
        !           620:  *     Purpose:
        !           621:  *             Given a name, returns the largest value present
        !           622:  *             in the tree that is smaller than or equal to the name,
        !           623:  *             or ~0 if no such value exists.  Similarly, returns
        !           624:  *             the smallest value present that is greater than or
        !           625:  *             equal to the name, or 0 if no such value exists.
        !           626:  *
        !           627:  *             Hence, if
        !           628:  *             lower = upper, then lower = name = upper
        !           629:  *                             and name is present in the tree
        !           630:  *             lower = ~0 and upper = 0,
        !           631:  *                             then the tree is empty
        !           632:  *             lower = ~0 and upper > 0, then name < upper
        !           633:  *                             and upper is smallest value in tree
        !           634:  *             lower < ~0 and upper = 0, then lower < name
        !           635:  *                             and lower is largest value in tree
        !           636:  *             lower < ~0 and upper > 0, then lower < name < upper
        !           637:  *                             and they are tight bounds on name
        !           638:  *
        !           639:  *             (Note MACH_PORT_SMALLEST = 0 and MACH_PORT_LARGEST = ~0.)
        !           640:  */
        !           641: 
        !           642: void
        !           643: ipc_splay_tree_bounds(
        !           644:        ipc_splay_tree_t        splay,
        !           645:        mach_port_t             name,
        !           646:        mach_port_t             *lowerp, 
        !           647:        mach_port_t             *upperp)
        !           648: {
        !           649:        ipc_tree_entry_t root;
        !           650: 
        !           651:        ist_lock(splay);
        !           652: 
        !           653:        root = splay->ist_root;
        !           654:        if (root == ITE_NULL) {
        !           655:                *lowerp = MACH_PORT_LARGEST;
        !           656:                *upperp = MACH_PORT_SMALLEST;
        !           657:        } else {
        !           658:                mach_port_t rname;
        !           659: 
        !           660:                if (splay->ist_name != name) {
        !           661:                        ipc_splay_prim_assemble(root,
        !           662:                                &splay->ist_ltree, splay->ist_ltreep,
        !           663:                                &splay->ist_rtree, splay->ist_rtreep);
        !           664:                        ipc_splay_prim_lookup(name, root, &root,
        !           665:                                &splay->ist_ltree, &splay->ist_ltreep,
        !           666:                                &splay->ist_rtree, &splay->ist_rtreep);
        !           667:                        splay->ist_name = name;
        !           668:                        splay->ist_root = root;
        !           669:                }
        !           670: 
        !           671:                rname = root->ite_name;
        !           672: 
        !           673:                /*
        !           674:                 *      OK, it's a hack.  We convert the ltreep and rtreep
        !           675:                 *      pointers back into real entry pointers,
        !           676:                 *      so we can pick the names out of the entries.
        !           677:                 */
        !           678: 
        !           679:                if (rname <= name)
        !           680:                        *lowerp = rname;
        !           681:                else if (splay->ist_ltreep == &splay->ist_ltree)
        !           682:                        *lowerp = MACH_PORT_LARGEST;
        !           683:                else {
        !           684:                        ipc_tree_entry_t entry;
        !           685: 
        !           686:                        entry = (ipc_tree_entry_t)
        !           687:                                ((char *)splay->ist_ltreep -
        !           688:                                 ((char *)&root->ite_rchild -
        !           689:                                  (char *)root));
        !           690:                        *lowerp = entry->ite_name;
        !           691:                }
        !           692: 
        !           693:                if (rname >= name)
        !           694:                        *upperp = rname;
        !           695:                else if (splay->ist_rtreep == &splay->ist_rtree)
        !           696:                        *upperp = MACH_PORT_SMALLEST;
        !           697:                else {
        !           698:                        ipc_tree_entry_t entry;
        !           699: 
        !           700:                        entry = (ipc_tree_entry_t)
        !           701:                                ((char *)splay->ist_rtreep -
        !           702:                                 ((char *)&root->ite_lchild -
        !           703:                                  (char *)root));
        !           704:                        *upperp = entry->ite_name;
        !           705:                }
        !           706:        }
        !           707: 
        !           708:        ist_unlock(splay);
        !           709: }
        !           710: 
        !           711: /*
        !           712:  *     Routine:        ipc_splay_traverse_start
        !           713:  *     Routine:        ipc_splay_traverse_next
        !           714:  *     Routine:        ipc_splay_traverse_finish
        !           715:  *     Purpose:
        !           716:  *             Perform a symmetric order traversal of a splay tree.
        !           717:  *     Usage:
        !           718:  *             for (entry = ipc_splay_traverse_start(splay);
        !           719:  *                  entry != ITE_NULL;
        !           720:  *                  entry = ipc_splay_traverse_next(splay, delete)) {
        !           721:  *                     do something with entry
        !           722:  *             }
        !           723:  *             ipc_splay_traverse_finish(splay);
        !           724:  *
        !           725:  *             If "delete" is TRUE, then the current entry
        !           726:  *             is removed from the tree and deallocated.
        !           727:  *
        !           728:  *             During the traversal, the splay tree is locked.
        !           729:  */
        !           730: 
        !           731: ipc_tree_entry_t
        !           732: ipc_splay_traverse_start(
        !           733:        ipc_splay_tree_t        splay)
        !           734: {
        !           735:        ipc_tree_entry_t current, parent;
        !           736: 
        !           737:        ist_lock(splay);
        !           738: 
        !           739:        current = splay->ist_root;
        !           740:        if (current != ITE_NULL) {
        !           741:                ipc_splay_prim_assemble(current,
        !           742:                        &splay->ist_ltree, splay->ist_ltreep,
        !           743:                        &splay->ist_rtree, splay->ist_rtreep);
        !           744: 
        !           745:                parent = ITE_NULL;
        !           746: 
        !           747:                while (current->ite_lchild != ITE_NULL) {
        !           748:                        ipc_tree_entry_t next;
        !           749: 
        !           750:                        next = current->ite_lchild;
        !           751:                        current->ite_lchild = parent;
        !           752:                        parent = current;
        !           753:                        current = next;
        !           754:                }
        !           755: 
        !           756:                splay->ist_ltree = current;
        !           757:                splay->ist_rtree = parent;
        !           758:        }
        !           759: 
        !           760:        return current;
        !           761: }
        !           762: 
        !           763: ipc_tree_entry_t
        !           764: ipc_splay_traverse_next(
        !           765:        ipc_splay_tree_t        splay,
        !           766:        boolean_t               delete)
        !           767: {
        !           768:        ipc_tree_entry_t current, parent;
        !           769: 
        !           770:        /* pick up where traverse_entry left off */
        !           771: 
        !           772:        current = splay->ist_ltree;
        !           773:        parent = splay->ist_rtree;
        !           774:        assert(current != ITE_NULL);
        !           775: 
        !           776:        if (!delete)
        !           777:                goto traverse_right;
        !           778: 
        !           779:        /* we must delete current and patch the tree */
        !           780: 
        !           781:        if (current->ite_lchild == ITE_NULL) {
        !           782:                if (current->ite_rchild == ITE_NULL) {
        !           783:                        /* like traverse_back, but with deletion */
        !           784: 
        !           785:                        if (parent == ITE_NULL) {
        !           786:                                ite_free(current);
        !           787: 
        !           788:                                splay->ist_root = ITE_NULL;
        !           789:                                return ITE_NULL;
        !           790:                        }
        !           791: 
        !           792:                        if (current->ite_name < parent->ite_name) {
        !           793:                                ite_free(current);
        !           794: 
        !           795:                                current = parent;
        !           796:                                parent = current->ite_lchild;
        !           797:                                current->ite_lchild = ITE_NULL;
        !           798:                                goto traverse_entry;
        !           799:                        } else {
        !           800:                                ite_free(current);
        !           801: 
        !           802:                                current = parent;
        !           803:                                parent = current->ite_rchild;
        !           804:                                current->ite_rchild = ITE_NULL;
        !           805:                                goto traverse_back;
        !           806:                        }
        !           807:                } else {
        !           808:                        ipc_tree_entry_t prev;
        !           809: 
        !           810:                        prev = current;
        !           811:                        current = current->ite_rchild;
        !           812:                        ite_free(prev);
        !           813:                        goto traverse_left;
        !           814:                }
        !           815:        } else {
        !           816:                if (current->ite_rchild == ITE_NULL) {
        !           817:                        ipc_tree_entry_t prev;
        !           818: 
        !           819:                        prev = current;
        !           820:                        current = current->ite_lchild;
        !           821:                        ite_free(prev);
        !           822:                        goto traverse_back;
        !           823:                } else {
        !           824:                        ipc_tree_entry_t prev;
        !           825:                        ipc_tree_entry_t ltree, rtree;
        !           826:                        ipc_tree_entry_t *ltreep, *rtreep;
        !           827: 
        !           828:                        /* replace current with largest of left children */
        !           829: 
        !           830:                        prev = current;
        !           831:                        ipc_splay_prim_lookup(MACH_PORT_LARGEST,
        !           832:                                current->ite_lchild, &current,
        !           833:                                &ltree, &ltreep, &rtree, &rtreep);
        !           834:                        ipc_splay_prim_assemble(current,
        !           835:                                &ltree, ltreep, &rtree, rtreep);
        !           836: 
        !           837:                        assert(current->ite_rchild == ITE_NULL);
        !           838:                        current->ite_rchild = prev->ite_rchild;
        !           839:                        ite_free(prev);
        !           840:                        goto traverse_right;
        !           841:                }
        !           842:        }
        !           843:        /*NOTREACHED*/
        !           844: 
        !           845:        /*
        !           846:         *      A state machine:  for each entry, we
        !           847:         *              1) traverse left subtree
        !           848:         *              2) traverse the entry
        !           849:         *              3) traverse right subtree
        !           850:         *              4) traverse back to parent
        !           851:         */
        !           852: 
        !           853:     traverse_left:
        !           854:        if (current->ite_lchild != ITE_NULL) {
        !           855:                ipc_tree_entry_t next;
        !           856: 
        !           857:                next = current->ite_lchild;
        !           858:                current->ite_lchild = parent;
        !           859:                parent = current;
        !           860:                current = next;
        !           861:                goto traverse_left;
        !           862:        }
        !           863: 
        !           864:     traverse_entry:
        !           865:        splay->ist_ltree = current;
        !           866:        splay->ist_rtree = parent;
        !           867:        return current;
        !           868: 
        !           869:     traverse_right:
        !           870:        if (current->ite_rchild != ITE_NULL) {
        !           871:                ipc_tree_entry_t next;
        !           872: 
        !           873:                next = current->ite_rchild;
        !           874:                current->ite_rchild = parent;
        !           875:                parent = current;
        !           876:                current = next;
        !           877:                goto traverse_left;
        !           878:        }
        !           879: 
        !           880:     traverse_back:
        !           881:        if (parent == ITE_NULL) {
        !           882:                splay->ist_root = current;
        !           883:                return ITE_NULL;
        !           884:        }
        !           885: 
        !           886:        if (current->ite_name < parent->ite_name) {
        !           887:                ipc_tree_entry_t prev;
        !           888: 
        !           889:                prev = current;
        !           890:                current = parent;
        !           891:                parent = current->ite_lchild;
        !           892:                current->ite_lchild = prev;
        !           893:                goto traverse_entry;
        !           894:        } else {
        !           895:                ipc_tree_entry_t prev;
        !           896: 
        !           897:                prev = current;
        !           898:                current = parent;
        !           899:                parent = current->ite_rchild;
        !           900:                current->ite_rchild = prev;
        !           901:                goto traverse_back;
        !           902:        }
        !           903: }
        !           904: 
        !           905: void
        !           906: ipc_splay_traverse_finish(
        !           907:        ipc_splay_tree_t        splay)
        !           908: {
        !           909:        ipc_tree_entry_t root;
        !           910: 
        !           911:        root = splay->ist_root;
        !           912:        if (root != ITE_NULL) {
        !           913:                splay->ist_name = root->ite_name;
        !           914:                splay->ist_ltreep = &splay->ist_ltree;
        !           915:                splay->ist_rtreep = &splay->ist_rtree;
        !           916:        }
        !           917: 
        !           918:        ist_unlock(splay);
        !           919: }
        !           920: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.