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 newCapacity
= capacity
+ capacityIncrement
;
146 newElements
= IONew( IORangeAllocatorElement
, newCapacity
);
153 index
* sizeof( IORangeAllocatorElement
));
154 bcopy( elements
+ index
,
155 newElements
+ index
+ 1,
156 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
158 IODelete( elements
, IORangeAllocatorElement
, capacity
);
161 elements
= newElements
;
162 capacity
= newCapacity
;
166 bcopy( elements
+ index
,
167 elements
+ index
+ 1,
168 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
175 // destroy element at index
176 void IORangeAllocator::deallocElement( UInt32 index
)
179 bcopy( elements
+ index
+ 1,
181 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
184 bool IORangeAllocator::allocate( IORangeScalar size
,
185 IORangeScalar
* result
,
186 IORangeScalar alignment
)
188 IORangeScalar data
, dataEnd
;
189 IORangeScalar thisStart
, thisEnd
;
193 if( !size
|| !result
)
197 alignment
= defaultAlignmentMask
;
201 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
205 for( index
= 0; index
< numElements
; index
++ ) {
207 thisStart
= elements
[index
].start
;
208 thisEnd
= elements
[index
].end
;
209 data
= (thisStart
+ alignment
) & ~alignment
;
210 dataEnd
= (data
+ size
- 1);
212 ok
= (dataEnd
<= thisEnd
);
214 if( data
!= thisStart
) {
215 if( dataEnd
!= thisEnd
) {
216 if( allocElement( index
+ 1 )) {
217 elements
[index
++].end
= data
- 1;
218 elements
[index
].start
= dataEnd
+ 1;
219 elements
[index
].end
= thisEnd
;
223 elements
[index
].end
= data
- 1;
225 if( dataEnd
!= thisEnd
)
226 elements
[index
].start
= dataEnd
+ 1;
228 deallocElement( index
);
241 bool IORangeAllocator::allocateRange( IORangeScalar data
,
244 IORangeScalar thisStart
, thisEnd
;
245 IORangeScalar dataEnd
;
252 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
253 dataEnd
= data
+ size
- 1;
258 (!found
) && (index
< numElements
);
261 thisStart
= elements
[index
].start
;
262 thisEnd
= elements
[index
].end
;
264 if( thisStart
> data
)
266 found
= (dataEnd
<= thisEnd
);
269 if( data
!= thisStart
) {
270 if( dataEnd
!= thisEnd
) {
271 found
= allocElement( index
+ 1 );
273 elements
[index
++].end
= data
- 1;
274 elements
[index
].start
= dataEnd
+ 1;
275 elements
[index
].end
= thisEnd
;
278 elements
[index
].end
= data
- 1;
279 } else if( dataEnd
!= thisEnd
)
280 elements
[index
].start
= dataEnd
+ 1;
282 deallocElement( index
);
291 void IORangeAllocator::deallocate( IORangeScalar data
,
294 IORangeScalar dataEnd
;
296 bool headContig
= false;
297 bool tailContig
= false;
299 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
300 dataEnd
= data
+ size
- 1;
304 for( index
= 0; index
< numElements
; index
++ ) {
305 if( elements
[index
].start
< data
) {
306 headContig
= (data
<= (elements
[index
].end
+ 1));
309 tailContig
= ((data
+ size
) >= elements
[index
].start
);
315 elements
[index
-1].end
= elements
[index
].end
;
316 deallocElement( index
);
317 } else /*safe*/ if( dataEnd
> elements
[index
-1].end
)
318 elements
[index
-1].end
= dataEnd
;
320 } else if( tailContig
) {
321 if( data
< elements
[index
].start
) /*safe*/
322 elements
[index
].start
= data
;
324 } else if( allocElement( index
)) {
325 elements
[index
].start
= data
;
326 elements
[index
].end
= dataEnd
;
332 bool IORangeAllocator::serialize(OSSerialize
*s
) const
334 OSArray
* array
= OSArray::withCapacity( numElements
* 2 );
344 for( index
= 0; index
< numElements
; index
++) {
345 if( (num
= OSNumber::withNumber( elements
[index
].start
,
346 8 * sizeof(IORangeScalar
) ))) {
347 array
->setObject(num
);
350 if( (num
= OSNumber::withNumber( elements
[index
].end
,
351 8 * sizeof(IORangeScalar
) ))) {
352 array
->setObject(num
);
359 ret
= array
->serialize(s
);
365 IORangeScalar
IORangeAllocator::getFreeCount( void )
368 IORangeScalar sum
= 0;
370 for( index
= 0; index
< numElements
; index
++)
371 sum
+= elements
[index
].end
- elements
[index
].start
+ 1;