1 /* *****************************************************************************
2 * Copyright (c) 2007-2014 Alexis Naveros.
4 * Ecere Corporation has unlimited/unrestricted rights.
5 * *****************************************************************************/
13 #include "cpuconfig.h"
19 /* Friendlier to cache on SMP systems */
20 #define BP_BITMAP_PREWRITE_CHECK
25 If we don't have atomic instruction support somehow, we need a much better mutex locking mechanism!!
29 int mmBitMapInit( mmBitMap *bitmap, size_t entrycount, int initvalue )
31 size_t mapsize, index;
33 #ifdef MM_ATOMIC_SUPPORT
39 mapsize = ( entrycount + CPUCONF_LONG_BITS - 1 ) >> CPUCONF_LONG_BITSHIFT;
43 if( !( bitmap->map = malloc( mapsize * sizeof(mmAtomicL) ) ) )
46 bitmap->mapsize = mapsize;
47 bitmap->entrycount = entrycount;
50 value = ( initvalue & 0x1 ? ~0x0 : 0x0 );
51 #ifdef MM_ATOMIC_SUPPORT
52 for( index = 0 ; index < mapsize ; index++ )
53 mmAtomicWriteL( &map[index], value );
55 for( index = 0 ; index < mapsize ; index++ )
57 mtMutexInit( &bitmap->mutex );
63 void mmBitMapReset( mmBitMap *bitmap, int resetvalue )
67 #ifdef MM_ATOMIC_SUPPORT
74 value = ( resetvalue & 0x1 ? ~(long)0x0 : (long)0x0 );
75 #ifdef MM_ATOMIC_SUPPORT
76 for( index = 0 ; index < bitmap->mapsize ; index++ )
77 mmAtomicWriteL( &map[index], value );
79 for( index = 0 ; index < bitmap->mapsize ; index++ )
86 void mmBitMapResetRange( mmBitMap *bitmap, int minimumentrycount, int resetvalue )
88 size_t index, entrycount;
90 #ifdef MM_ATOMIC_SUPPORT
97 value = ( resetvalue & 0x1 ? ~(long)0x0 : (long)0x0 );
98 entrycount = ( minimumentrycount + CPUCONF_LONG_BITS - 1 ) >> CPUCONF_LONG_BITSHIFT;
99 #ifdef MM_ATOMIC_SUPPORT
100 for( index = 0 ; index < entrycount ; index++ )
101 mmAtomicWriteL( &map[index], value );
103 for( index = 0 ; index < entrycount ; index++ )
110 void mmBitMapFree( mmBitMap *bitmap )
115 #ifndef MM_ATOMIC_SUPPORT
116 mtMutexDestroy( &bitmap->mutex );
121 /* TODO: Yeah... That code was written in one go, maybe I should test if it's working fine, just in case? */
122 int mmBitMapFindSet( mmBitMap *bitmap, size_t entryindex, size_t entryindexlast, size_t *retentryindex )
125 size_t index, shift, shiftbase, shiftmax, indexlast, shiftlast;
127 if( !( bitmap->entrycount ) )
130 indexlast = entryindexlast >> CPUCONF_LONG_BITSHIFT;
131 shiftlast = entryindexlast & ( CPUCONF_LONG_BITS - 1 );
133 /* Leading bits search */
134 index = entryindex >> CPUCONF_LONG_BITSHIFT;
135 shiftbase = entryindex & ( CPUCONF_LONG_BITS - 1 );
136 #ifdef MM_ATOMIC_SUPPORT
137 value = mmAtomicReadL( &bitmap->map[index] );
139 mtMutexLock( &bitmap->mutex );
140 value = bitmap->map[index];
142 if( value != (unsigned long)0x0 )
144 shiftmax = CPUCONF_LONG_BITS-1;
145 if( ( index == indexlast ) && ( shiftlast > shiftbase ) )
146 shiftmax = shiftlast;
148 for( shift = shiftbase ; shift <= shiftmax ; shift++, value >>= 1 )
150 if( !( value & 0x1 ) )
152 entryindex = ( index << CPUCONF_LONG_BITSHIFT ) | shift;
153 if( entryindex >= bitmap->entrycount )
155 #ifndef MM_ATOMIC_SUPPORT
156 mtMutexUnlock( &bitmap->mutex );
158 *retentryindex = entryindex;
162 if( ( index == indexlast ) && ( shiftlast > shiftbase ) )
164 #ifndef MM_ATOMIC_SUPPORT
165 mtMutexUnlock( &bitmap->mutex );
173 index = ( index + 1 ) % bitmap->mapsize;
174 if( index == indexlast )
176 #ifdef MM_ATOMIC_SUPPORT
177 value = mmAtomicReadL( &bitmap->map[index] );
179 value = bitmap->map[index];
181 if( value != (unsigned long)0x0 )
183 for( shift = 0 ; ; shift++, value >>= 1 )
185 if( !( value & 0x1 ) )
187 entryindex = ( index << CPUCONF_LONG_BITSHIFT ) | shift;
188 if( entryindex >= bitmap->entrycount )
190 #ifndef MM_ATOMIC_SUPPORT
191 mtMutexUnlock( &bitmap->mutex );
193 *retentryindex = entryindex;
199 /* Trailing bits search */
200 shiftlast = entryindexlast & ( CPUCONF_LONG_BITS - 1 );
201 #ifdef MM_ATOMIC_SUPPORT
202 value = mmAtomicReadL( &bitmap->map[index] );
204 value = bitmap->map[index];
206 if( value != (unsigned long)0x0 )
208 for( shift = 0 ; shift < shiftlast ; shift++, value >>= 1 )
210 if( !( value & 0x1 ) )
212 entryindex = ( index << CPUCONF_LONG_BITSHIFT ) | shift;
213 if( entryindex >= bitmap->entrycount )
215 #ifndef MM_ATOMIC_SUPPORT
216 mtMutexUnlock( &bitmap->mutex );
218 *retentryindex = entryindex;
222 #ifndef MM_ATOMIC_SUPPORT
223 mtMutexUnlock( &bitmap->mutex );
229 int mmBitMapFindClear( mmBitMap *bitmap, size_t entryindex, size_t entryindexlast, size_t *retentryindex )
232 size_t index, shift, shiftbase, shiftmax, indexlast, shiftlast;
234 if( !( bitmap->entrycount ) )
237 indexlast = entryindexlast >> CPUCONF_LONG_BITSHIFT;
238 shiftlast = entryindexlast & ( CPUCONF_LONG_BITS - 1 );
240 /* Leading bits search */
241 index = entryindex >> CPUCONF_LONG_BITSHIFT;
242 shiftbase = entryindex & ( CPUCONF_LONG_BITS - 1 );
243 #ifdef MM_ATOMIC_SUPPORT
244 value = mmAtomicReadL( &bitmap->map[index] );
246 mtMutexLock( &bitmap->mutex );
247 value = bitmap->map[index];
249 if( value != ~(unsigned long)0x0 )
251 shiftmax = CPUCONF_LONG_BITS-1;
252 if( ( index == indexlast ) && ( shiftlast > shiftbase ) )
253 shiftmax = shiftlast;
255 for( shift = shiftbase ; shift <= shiftmax ; shift++, value >>= 1 )
259 entryindex = ( index << CPUCONF_LONG_BITSHIFT ) | shift;
260 if( entryindex >= bitmap->entrycount )
262 #ifndef MM_ATOMIC_SUPPORT
263 mtMutexUnlock( &bitmap->mutex );
265 *retentryindex = entryindex;
269 if( ( index == indexlast ) && ( shiftlast > shiftbase ) )
271 #ifndef MM_ATOMIC_SUPPORT
272 mtMutexUnlock( &bitmap->mutex );
280 index = ( index + 1 ) % bitmap->mapsize;
281 if( index == indexlast )
283 #ifdef MM_ATOMIC_SUPPORT
284 value = mmAtomicReadL( &bitmap->map[index] );
286 value = bitmap->map[index];
288 if( value != ~(unsigned long)0x0 )
290 for( shift = 0 ; ; shift++, value >>= 1 )
294 entryindex = ( index << CPUCONF_LONG_BITSHIFT ) | shift;
295 if( entryindex >= bitmap->entrycount )
297 #ifndef MM_ATOMIC_SUPPORT
298 mtMutexUnlock( &bitmap->mutex );
300 *retentryindex = entryindex;
306 /* Trailing bits search */
307 shiftlast = entryindexlast & ( CPUCONF_LONG_BITS - 1 );
308 #ifdef MM_ATOMIC_SUPPORT
309 value = mmAtomicReadL( &bitmap->map[index] );
311 value = bitmap->map[index];
313 if( value != ~(unsigned long)0x0 )
315 for( shift = 0 ; shift <= shiftlast ; shift++, value >>= 1 )
319 entryindex = ( index << CPUCONF_LONG_BITSHIFT ) | shift;
320 if( entryindex >= bitmap->entrycount )
322 #ifndef MM_ATOMIC_SUPPORT
323 mtMutexUnlock( &bitmap->mutex );
325 *retentryindex = entryindex;
329 #ifndef MM_ATOMIC_SUPPORT
330 mtMutexUnlock( &bitmap->mutex );