Annotation of kernel/ipc/ipc_splay.c, revision 1.1

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

unix.superglobalmegacorp.com

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