|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.