2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1999 Apple Computer, Inc.
29 * sdouglas 05 Nov 99 - created.
32 #include <libkern/c++/OSArray.h>
33 #include <libkern/c++/OSNumber.h>
34 #include <IOKit/IORangeAllocator.h>
35 #include <IOKit/IOLib.h>
36 #include <IOKit/IOLocks.h>
37 #include <IOKit/assert.h>
39 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
42 #define super OSObject
44 OSDefineMetaClassAndStructors( IORangeAllocator
, OSObject
)
46 struct IORangeAllocatorElement
{
52 IOLock
* gIORangeAllocatorLock
;
55 if( options & kLocking) IOTakeLock( gIORangeAllocatorLock )
57 if( options & kLocking) IOUnlock( gIORangeAllocatorLock )
59 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
61 bool IORangeAllocator::init( IORangeScalar endOfRange
,
62 IORangeScalar _defaultAlignment
,
64 IOOptionBits _options
)
71 if( !_defaultAlignment
)
72 _defaultAlignment
= 1;
74 capacityIncrement
= _capacity
;
77 defaultAlignmentMask
= _defaultAlignment
- 1;
80 if( (!gIORangeAllocatorLock
) && (options
& kLocking
))
81 gIORangeAllocatorLock
= IOLockAlloc();
84 deallocate( 0, endOfRange
+ 1 );
89 IORangeAllocator
* IORangeAllocator:: withRange(
90 IORangeScalar endOfRange
,
91 IORangeScalar defaultAlignment
,
93 IOOptionBits options
)
95 IORangeAllocator
* thingy
;
97 thingy
= new IORangeAllocator
;
98 if( thingy
&& ! thingy
->init( endOfRange
, defaultAlignment
,
99 capacity
, options
)) {
107 void IORangeAllocator::free()
110 IODelete( elements
, IORangeAllocatorElement
, capacity
);
115 UInt32
IORangeAllocator::getFragmentCount( void )
117 return( numElements
);
120 UInt32
IORangeAllocator::getFragmentCapacity( void )
125 void IORangeAllocator::setFragmentCapacityIncrement( UInt32 count
)
127 capacityIncrement
= count
;
131 // allocate element at index
132 bool IORangeAllocator::allocElement( UInt32 index
)
135 IORangeAllocatorElement
* newElements
;
137 if( ((numElements
== capacity
) && capacityIncrement
)
140 newCapacity
= capacity
+ capacityIncrement
;
141 newElements
= IONew( IORangeAllocatorElement
, newCapacity
);
148 index
* sizeof( IORangeAllocatorElement
));
149 bcopy( elements
+ index
,
150 newElements
+ index
+ 1,
151 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
153 IODelete( elements
, IORangeAllocatorElement
, capacity
);
156 elements
= newElements
;
157 capacity
= newCapacity
;
161 bcopy( elements
+ index
,
162 elements
+ index
+ 1,
163 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
170 // destroy element at index
171 void IORangeAllocator::deallocElement( UInt32 index
)
174 bcopy( elements
+ index
+ 1,
176 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
179 bool IORangeAllocator::allocate( IORangeScalar size
,
180 IORangeScalar
* result
,
181 IORangeScalar alignment
)
183 IORangeScalar data
, dataEnd
;
184 IORangeScalar thisStart
, thisEnd
;
188 if( !size
|| !result
)
192 alignment
= defaultAlignmentMask
;
196 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
200 for( index
= 0; index
< numElements
; index
++ ) {
202 thisStart
= elements
[index
].start
;
203 thisEnd
= elements
[index
].end
;
204 data
= (thisStart
+ alignment
) & ~alignment
;
205 dataEnd
= (data
+ size
- 1);
207 ok
= (dataEnd
<= thisEnd
);
209 if( data
!= thisStart
) {
210 if( dataEnd
!= thisEnd
) {
211 if( allocElement( index
+ 1 )) {
212 elements
[index
++].end
= data
- 1;
213 elements
[index
].start
= dataEnd
+ 1;
214 elements
[index
].end
= thisEnd
;
218 elements
[index
].end
= data
- 1;
220 if( dataEnd
!= thisEnd
)
221 elements
[index
].start
= dataEnd
+ 1;
223 deallocElement( index
);
236 bool IORangeAllocator::allocateRange( IORangeScalar data
,
239 IORangeScalar thisStart
, thisEnd
;
240 IORangeScalar dataEnd
;
247 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
248 dataEnd
= data
+ size
- 1;
253 (!found
) && (index
< numElements
);
256 thisStart
= elements
[index
].start
;
257 thisEnd
= elements
[index
].end
;
259 if( thisStart
> data
)
261 found
= (dataEnd
<= thisEnd
);
264 if( data
!= thisStart
) {
265 if( dataEnd
!= thisEnd
) {
266 found
= allocElement( index
+ 1 );
268 elements
[index
++].end
= data
- 1;
269 elements
[index
].start
= dataEnd
+ 1;
270 elements
[index
].end
= thisEnd
;
273 elements
[index
].end
= data
- 1;
274 } else if( dataEnd
!= thisEnd
)
275 elements
[index
].start
= dataEnd
+ 1;
277 deallocElement( index
);
286 void IORangeAllocator::deallocate( IORangeScalar data
,
289 IORangeScalar dataEnd
;
291 bool headContig
= false;
292 bool tailContig
= false;
294 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
295 dataEnd
= data
+ size
- 1;
299 for( index
= 0; index
< numElements
; index
++ ) {
300 if( elements
[index
].start
< data
) {
301 headContig
= (data
<= (elements
[index
].end
+ 1));
304 tailContig
= ((data
+ size
) >= elements
[index
].start
);
310 elements
[index
-1].end
= elements
[index
].end
;
311 deallocElement( index
);
312 } else /*safe*/ if( dataEnd
> elements
[index
-1].end
)
313 elements
[index
-1].end
= dataEnd
;
315 } else if( tailContig
) {
316 if( data
< elements
[index
].start
) /*safe*/
317 elements
[index
].start
= data
;
319 } else if( allocElement( index
)) {
320 elements
[index
].start
= data
;
321 elements
[index
].end
= dataEnd
;
327 bool IORangeAllocator::serialize(OSSerialize
*s
) const
329 OSArray
* array
= OSArray::withCapacity( numElements
* 2 );
339 for( index
= 0; index
< numElements
; index
++) {
340 if( (num
= OSNumber::withNumber( elements
[index
].start
,
341 8 * sizeof(IORangeScalar
) ))) {
342 array
->setObject(num
);
345 if( (num
= OSNumber::withNumber( elements
[index
].end
,
346 8 * sizeof(IORangeScalar
) ))) {
347 array
->setObject(num
);
354 ret
= array
->serialize(s
);
360 IORangeScalar
IORangeAllocator::getFreeCount( void )
363 IORangeScalar sum
= 0;
365 for( index
= 0; index
< numElements
; index
++)
366 sum
+= elements
[index
].end
- elements
[index
].start
+ 1;