2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_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. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1999 Apple Computer, Inc.
34 * sdouglas 05 Nov 99 - created.
37 #include <libkern/c++/OSArray.h>
38 #include <libkern/c++/OSNumber.h>
39 #include <IOKit/IORangeAllocator.h>
40 #include <IOKit/IOLib.h>
41 #include <IOKit/IOLocks.h>
42 #include <IOKit/assert.h>
44 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
47 #define super OSObject
49 OSDefineMetaClassAndStructors( IORangeAllocator
, OSObject
)
51 struct IORangeAllocatorElement
{
57 IOLock
* gIORangeAllocatorLock
;
60 if( options & kLocking) IOTakeLock( gIORangeAllocatorLock )
62 if( options & kLocking) IOUnlock( gIORangeAllocatorLock )
64 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
66 bool IORangeAllocator::init( IORangeScalar endOfRange
,
67 IORangeScalar _defaultAlignment
,
69 IOOptionBits _options
)
76 if( !_defaultAlignment
)
77 _defaultAlignment
= 1;
79 capacityIncrement
= _capacity
;
82 defaultAlignmentMask
= _defaultAlignment
- 1;
85 if( (!gIORangeAllocatorLock
) && (options
& kLocking
))
86 gIORangeAllocatorLock
= IOLockAlloc();
89 deallocate( 0, endOfRange
+ 1 );
94 IORangeAllocator
* IORangeAllocator::withRange(
95 IORangeScalar endOfRange
,
96 IORangeScalar defaultAlignment
,
98 IOOptionBits options
)
100 IORangeAllocator
* thingy
;
102 thingy
= new IORangeAllocator
;
103 if( thingy
&& ! thingy
->init( endOfRange
, defaultAlignment
,
104 capacity
, options
)) {
112 void IORangeAllocator::free()
115 IODelete( elements
, IORangeAllocatorElement
, capacity
);
120 UInt32
IORangeAllocator::getFragmentCount( void )
122 return( numElements
);
125 UInt32
IORangeAllocator::getFragmentCapacity( void )
130 void IORangeAllocator::setFragmentCapacityIncrement( UInt32 count
)
132 capacityIncrement
= count
;
136 // allocate element at index
137 bool IORangeAllocator::allocElement( UInt32 index
)
140 IORangeAllocatorElement
* newElements
;
142 if( ((numElements
== capacity
) && capacityIncrement
)
145 if (os_add_overflow(capacity
, capacityIncrement
, &newCapacity
))
147 newElements
= IONew( IORangeAllocatorElement
, newCapacity
);
154 index
* sizeof( IORangeAllocatorElement
));
155 bcopy( elements
+ index
,
156 newElements
+ index
+ 1,
157 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
159 IODelete( elements
, IORangeAllocatorElement
, capacity
);
162 elements
= newElements
;
163 capacity
= newCapacity
;
167 bcopy( elements
+ index
,
168 elements
+ index
+ 1,
169 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
176 // destroy element at index
177 void IORangeAllocator::deallocElement( UInt32 index
)
180 bcopy( elements
+ index
+ 1,
182 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
185 bool IORangeAllocator::allocate( IORangeScalar size
,
186 IORangeScalar
* result
,
187 IORangeScalar alignment
)
189 IORangeScalar data
, dataEnd
;
190 IORangeScalar thisStart
, thisEnd
;
194 if( !size
|| !result
)
198 alignment
= defaultAlignmentMask
;
202 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
206 for( index
= 0; index
< numElements
; index
++ ) {
208 thisStart
= elements
[index
].start
;
209 thisEnd
= elements
[index
].end
;
210 data
= (thisStart
+ alignment
) & ~alignment
;
211 dataEnd
= (data
+ size
- 1);
213 ok
= (dataEnd
<= thisEnd
);
215 if( data
!= thisStart
) {
216 if( dataEnd
!= thisEnd
) {
217 if( allocElement( index
+ 1 )) {
218 elements
[index
++].end
= data
- 1;
219 elements
[index
].start
= dataEnd
+ 1;
220 elements
[index
].end
= thisEnd
;
224 elements
[index
].end
= data
- 1;
226 if( dataEnd
!= thisEnd
)
227 elements
[index
].start
= dataEnd
+ 1;
229 deallocElement( index
);
242 bool IORangeAllocator::allocateRange( IORangeScalar data
,
245 IORangeScalar thisStart
, thisEnd
;
246 IORangeScalar dataEnd
;
253 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
254 dataEnd
= data
+ size
- 1;
259 (!found
) && (index
< numElements
);
262 thisStart
= elements
[index
].start
;
263 thisEnd
= elements
[index
].end
;
265 if( thisStart
> data
)
267 found
= (dataEnd
<= thisEnd
);
270 if( data
!= thisStart
) {
271 if( dataEnd
!= thisEnd
) {
272 found
= allocElement( index
+ 1 );
274 elements
[index
++].end
= data
- 1;
275 elements
[index
].start
= dataEnd
+ 1;
276 elements
[index
].end
= thisEnd
;
279 elements
[index
].end
= data
- 1;
280 } else if( dataEnd
!= thisEnd
)
281 elements
[index
].start
= dataEnd
+ 1;
283 deallocElement( index
);
292 void IORangeAllocator::deallocate( IORangeScalar data
,
295 IORangeScalar dataEnd
;
297 bool headContig
= false;
298 bool tailContig
= false;
300 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
301 dataEnd
= data
+ size
- 1;
305 for( index
= 0; index
< numElements
; index
++ ) {
306 if( elements
[index
].start
< data
) {
307 headContig
= (data
<= (elements
[index
].end
+ 1));
310 tailContig
= ((data
+ size
) >= elements
[index
].start
);
316 elements
[index
-1].end
= elements
[index
].end
;
317 deallocElement( index
);
318 } else /*safe*/ if( dataEnd
> elements
[index
-1].end
)
319 elements
[index
-1].end
= dataEnd
;
321 } else if( tailContig
) {
322 if( data
< elements
[index
].start
) /*safe*/
323 elements
[index
].start
= data
;
325 } else if( allocElement( index
)) {
326 elements
[index
].start
= data
;
327 elements
[index
].end
= dataEnd
;
333 bool IORangeAllocator::serialize(OSSerialize
*s
) const
335 OSArray
* array
= OSArray::withCapacity( numElements
* 2 );
345 for( index
= 0; index
< numElements
; index
++) {
346 if( (num
= OSNumber::withNumber( elements
[index
].start
,
347 8 * sizeof(IORangeScalar
) ))) {
348 array
->setObject(num
);
351 if( (num
= OSNumber::withNumber( elements
[index
].end
,
352 8 * sizeof(IORangeScalar
) ))) {
353 array
->setObject(num
);
360 ret
= array
->serialize(s
);
366 IORangeScalar
IORangeAllocator::getFreeCount( void )
369 IORangeScalar sum
= 0;
371 for( index
= 0; index
< numElements
; index
++)
372 sum
+= elements
[index
].end
- elements
[index
].start
+ 1;