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 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
67 IORangeAllocator::init( IORangeScalar endOfRange
,
68 IORangeScalar _defaultAlignment
,
70 IOOptionBits _options
)
79 if (!_defaultAlignment
) {
80 _defaultAlignment
= 1;
83 capacityIncrement
= _capacity
;
86 defaultAlignmentMask
= _defaultAlignment
- 1;
89 if ((!gIORangeAllocatorLock
) && (options
& kLocking
)) {
90 gIORangeAllocatorLock
= IOLockAlloc();
94 deallocate( 0, endOfRange
+ 1 );
101 IORangeAllocator::withRange(
102 IORangeScalar endOfRange
,
103 IORangeScalar defaultAlignment
,
105 IOOptionBits options
)
107 IORangeAllocator
* thingy
;
109 thingy
= new IORangeAllocator
;
110 if (thingy
&& !thingy
->init( endOfRange
, defaultAlignment
,
111 capacity
, options
)) {
120 IORangeAllocator::free()
123 IODelete( elements
, IORangeAllocatorElement
, capacity
);
130 IORangeAllocator::getFragmentCount( void )
136 IORangeAllocator::getFragmentCapacity( void )
142 IORangeAllocator::setFragmentCapacityIncrement( UInt32 count
)
144 capacityIncrement
= count
;
148 // allocate element at index
150 IORangeAllocator::allocElement( UInt32 index
)
153 IORangeAllocatorElement
* newElements
;
155 if (((numElements
== capacity
) && capacityIncrement
)
157 if (os_add_overflow(capacity
, capacityIncrement
, &newCapacity
)) {
160 newElements
= IONew( IORangeAllocatorElement
, newCapacity
);
168 index
* sizeof(IORangeAllocatorElement
));
169 bcopy( elements
+ index
,
170 newElements
+ index
+ 1,
171 (numElements
- index
) * sizeof(IORangeAllocatorElement
));
173 IODelete( elements
, IORangeAllocatorElement
, capacity
);
176 elements
= newElements
;
177 capacity
= newCapacity
;
179 bcopy( elements
+ index
,
180 elements
+ index
+ 1,
181 (numElements
- index
) * sizeof(IORangeAllocatorElement
));
188 // destroy element at index
190 IORangeAllocator::deallocElement( UInt32 index
)
193 bcopy( elements
+ index
+ 1,
195 (numElements
- index
) * sizeof(IORangeAllocatorElement
));
199 IORangeAllocator::allocate( IORangeScalar size
,
200 IORangeScalar
* result
,
201 IORangeScalar alignment
)
203 IORangeScalar data
, dataEnd
;
204 IORangeScalar thisStart
, thisEnd
;
208 if (!size
|| !result
) {
212 if (0 == alignment
) {
213 alignment
= defaultAlignmentMask
;
218 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
222 for (index
= 0; index
< numElements
; index
++) {
223 thisStart
= elements
[index
].start
;
224 thisEnd
= elements
[index
].end
;
225 data
= (thisStart
+ alignment
) & ~alignment
;
226 dataEnd
= (data
+ size
- 1);
228 ok
= (dataEnd
<= thisEnd
);
230 if (data
!= thisStart
) {
231 if (dataEnd
!= thisEnd
) {
232 if (allocElement( index
+ 1 )) {
233 elements
[index
++].end
= data
- 1;
234 elements
[index
].start
= dataEnd
+ 1;
235 elements
[index
].end
= thisEnd
;
240 elements
[index
].end
= data
- 1;
243 if (dataEnd
!= thisEnd
) {
244 elements
[index
].start
= dataEnd
+ 1;
246 deallocElement( index
);
262 IORangeAllocator::allocateRange( IORangeScalar data
,
265 IORangeScalar thisStart
, thisEnd
;
266 IORangeScalar dataEnd
;
274 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
275 dataEnd
= data
+ size
- 1;
280 (!found
) && (index
< numElements
);
282 thisStart
= elements
[index
].start
;
283 thisEnd
= elements
[index
].end
;
285 if (thisStart
> data
) {
288 found
= (dataEnd
<= thisEnd
);
291 if (data
!= thisStart
) {
292 if (dataEnd
!= thisEnd
) {
293 found
= allocElement( index
+ 1 );
295 elements
[index
++].end
= data
- 1;
296 elements
[index
].start
= dataEnd
+ 1;
297 elements
[index
].end
= thisEnd
;
300 elements
[index
].end
= data
- 1;
302 } else if (dataEnd
!= thisEnd
) {
303 elements
[index
].start
= dataEnd
+ 1;
305 deallocElement( index
);
316 IORangeAllocator::deallocate( IORangeScalar data
,
319 IORangeScalar dataEnd
;
321 bool headContig
= false;
322 bool tailContig
= false;
324 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
325 dataEnd
= data
+ size
- 1;
329 for (index
= 0; index
< numElements
; index
++) {
330 if (elements
[index
].start
< data
) {
331 headContig
= (data
<= (elements
[index
].end
+ 1));
334 tailContig
= ((data
+ size
) >= elements
[index
].start
);
340 elements
[index
- 1].end
= elements
[index
].end
;
341 deallocElement( index
);
342 } else /*safe*/ if (dataEnd
> elements
[index
- 1].end
) {
343 elements
[index
- 1].end
= dataEnd
;
345 } else if (tailContig
) {
346 if (data
< elements
[index
].start
) { /*safe*/
347 elements
[index
].start
= data
;
349 } else if (allocElement( index
)) {
350 elements
[index
].start
= data
;
351 elements
[index
].end
= dataEnd
;
358 IORangeAllocator::serialize(OSSerialize
*s
) const
360 OSArray
* array
= OSArray::withCapacity( numElements
* 2 );
371 for (index
= 0; index
< numElements
; index
++) {
372 if ((num
= OSNumber::withNumber( elements
[index
].start
,
373 8 * sizeof(IORangeScalar
)))) {
374 array
->setObject(num
);
377 if ((num
= OSNumber::withNumber( elements
[index
].end
,
378 8 * sizeof(IORangeScalar
)))) {
379 array
->setObject(num
);
386 ret
= array
->serialize(s
);
393 IORangeAllocator::getFreeCount( void )
396 IORangeScalar sum
= 0;
398 for (index
= 0; index
< numElements
; index
++) {
399 sum
+= elements
[index
].end
- elements
[index
].start
+ 1;