Annotation of XNU/osfmk/kern/rtmalloc.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * @OSF_COPYRIGHT@
        !            24:  */
        !            25: /*
        !            26:  * HISTORY
        !            27:  * $Log: rtmalloc.c,v $
        !            28:  * Revision 1.1.1.1  2000/03/25 21:02:59  wsanchez
        !            29:  * Import of xnu-68.4
        !            30:  *
        !            31:  * Revision 1.3  2000/01/26 05:57:35  wsanchez
        !            32:  * Add APSL
        !            33:  *
        !            34:  * Revision 1.2  1998/10/20 03:35:27  wsanchez
        !            35:  * Merged in Bill's mother-of-all-diffs.
        !            36:  *
        !            37:  * Revision 1.1.2.1  1998/10/20 02:52:22  angell
        !            38:  * Changed PTE handling.  Added SMP and RT. Improved context saving.
        !            39:  *
        !            40:  * Revision 1.1.1.1  1998/09/22 21:05:33  wsanchez
        !            41:  * Import of Mac OS X kernel (~semeria)
        !            42:  *
        !            43:  * Revision 1.1.1.1  1998/03/07 02:25:56  wsanchez
        !            44:  * Import of OSF Mach kernel (~mburg)
        !            45:  *
        !            46:  * Revision 1.1.4.4  1995/10/09  17:16:24  devrcs
        !            47:  *     Merge RT IPC
        !            48:  *     [1995/09/21  23:10:26  widyono]
        !            49:  *
        !            50:  * Revision 1.1.4.3  1995/01/10  05:13:37  devrcs
        !            51:  *     mk6 CR801 - copyright marker not FREE_
        !            52:  *     [1994/12/01  19:24:57  dwm]
        !            53:  * 
        !            54:  *     mk6 CR668 - 1.3b26 merge
        !            55:  *     zchange to zone_change
        !            56:  *     [1994/11/04  09:29:18  dwm]
        !            57:  * 
        !            58:  * Revision 1.1.4.1  1994/08/18  23:12:56  widyono
        !            59:  *     RT IPC from RT2_SHARED
        !            60:  *     [1994/08/18  15:50:06  widyono]
        !            61:  * 
        !            62:  * Revision 1.1.2.1  1994/07/29  07:34:38  widyono
        !            63:  *     Explicitly make RT zones non-collectable, non-expandable
        !            64:  *     [1994/07/29  06:26:39  widyono]
        !            65:  * 
        !            66:  *     Update to rt2_shared: zchange -> zone_change
        !            67:  *     [1994/07/29  05:07:59  widyono]
        !            68:  * 
        !            69:  *     RT zone allocation routines, new module
        !            70:  *     [1994/07/28  22:31:19  widyono]
        !            71:  * 
        !            72:  * $EndLog$
        !            73:  */
        !            74: /* CMU_HIST */
        !            75: /*
        !            76:  * Revision 2.9  91/05/14  16:43:17  mrt
        !            77:  *     Correcting copyright
        !            78:  * 
        !            79:  * Revision 2.8  91/03/16  14:50:37  rpd
        !            80:  *     Updated for new kmem_alloc interface.
        !            81:  *     [91/03/03            rpd]
        !            82:  * 
        !            83:  * Revision 2.7  91/02/05  17:27:22  mrt
        !            84:  *     Changed to new Mach copyright
        !            85:  *     [91/02/01  16:14:12  mrt]
        !            86:  * 
        !            87:  * Revision 2.6  90/06/19  22:59:06  rpd
        !            88:  *     Made the big kalloc zones collectable.
        !            89:  *     [90/06/05            rpd]
        !            90:  * 
        !            91:  * Revision 2.5  90/06/02  14:54:47  rpd
        !            92:  *     Added kalloc_max, kalloc_map_size.
        !            93:  *     [90/03/26  22:06:39  rpd]
        !            94:  * 
        !            95:  * Revision 2.4  90/01/11  11:43:13  dbg
        !            96:  *     De-lint.
        !            97:  *     [89/12/06            dbg]
        !            98:  * 
        !            99:  * Revision 2.3  89/09/08  11:25:51  dbg
        !           100:  *     MACH_KERNEL: remove non-MACH data types.
        !           101:  *     [89/07/11            dbg]
        !           102:  * 
        !           103:  * Revision 2.2  89/08/31  16:18:59  rwd
        !           104:  *     First Checkin
        !           105:  *     [89/08/23  15:41:37  rwd]
        !           106:  * 
        !           107:  * Revision 2.6  89/08/02  08:03:28  jsb
        !           108:  *     Make all kalloc zones 8 MB big. (No more kalloc panics!)
        !           109:  *     [89/08/01  14:10:17  jsb]
        !           110:  * 
        !           111:  * Revision 2.4  89/04/05  13:03:10  rvb
        !           112:  *     Guarantee a zone max of at least 100 elements or 10 pages
        !           113:  *     which ever is greater.  Afs (AllocDouble()) puts a great demand
        !           114:  *     on the 2048 zone and used to blow away.
        !           115:  *     [89/03/09            rvb]
        !           116:  * 
        !           117:  * Revision 2.3  89/02/25  18:04:39  gm0w
        !           118:  *     Changes for cleanup.
        !           119:  * 
        !           120:  * Revision 2.2  89/01/18  02:07:04  jsb
        !           121:  *     Give each kalloc zone a meaningful name (for panics);
        !           122:  *     create a zone for each power of 2 between MINSIZE
        !           123:  *     and PAGE_SIZE, instead of using (obsoleted) NQUEUES.
        !           124:  *     [89/01/17  10:16:33  jsb]
        !           125:  * 
        !           126:  *
        !           127:  * 13-Feb-88  John Seamons (jks) at NeXT
        !           128:  *     Updated to use kmem routines instead of vmem routines.
        !           129:  *
        !           130:  * 21-Jun-85  Avadis Tevanian (avie) at Carnegie-Mellon University
        !           131:  *     Created.
        !           132:  */
        !           133: /* CMU_ENDHIST */
        !           134: /* 
        !           135:  * Mach Operating System
        !           136:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
        !           137:  * All Rights Reserved.
        !           138:  * 
        !           139:  * Permission to use, copy, modify and distribute this software and its
        !           140:  * documentation is hereby granted, provided that both the copyright
        !           141:  * notice and this permission notice appear in all copies of the
        !           142:  * software, derivative works or modified versions, and any portions
        !           143:  * thereof, and that both notices appear in supporting documentation.
        !           144:  * 
        !           145:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !           146:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !           147:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !           148:  * 
        !           149:  * Carnegie Mellon requests users of this software to return to
        !           150:  * 
        !           151:  *  Software Distribution Coordinator  or  [email protected]
        !           152:  *  School of Computer Science
        !           153:  *  Carnegie Mellon University
        !           154:  *  Pittsburgh PA 15213-3890
        !           155:  * 
        !           156:  * any improvements or extensions that they make and grant Carnegie Mellon
        !           157:  * the rights to redistribute these changes.
        !           158:  */
        !           159: /*
        !           160:  */
        !           161: /*
        !           162:  *     File:   kern/rtmalloc.c
        !           163:  *     Author: Ron Widyono
        !           164:  *     Date:   1994
        !           165:  *
        !           166:  *     General real-time kernel memory allocator.  This allocator is designed
        !           167:  *     to be used by the kernel to manage dynamic memory fast, but exclusively
        !           168:  *      for real-time purposes.  In fact, only real-time IPC users compete for
        !           169:  *      these resources.
        !           170:  *
        !           171:  *      This is a dirty implementation--a clone of kalloc.  A cleaner imple-
        !           172:  *      mentation is to have both k_zones and rt_zones use common code.
        !           173:  */
        !           174: 
        !           175: #include <mach/boolean.h>
        !           176: #include <mach/machine/vm_types.h>
        !           177: #include <mach/vm_param.h>
        !           178: #include <kern/misc_protos.h>
        !           179: #include <kern/zalloc.h>
        !           180: #include <kern/rtmalloc.h>
        !           181: #include <vm/vm_kern.h>
        !           182: #include <vm/vm_object.h>
        !           183: #include <vm/vm_map.h>
        !           184: 
        !           185: extern void    Debugger(const char *);
        !           186: 
        !           187: vm_map_t rtmalloc_map;
        !           188: vm_size_t rtmalloc_map_size = 8 * 1024 * 1024;
        !           189: vm_size_t rtmalloc_max;
        !           190: vm_size_t rtmalloc_max_prerounded;
        !           191: 
        !           192: /*
        !           193:  *     All allocations of size less than rtmalloc_max are rounded to the
        !           194:  *     next highest power of 2.  This allocator is built on top of
        !           195:  *     the zone allocator.  A zone is created for each potential size
        !           196:  *     that we are willing to get in small blocks.
        !           197:  *
        !           198:  *     We assume that rtmalloc_max is not greater than 64K;
        !           199:  *     thus 16 is a safe array size for rt_zone and rt_zone_name.
        !           200:  *
        !           201:  *     Note that rtmalloc_max is somewhat confusingly named.
        !           202:  *     It represents the first power of two for which no zone exists.
        !           203:  *     rtmalloc_max_prerounded is the smallest allocation size, before
        !           204:  *     rounding, for which no zone exists.
        !           205:  */
        !           206: 
        !           207: int first_rt_zone = -1;
        !           208: struct zone *rt_zone[16];
        !           209: static char *rt_zone_name[16] = {
        !           210:        "rtmalloc.1",           "rtmalloc.2",
        !           211:        "rtmalloc.4",           "rtmalloc.8",
        !           212:        "rtmalloc.16",          "rtmalloc.32",
        !           213:        "rtmalloc.64",          "rtmalloc.128",
        !           214:        "rtmalloc.256",         "rtmalloc.512",
        !           215:        "rtmalloc.1024",                "rtmalloc.2048",
        !           216:        "rtmalloc.4096",                "rtmalloc.8192",
        !           217:        "rtmalloc.16384",       "rtmalloc.32768"
        !           218: };
        !           219: 
        !           220: /*
        !           221:  *  Max number of elements per zone.  zinit rounds things up correctly
        !           222:  *  Doing things this way permits each zone to have a different maximum size
        !           223:  *  based on need, rather than just guessing; it also
        !           224:  *  means its patchable in case you're wrong!
        !           225:  */
        !           226: unsigned long rt_zone_max[16] = {
        !           227:       RT_ZONE_MAX_1,   
        !           228:       RT_ZONE_MAX_2,   
        !           229:       RT_ZONE_MAX_4,   
        !           230:       RT_ZONE_MAX_8,   
        !           231:       RT_ZONE_MAX_16,  
        !           232:       RT_ZONE_MAX_32,  
        !           233:       RT_ZONE_MAX_64,  
        !           234:       RT_ZONE_MAX_128, 
        !           235:       RT_ZONE_MAX_256, 
        !           236:       RT_ZONE_MAX_512, 
        !           237:       RT_ZONE_MAX_1024,        
        !           238:       RT_ZONE_MAX_2048,        
        !           239:       RT_ZONE_MAX_4096,        
        !           240:       RT_ZONE_MAX_8192,        
        !           241:       RT_ZONE_MAX_16384,
        !           242:       RT_ZONE_MAX_32768
        !           243: };
        !           244: 
        !           245: /*
        !           246:  *     Initialize the memory allocator.  This should be called only
        !           247:  *     once on a system wide basis (i.e. first processor to get here
        !           248:  *     does the initialization).
        !           249:  *
        !           250:  *     This initializes all of the zones.
        !           251:  */
        !           252: 
        !           253: void
        !           254: rtmalloc_init(
        !           255:        void)
        !           256: {
        !           257:        kern_return_t retval;
        !           258:        vm_offset_t min, addr;
        !           259:        vm_size_t size;
        !           260:        register int i;
        !           261: 
        !           262:        retval = kmem_suballoc(kernel_map, &min, rtmalloc_map_size,
        !           263:                               FALSE, TRUE, &rtmalloc_map);
        !           264:        if (retval != KERN_SUCCESS)
        !           265:                panic("rtmalloc_init: kmem_suballoc failed");
        !           266: 
        !           267:        /*
        !           268:         *      Ensure that zones up to size 8192 bytes exist.
        !           269:         *      This is desirable because messages are allocated
        !           270:         *      with rtmalloc, and messages up through size 8192 are common.
        !           271:         */
        !           272: 
        !           273:        rtmalloc_max = 16 * 1024;
        !           274:        rtmalloc_max_prerounded = rtmalloc_max / 2 + 1;
        !           275: 
        !           276:        /*
        !           277:         *      Allocate a zone for each size we are going to handle.
        !           278:         *      We specify non-paged memory.  Make zone exhaustible.
        !           279:         */
        !           280:        for (i = 0, size = 1; size < rtmalloc_max; i++, size <<= 1) {
        !           281:                if (size < rtmalloc_MINSIZE) {
        !           282:                        rt_zone[i] = 0;
        !           283:                        continue;
        !           284:                }
        !           285:                if (size == rtmalloc_MINSIZE) {
        !           286:                        first_rt_zone = i;
        !           287:                }
        !           288:                rt_zone[i] = zinit(size, rt_zone_max[i] * size, size,
        !           289:                                  rt_zone_name[i]);
        !           290:                zone_change(rt_zone[i], Z_EXHAUST, TRUE);
        !           291:                zone_change(rt_zone[i], Z_COLLECT, FALSE);
        !           292:                zone_change(rt_zone[i], Z_EXPAND, FALSE);
        !           293: 
        !           294:                /*
        !           295:                 * Get space from the zone_map.  Since these zones are
        !           296:                 * not collectable, no pages containing elements from these
        !           297:                 * zones will ever be reclaimed by the garbage collection
        !           298:                 * scheme below.
        !           299:                 */
        !           300: 
        !           301:                zprealloc(rt_zone[i], rt_zone_max[i] * size);
        !           302:        }
        !           303: }
        !           304: 
        !           305: vm_offset_t
        !           306: rtmalloc(
        !           307:        vm_size_t       size)
        !           308: {
        !           309:        register int zindex;
        !           310:        register vm_size_t allocsize;
        !           311: 
        !           312:        /*
        !           313:         * If size is too large for a zone, return error (0)
        !           314:         */
        !           315: 
        !           316:        if (size >= rtmalloc_max_prerounded) {
        !           317:                return(0);
        !           318:        }
        !           319: 
        !           320:        /* compute the size of the block that we will actually allocate */
        !           321: 
        !           322:        allocsize = rtmalloc_MINSIZE;
        !           323:        zindex = first_rt_zone;
        !           324:        while (allocsize < size) {
        !           325:                allocsize <<= 1;
        !           326:                zindex++;
        !           327:        }
        !           328: 
        !           329:        /* allocate from the appropriate zone */
        !           330: 
        !           331:        assert(allocsize < rtmalloc_max);
        !           332:        return(zalloc(rt_zone[zindex]));
        !           333: }
        !           334: 
        !           335: vm_offset_t
        !           336: rtget(
        !           337:        vm_size_t       size)
        !           338: {
        !           339:        register int zindex;
        !           340:        register vm_size_t allocsize;
        !           341: 
        !           342:        /* size must not be too large for a zone */
        !           343: 
        !           344:        if (size >= rtmalloc_max_prerounded) {
        !           345:                /* This will never work, so we might as well panic */
        !           346:                panic("rtget");
        !           347:        }
        !           348: 
        !           349:        /* compute the size of the block that we will actually allocate */
        !           350: 
        !           351:        allocsize = rtmalloc_MINSIZE;
        !           352:        zindex = first_rt_zone;
        !           353:        while (allocsize < size) {
        !           354:                allocsize <<= 1;
        !           355:                zindex++;
        !           356:        }
        !           357: 
        !           358:        /* allocate from the appropriate zone */
        !           359: 
        !           360:        assert(allocsize < rtmalloc_max);
        !           361:        return(zget(rt_zone[zindex]));
        !           362: }
        !           363: 
        !           364: void
        !           365: rtmfree(
        !           366:        vm_offset_t     data,
        !           367:        vm_size_t       size)
        !           368: {
        !           369:        register int zindex;
        !           370:        register vm_size_t freesize;
        !           371: 
        !           372:        /*
        !           373:         * if size was too large for a RT zone, this is impossible;
        !           374:         * just return
        !           375:         */
        !           376: 
        !           377:        assert(size < rtmalloc_max_prerounded);
        !           378:        if (size >= rtmalloc_max_prerounded) {
        !           379:                return;
        !           380:        }
        !           381: 
        !           382:        /* compute the size of the block that we actually allocated from */
        !           383: 
        !           384:        freesize = rtmalloc_MINSIZE;
        !           385:        zindex = first_rt_zone;
        !           386:        while (freesize < size) {
        !           387:                freesize <<= 1;
        !           388:                zindex++;
        !           389:        }
        !           390: 
        !           391:        /* free to the appropriate zone */
        !           392: 
        !           393:        assert(freesize < rtmalloc_max);
        !           394:        zfree(rt_zone[zindex], data);
        !           395: }

unix.superglobalmegacorp.com

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