2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright (c) 1999 Apple Computer, Inc.
36 * sdouglas 05 Nov 99 - created.
39 #include <libkern/c++/OSArray.h>
40 #include <libkern/c++/OSNumber.h>
41 #include <IOKit/IORangeAllocator.h>
42 #include <IOKit/IOLib.h>
43 #include <IOKit/IOLocks.h>
44 #include <IOKit/assert.h>
46 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
49 #define super OSObject
51 OSDefineMetaClassAndStructors( IORangeAllocator
, OSObject
)
53 struct IORangeAllocatorElement
{
59 IOLock
* gIORangeAllocatorLock
;
62 if( options & kLocking) IOTakeLock( gIORangeAllocatorLock )
64 if( options & kLocking) IOUnlock( gIORangeAllocatorLock )
66 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
68 bool IORangeAllocator::init( IORangeScalar endOfRange
,
69 IORangeScalar _defaultAlignment
,
71 IOOptionBits _options
)
78 if( !_defaultAlignment
)
79 _defaultAlignment
= 1;
81 capacityIncrement
= _capacity
;
84 defaultAlignmentMask
= _defaultAlignment
- 1;
87 if( (!gIORangeAllocatorLock
) && (options
& kLocking
))
88 gIORangeAllocatorLock
= IOLockAlloc();
91 deallocate( 0, endOfRange
+ 1 );
96 IORangeAllocator
* IORangeAllocator:: withRange(
97 IORangeScalar endOfRange
,
98 IORangeScalar defaultAlignment
,
100 IOOptionBits options
)
102 IORangeAllocator
* thingy
;
104 thingy
= new IORangeAllocator
;
105 if( thingy
&& ! thingy
->init( endOfRange
, defaultAlignment
,
106 capacity
, options
)) {
114 void IORangeAllocator::free()
117 IODelete( elements
, IORangeAllocatorElement
, capacity
);
122 UInt32
IORangeAllocator::getFragmentCount( void )
124 return( numElements
);
127 UInt32
IORangeAllocator::getFragmentCapacity( void )
132 void IORangeAllocator::setFragmentCapacityIncrement( UInt32 count
)
134 capacityIncrement
= count
;
138 // allocate element at index
139 bool IORangeAllocator::allocElement( UInt32 index
)
142 IORangeAllocatorElement
* newElements
;
144 if( ((numElements
== capacity
) && capacityIncrement
)
147 newCapacity
= capacity
+ capacityIncrement
;
148 newElements
= IONew( IORangeAllocatorElement
, newCapacity
);
155 index
* sizeof( IORangeAllocatorElement
));
156 bcopy( elements
+ index
,
157 newElements
+ index
+ 1,
158 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
160 IODelete( elements
, IORangeAllocatorElement
, capacity
);
163 elements
= newElements
;
164 capacity
= newCapacity
;
168 bcopy( elements
+ index
,
169 elements
+ index
+ 1,
170 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
177 // destroy element at index
178 void IORangeAllocator::deallocElement( UInt32 index
)
181 bcopy( elements
+ index
+ 1,
183 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
186 bool IORangeAllocator::allocate( IORangeScalar size
,
187 IORangeScalar
* result
,
188 IORangeScalar alignment
)
190 IORangeScalar data
, dataEnd
;
191 IORangeScalar thisStart
, thisEnd
;
195 if( !size
|| !result
)
199 alignment
= defaultAlignmentMask
;
203 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
207 for( index
= 0; index
< numElements
; index
++ ) {
209 thisStart
= elements
[index
].start
;
210 thisEnd
= elements
[index
].end
;
211 data
= (thisStart
+ alignment
) & ~alignment
;
212 dataEnd
= (data
+ size
- 1);
214 ok
= (dataEnd
<= thisEnd
);
216 if( data
!= thisStart
) {
217 if( dataEnd
!= thisEnd
) {
218 if( allocElement( index
+ 1 )) {
219 elements
[index
++].end
= data
- 1;
220 elements
[index
].start
= dataEnd
+ 1;
221 elements
[index
].end
= thisEnd
;
225 elements
[index
].end
= data
- 1;
227 if( dataEnd
!= thisEnd
)
228 elements
[index
].start
= dataEnd
+ 1;
230 deallocElement( index
);
243 bool IORangeAllocator::allocateRange( IORangeScalar data
,
246 IORangeScalar thisStart
, thisEnd
;
247 IORangeScalar dataEnd
;
254 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
255 dataEnd
= data
+ size
- 1;
260 (!found
) && (index
< numElements
);
263 thisStart
= elements
[index
].start
;
264 thisEnd
= elements
[index
].end
;
266 if( thisStart
> data
)
268 found
= (dataEnd
<= thisEnd
);
271 if( data
!= thisStart
) {
272 if( dataEnd
!= thisEnd
) {
273 found
= allocElement( index
+ 1 );
275 elements
[index
++].end
= data
- 1;
276 elements
[index
].start
= dataEnd
+ 1;
277 elements
[index
].end
= thisEnd
;
280 elements
[index
].end
= data
- 1;
281 } else if( dataEnd
!= thisEnd
)
282 elements
[index
].start
= dataEnd
+ 1;
284 deallocElement( index
);
293 void IORangeAllocator::deallocate( IORangeScalar data
,
296 IORangeScalar dataEnd
;
298 bool headContig
= false;
299 bool tailContig
= false;
301 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
302 dataEnd
= data
+ size
- 1;
306 for( index
= 0; index
< numElements
; index
++ ) {
307 if( elements
[index
].start
< data
) {
308 headContig
= (data
<= (elements
[index
].end
+ 1));
311 tailContig
= ((data
+ size
) >= elements
[index
].start
);
317 elements
[index
-1].end
= elements
[index
].end
;
318 deallocElement( index
);
319 } else /*safe*/ if( dataEnd
> elements
[index
-1].end
)
320 elements
[index
-1].end
= dataEnd
;
322 } else if( tailContig
) {
323 if( data
< elements
[index
].start
) /*safe*/
324 elements
[index
].start
= data
;
326 } else if( allocElement( index
)) {
327 elements
[index
].start
= data
;
328 elements
[index
].end
= dataEnd
;
334 bool IORangeAllocator::serialize(OSSerialize
*s
) const
336 OSArray
* array
= OSArray::withCapacity( numElements
* 2 );
346 for( index
= 0; index
< numElements
; index
++) {
347 if( (num
= OSNumber::withNumber( elements
[index
].start
,
348 8 * sizeof(IORangeScalar
) ))) {
349 array
->setObject(num
);
352 if( (num
= OSNumber::withNumber( elements
[index
].end
,
353 8 * sizeof(IORangeScalar
) ))) {
354 array
->setObject(num
);
361 ret
= array
->serialize(s
);
367 IORangeScalar
IORangeAllocator::getFreeCount( void )
370 IORangeScalar sum
= 0;
372 for( index
= 0; index
< numElements
; index
++)
373 sum
+= elements
[index
].end
- elements
[index
].start
+ 1;