2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1999 Apple Computer, Inc.
28 * sdouglas 05 Nov 99 - created.
31 #include <libkern/c++/OSArray.h>
32 #include <libkern/c++/OSNumber.h>
33 #include <IOKit/IORangeAllocator.h>
34 #include <IOKit/IOLib.h>
35 #include <IOKit/IOLocks.h>
36 #include <IOKit/assert.h>
38 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
41 #define super OSObject
43 OSDefineMetaClassAndStructors( IORangeAllocator
, OSObject
)
45 struct IORangeAllocatorElement
{
51 IOLock
* gIORangeAllocatorLock
;
54 if( options & kLocking) IOTakeLock( gIORangeAllocatorLock )
56 if( options & kLocking) IOUnlock( gIORangeAllocatorLock )
58 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
60 bool IORangeAllocator::init( IORangeScalar endOfRange
,
61 IORangeScalar _defaultAlignment
,
63 IOOptionBits _options
)
70 if( !_defaultAlignment
)
71 _defaultAlignment
= 1;
73 capacityIncrement
= _capacity
;
76 defaultAlignmentMask
= _defaultAlignment
- 1;
79 if( (!gIORangeAllocatorLock
) && (options
& kLocking
))
80 gIORangeAllocatorLock
= IOLockAlloc();
83 deallocate( 0, endOfRange
+ 1 );
88 IORangeAllocator
* IORangeAllocator:: withRange(
89 IORangeScalar endOfRange
,
90 IORangeScalar defaultAlignment
= 0,
92 IOOptionBits options
= 0 )
94 IORangeAllocator
* thingy
;
96 thingy
= new IORangeAllocator
;
97 if( thingy
&& ! thingy
->init( endOfRange
, defaultAlignment
,
98 capacity
, options
)) {
106 void IORangeAllocator::free()
109 IODelete( elements
, IORangeAllocatorElement
, capacity
);
114 UInt32
IORangeAllocator::getFragmentCount( void )
116 return( numElements
);
119 UInt32
IORangeAllocator::getFragmentCapacity( void )
124 void IORangeAllocator::setFragmentCapacityIncrement( UInt32 count
)
126 capacityIncrement
= count
;
130 // allocate element at index
131 bool IORangeAllocator::allocElement( UInt32 index
)
134 IORangeAllocatorElement
* newElements
;
136 if( ((numElements
== capacity
) && capacityIncrement
)
139 newCapacity
= capacity
+ capacityIncrement
;
140 newElements
= IONew( IORangeAllocatorElement
, newCapacity
);
147 index
* sizeof( IORangeAllocatorElement
));
148 bcopy( elements
+ index
,
149 newElements
+ index
+ 1,
150 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
152 IODelete( elements
, IORangeAllocatorElement
, capacity
);
155 elements
= newElements
;
156 capacity
= newCapacity
;
160 bcopy( elements
+ index
,
161 elements
+ index
+ 1,
162 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
169 // destroy element at index
170 void IORangeAllocator::deallocElement( UInt32 index
)
173 bcopy( elements
+ index
+ 1,
175 (numElements
- index
) * sizeof( IORangeAllocatorElement
));
178 bool IORangeAllocator::allocate( IORangeScalar size
,
179 IORangeScalar
* result
,
180 IORangeScalar alignment
= 0 )
182 IORangeScalar data
, dataEnd
;
183 IORangeScalar thisStart
, thisEnd
;
187 if( !size
|| !result
)
191 alignment
= defaultAlignmentMask
;
195 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
199 for( index
= 0; index
< numElements
; index
++ ) {
201 thisStart
= elements
[index
].start
;
202 thisEnd
= elements
[index
].end
;
203 data
= (thisStart
+ alignment
) & ~alignment
;
204 dataEnd
= (data
+ size
- 1);
206 ok
= (dataEnd
<= thisEnd
);
208 if( data
!= thisStart
) {
209 if( dataEnd
!= thisEnd
) {
210 if( allocElement( index
+ 1 )) {
211 elements
[index
++].end
= data
- 1;
212 elements
[index
].start
= dataEnd
+ 1;
213 elements
[index
].end
= thisEnd
;
217 elements
[index
].end
= data
- 1;
219 if( dataEnd
!= thisEnd
)
220 elements
[index
].start
= dataEnd
+ 1;
222 deallocElement( index
);
235 bool IORangeAllocator::allocateRange( IORangeScalar data
,
238 IORangeScalar thisStart
, thisEnd
;
239 IORangeScalar dataEnd
;
246 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
247 dataEnd
= data
+ size
- 1;
252 (!found
) && (index
< numElements
);
255 thisStart
= elements
[index
].start
;
256 thisEnd
= elements
[index
].end
;
258 if( thisStart
> data
)
260 found
= (dataEnd
<= thisEnd
);
263 if( data
!= thisStart
) {
264 if( dataEnd
!= thisEnd
) {
265 found
= allocElement( index
+ 1 );
267 elements
[index
++].end
= data
- 1;
268 elements
[index
].start
= dataEnd
+ 1;
269 elements
[index
].end
= thisEnd
;
272 elements
[index
].end
= data
- 1;
273 } else if( dataEnd
!= thisEnd
)
274 elements
[index
].start
= dataEnd
+ 1;
276 deallocElement( index
);
285 void IORangeAllocator::deallocate( IORangeScalar data
,
288 IORangeScalar dataEnd
;
290 bool headContig
= false;
291 bool tailContig
= false;
293 size
= (size
+ defaultAlignmentMask
) & ~defaultAlignmentMask
;
294 dataEnd
= data
+ size
- 1;
298 for( index
= 0; index
< numElements
; index
++ ) {
299 if( elements
[index
].start
< data
) {
300 headContig
= (data
<= (elements
[index
].end
+ 1));
303 tailContig
= ((data
+ size
) >= elements
[index
].start
);
309 elements
[index
-1].end
= elements
[index
].end
;
310 deallocElement( index
);
311 } else /*safe*/ if( dataEnd
> elements
[index
-1].end
)
312 elements
[index
-1].end
= dataEnd
;
314 } else if( tailContig
) {
315 if( data
< elements
[index
].start
) /*safe*/
316 elements
[index
].start
= data
;
318 } else if( allocElement( index
)) {
319 elements
[index
].start
= data
;
320 elements
[index
].end
= dataEnd
;
326 bool IORangeAllocator::serialize(OSSerialize
*s
) const
328 OSArray
* array
= OSArray::withCapacity( numElements
* 2 );
338 for( index
= 0; index
< numElements
; index
++) {
339 if( (num
= OSNumber::withNumber( elements
[index
].start
,
340 8 * sizeof(IORangeScalar
) ))) {
341 array
->setObject(num
);
344 if( (num
= OSNumber::withNumber( elements
[index
].end
,
345 8 * sizeof(IORangeScalar
) ))) {
346 array
->setObject(num
);
353 ret
= array
->serialize(s
);
359 IORangeScalar
IORangeAllocator::getFreeCount( void )
362 IORangeScalar sum
= 0;
364 for( index
= 0; index
< numElements
; index
++)
365 sum
+= elements
[index
].end
- elements
[index
].start
+ 1;