Annotation of XNU/iokit/Kernel/IORangeAllocator.cpp, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1998-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:  * Copyright (c) 1999 Apple Computer, Inc.
                     24:  *
                     25:  *
                     26:  * HISTORY
                     27:  *
                     28:  * sdouglas 05 Nov 99 - created.
                     29:  */
                     30: 
                     31: #include <libkern/c++/OSArray.h>
                     32: #include <libkern/c++/OSNumber.h>
                     33: #include <IOKit/IORangeAllocator.h>
                     34: #include <IOKit/IOLib.h>
                     35: #include <IOKit/IOLocks.h>
                     36: #include <IOKit/assert.h>
                     37: 
                     38: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     39: 
                     40: #undef super
                     41: #define super OSObject
                     42: 
                     43: OSDefineMetaClassAndStructors( IORangeAllocator, OSObject )
                     44: 
                     45: struct IORangeAllocatorElement {
                     46:     // closed range
                     47:     IORangeScalar      start;
                     48:     IORangeScalar      end;
                     49: };
                     50: 
                     51: IOLock *       gIORangeAllocatorLock;
                     52: 
                     53: #define LOCK()         \
                     54:        if( options & kLocking) IOTakeLock( gIORangeAllocatorLock )
                     55: #define UNLOCK()       \
                     56:        if( options & kLocking) IOUnlock( gIORangeAllocatorLock )
                     57: 
                     58: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     59: 
                     60: bool IORangeAllocator::init( IORangeScalar endOfRange,
                     61:                                IORangeScalar _defaultAlignment,
                     62:                                UInt32 _capacity,
                     63:                                IOOptionBits _options )
                     64: {
                     65:     if( !super::init())
                     66:        return( false );
                     67: 
                     68:     if( !_capacity)
                     69:        _capacity = 1;
                     70:     if( !_defaultAlignment)
                     71:        _defaultAlignment = 1;
                     72:     capacity           = 0;
                     73:     capacityIncrement  = _capacity;
                     74:     numElements        = 0;
                     75:     elements           = 0;
                     76:     defaultAlignmentMask = _defaultAlignment - 1;
                     77:     options            = _options;
                     78: 
                     79:     if( (!gIORangeAllocatorLock) && (options & kLocking))
                     80:        gIORangeAllocatorLock = IOLockAlloc();
                     81: 
                     82:     if( endOfRange)
                     83:        deallocate( 0, endOfRange + 1 );
                     84: 
                     85:     return( true );
                     86: }
                     87: 
                     88: IORangeAllocator * IORangeAllocator:: withRange(
                     89:                                        IORangeScalar endOfRange,
                     90:                                        IORangeScalar defaultAlignment = 0,
                     91:                                        UInt32 capacity = 0,
                     92:                                        IOOptionBits options = 0 )
                     93: {
                     94:     IORangeAllocator * thingy;
                     95: 
                     96:     thingy = new IORangeAllocator;
                     97:     if( thingy && ! thingy->init( endOfRange, defaultAlignment,
                     98:                                capacity, options )) {
                     99:        thingy->release();
                    100:        thingy = 0;
                    101:     }
                    102: 
                    103:     return( thingy );
                    104: }
                    105: 
                    106: void IORangeAllocator::free()
                    107: {
                    108:     if( elements)
                    109:        IODelete( elements, IORangeAllocatorElement, capacity );
                    110: 
                    111:     super::free();
                    112: }
                    113: 
                    114: UInt32 IORangeAllocator::getFragmentCount( void )
                    115: {
                    116:     return( numElements );
                    117: }
                    118: 
                    119: UInt32 IORangeAllocator::getFragmentCapacity( void )
                    120: {
                    121:     return( capacity );
                    122: }
                    123: 
                    124: void IORangeAllocator::setFragmentCapacityIncrement( UInt32 count )
                    125: {
                    126:     capacityIncrement = count;
                    127: }
                    128: 
                    129: 
                    130: // allocate element at index
                    131: bool IORangeAllocator::allocElement( UInt32 index )
                    132: {
                    133:     UInt32                     newCapacity;
                    134:     IORangeAllocatorElement *  newElements;
                    135: 
                    136:     if( ((numElements == capacity) && capacityIncrement)
                    137:      || (!elements)) {
                    138: 
                    139:        newCapacity = capacity + capacityIncrement;
                    140:        newElements = IONew( IORangeAllocatorElement, newCapacity );
                    141:        if( !newElements)
                    142:            return( false );
                    143: 
                    144:        if( elements) {
                    145:            bcopy( elements,
                    146:                   newElements,
                    147:                   index * sizeof( IORangeAllocatorElement));
                    148:            bcopy( elements + index,
                    149:                   newElements + index + 1,
                    150:                   (numElements - index) * sizeof( IORangeAllocatorElement));
                    151: 
                    152:            IODelete( elements, IORangeAllocatorElement, capacity );
                    153:        }
                    154: 
                    155:        elements = newElements;
                    156:        capacity = newCapacity;
                    157: 
                    158:     } else {
                    159: 
                    160:        bcopy( elements + index,
                    161:               elements + index + 1,
                    162:               (numElements - index) * sizeof( IORangeAllocatorElement));
                    163:     }
                    164:     numElements++;
                    165: 
                    166:     return( true );
                    167: }
                    168: 
                    169: // destroy element at index
                    170: void IORangeAllocator::deallocElement( UInt32 index )
                    171: {
                    172:     numElements--;
                    173:     bcopy( elements + index + 1,
                    174:           elements + index,
                    175:           (numElements - index) * sizeof( IORangeAllocatorElement));
                    176: }
                    177: 
                    178: bool IORangeAllocator::allocate( IORangeScalar size,
                    179:                                 IORangeScalar * result,
                    180:                                 IORangeScalar alignment = 0 )
                    181: {
                    182:     IORangeScalar      data, dataEnd;
                    183:     IORangeScalar      thisStart, thisEnd;
                    184:     UInt32             index;
                    185:     bool               ok = false;
                    186: 
                    187:     if( !size || !result)
                    188:        return( false );
                    189: 
                    190:     if( 0 == alignment)
                    191:        alignment = defaultAlignmentMask;
                    192:     else
                    193:         alignment--;
                    194: 
                    195:     size = (size + defaultAlignmentMask) & ~defaultAlignmentMask;
                    196: 
                    197:     LOCK();
                    198: 
                    199:     for( index = 0; index < numElements; index++ ) {
                    200: 
                    201:        thisStart = elements[index].start;
                    202:        thisEnd = elements[index].end;
                    203:         data = (thisStart + alignment) & ~alignment;
                    204:        dataEnd = (data + size - 1);
                    205: 
                    206:        ok = (dataEnd <= thisEnd);
                    207:        if( ok) {
                    208:            if( data != thisStart) {
                    209:                if( dataEnd != thisEnd) {
                    210:                    if( allocElement( index + 1 )) {
                    211:                        elements[index++].end = data - 1;
                    212:                        elements[index].start = dataEnd + 1;
                    213:                        elements[index].end = thisEnd;
                    214:                    } else
                    215:                        ok = false;
                    216:                } else
                    217:                    elements[index].end = data - 1;
                    218:            } else {
                    219:                if( dataEnd != thisEnd)
                    220:                    elements[index].start = dataEnd + 1;
                    221:                else
                    222:                    deallocElement( index );
                    223:            }
                    224:            if( ok)
                    225:                *result = data;
                    226:            break;
                    227:        } 
                    228:     }
                    229: 
                    230:     UNLOCK();
                    231: 
                    232:     return( ok );
                    233: }
                    234: 
                    235: bool IORangeAllocator::allocateRange( IORangeScalar data,
                    236:                                         IORangeScalar size )
                    237: {
                    238:     IORangeScalar      thisStart, thisEnd;
                    239:     IORangeScalar      dataEnd;
                    240:     UInt32             index;
                    241:     bool               found = false;
                    242: 
                    243:     if( !size)
                    244:        return( 0 );
                    245: 
                    246:     size = (size + defaultAlignmentMask) & ~defaultAlignmentMask;
                    247:     dataEnd = data + size - 1;
                    248: 
                    249:     LOCK();
                    250: 
                    251:     for( index = 0;
                    252:         (!found) && (index < numElements);
                    253:         index++ ) {
                    254: 
                    255:        thisStart = elements[index].start;
                    256:        thisEnd = elements[index].end;
                    257: 
                    258:        if( thisStart > data)
                    259:            break;
                    260:        found = (dataEnd <= thisEnd);
                    261: 
                    262:         if( found) {
                    263:            if( data != thisStart) {
                    264:                if( dataEnd != thisEnd) {
                    265:                    found = allocElement( index + 1 );
                    266:                    if( found) {
                    267:                        elements[index++].end = data - 1;
                    268:                        elements[index].start = dataEnd + 1;
                    269:                        elements[index].end = thisEnd;
                    270:                    }
                    271:                } else
                    272:                    elements[index].end = data - 1;
                    273:            } else if( dataEnd != thisEnd)
                    274:                elements[index].start = dataEnd + 1;
                    275:            else
                    276:                deallocElement( index );
                    277:         }
                    278:     }
                    279: 
                    280:     UNLOCK();
                    281: 
                    282:     return( found );
                    283: }
                    284: 
                    285: void IORangeAllocator::deallocate( IORangeScalar data,
                    286:                                   IORangeScalar size )
                    287: {
                    288:     IORangeScalar      dataEnd;
                    289:     UInt32             index;
                    290:     bool               headContig = false;
                    291:     bool               tailContig = false;
                    292: 
                    293:     size = (size + defaultAlignmentMask) & ~defaultAlignmentMask;
                    294:     dataEnd = data + size - 1;
                    295: 
                    296:     LOCK();
                    297: 
                    298:     for( index = 0; index < numElements; index++ ) {
                    299:        if( elements[index].start < data) {
                    300:            headContig = (data <= (elements[index].end + 1));
                    301:            continue;
                    302:        }
                    303:        tailContig = ((data + size) >= elements[index].start);
                    304:        break;
                    305:     }
                    306: 
                    307:     if( headContig) {
                    308:         if( tailContig) {
                    309:             elements[index-1].end = elements[index].end;
                    310:            deallocElement( index );
                    311:        } else /*safe*/ if( dataEnd > elements[index-1].end)
                    312:            elements[index-1].end = dataEnd;
                    313: 
                    314:     } else if( tailContig) {
                    315:        if( data < elements[index].start) /*safe*/
                    316:            elements[index].start = data;
                    317: 
                    318:     } else if( allocElement( index)) {
                    319:        elements[index].start = data;
                    320:        elements[index].end = dataEnd;
                    321:     }
                    322: 
                    323:     UNLOCK();
                    324: }
                    325: 
                    326: bool IORangeAllocator::serialize(OSSerialize *s) const
                    327: {
                    328:     OSArray *  array = OSArray::withCapacity( numElements * 2 );
                    329:     OSNumber * num;
                    330:     UInt32     index;
                    331:     bool       ret;
                    332: 
                    333:     if( !array)
                    334:        return( false );
                    335: 
                    336:     LOCK();
                    337: 
                    338:     for( index = 0; index < numElements; index++) {
                    339:        if( (num = OSNumber::withNumber( elements[index].start,
                    340:                                        8 * sizeof(IORangeScalar) ))) {
                    341:            array->setObject(num);
                    342:            num->release();
                    343:        }
                    344:        if( (num = OSNumber::withNumber( elements[index].end,
                    345:                                        8 * sizeof(IORangeScalar) ))) {
                    346:            array->setObject(num);
                    347:            num->release();
                    348:        }
                    349:     }
                    350: 
                    351:     UNLOCK();
                    352: 
                    353:     ret = array->serialize(s);
                    354:     array->release();
                    355: 
                    356:     return( ret );
                    357: }
                    358: 
                    359: IORangeScalar IORangeAllocator::getFreeCount( void )
                    360: {
                    361:     UInt32             index;
                    362:     IORangeScalar      sum = 0;
                    363: 
                    364:     for( index = 0; index < numElements; index++)
                    365:        sum += elements[index].end - elements[index].start + 1;
                    366: 
                    367:     return( sum );
                    368: }
                    369: 

unix.superglobalmegacorp.com

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