1 /* *****************************************************************************
2 * Copyright (c) 2007-2014 Alexis Naveros.
4 * Ecere Corporation has unlimited/unrestricted rights.
5 * *****************************************************************************/
9 #if !defined(CPUCONF_LONG_BITSHIFT) || !defined(CPUCONF_LONG_BITS)
10 #error Preprocessor symbols CPUCONF_LONG_BITSHIFT and CPUCONF_LONG_BITS are undefined!
11 #error This header requires cpuconfig.h
14 #if !defined(MM_ATOMIC_SUPPORT)
15 #warning Compiling mmbitmap without atomic support, it is going to be SLOW.
16 #warning This header requires mm.h
24 #ifdef MM_ATOMIC_SUPPORT
32 int mmBitMapInit( mmBitMap *bitmap, size_t entrycount, int initvalue );
33 void mmBitMapReset( mmBitMap *bitmap, int resetvalue );
34 void mmBitMapResetRange( mmBitMap *bitmap, int minimumentrycount, int resetvalue );
35 void mmBitMapFree( mmBitMap *bitmap );
37 int mmBitMapFindSet( mmBitMap *bitmap, size_t entryindex, size_t entryindexlast, size_t *retentryindex );
38 int mmBitMapFindClear( mmBitMap *bitmap, size_t entryindex, size_t entryindexlast, size_t *retentryindex );
44 /* No atomic locking, single-threaded access */
46 static inline int mmBitMapDirectGet( mmBitMap *bitmap, size_t entryindex )
50 index = entryindex >> CPUCONF_LONG_BITSHIFT;
51 shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
52 #ifdef MM_ATOMIC_SUPPORT
53 value = (int)(( MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) >> shift ) & 0x1);
55 value = ( bitmap->map[index] >> shift ) & 0x1;
60 static inline void mmBitMapDirectSet( mmBitMap *bitmap, size_t entryindex )
63 index = entryindex >> CPUCONF_LONG_BITSHIFT;
64 shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
65 #ifdef MM_ATOMIC_SUPPORT
66 MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) |= (long)1 << shift;
68 bitmap->map[index] |= (long)1 << shift;
73 static inline void mmBitMapDirectClear( mmBitMap *bitmap, size_t entryindex )
76 index = entryindex >> CPUCONF_LONG_BITSHIFT;
77 shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
78 #ifdef MM_ATOMIC_SUPPORT
79 MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) &= ~( (long)1 << shift );
81 bitmap->map[index] &= ~( (long)1 << shift );
86 static inline int mmBitMapDirectMaskGet( mmBitMap *bitmap, size_t entryindex, long mask )
90 index = entryindex >> CPUCONF_LONG_BITSHIFT;
91 shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
92 #ifdef MM_ATOMIC_SUPPORT
93 value = (int)(( MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) >> shift ) & mask);
95 value = ( bitmap->map[index] >> shift ) & mask;
100 static inline void mmBitMapDirectMaskSet( mmBitMap *bitmap, size_t entryindex, long value, long mask )
103 index = entryindex >> CPUCONF_LONG_BITSHIFT;
104 shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
105 #ifdef MM_ATOMIC_SUPPORT
106 MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) = ( MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) & ~( mask << shift ) ) | ( value << shift );
108 bitmap->map[index] = ( bitmap->map[index] & ~( mask << shift ) ) | ( value << shift );
117 /* Atomic locking, multi-threaded access */
119 static inline int mmBitMapGet( mmBitMap *bitmap, size_t entryindex )
123 index = entryindex >> CPUCONF_LONG_BITSHIFT;
124 shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
125 #ifdef MM_ATOMIC_SUPPORT
126 value = (int)(( mmAtomicReadL( &bitmap->map[index] ) >> shift ) & 0x1);
128 mtMutexLock( &bitmap->mutex );
129 value = ( bitmap->map[index] >> shift ) & 0x1;
130 mtMutexUnlock( &bitmap->mutex );
135 static inline void mmBitMapSet( mmBitMap *bitmap, size_t entryindex )
138 index = entryindex >> CPUCONF_LONG_BITSHIFT;
139 shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
140 #ifdef MM_ATOMIC_SUPPORT
141 #ifdef BP_BITMAP_PREWRITE_CHECK
142 if( !( mmAtomicReadL( &bitmap->map[index] ) & ( (long)1 << shift ) ) )
143 mmAtomicOrL( &bitmap->map[index], (long)1 << shift );
145 mmAtomicOrL( &bitmap->map[index], (long)1 << shift );
148 mtMutexLock( &bitmap->mutex );
149 bitmap->map[index] |= (long)1 << shift;
150 mtMutexUnlock( &bitmap->mutex );
155 static inline void mmBitMapClear( mmBitMap *bitmap, size_t entryindex )
158 index = entryindex >> CPUCONF_LONG_BITSHIFT;
159 shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
160 #ifdef MM_ATOMIC_SUPPORT
161 #ifdef BP_BITMAP_PREWRITE_CHECK
162 if( mmAtomicReadL( &bitmap->map[index] ) & ( (long)1 << shift ) )
163 mmAtomicAndL( &bitmap->map[index], ~( (long)1 << shift ) );
165 mmAtomicAndL( &bitmap->map[index], ~( (long)1 << shift ) );
168 mtMutexLock( &bitmap->mutex );
169 bitmap->map[index] &= ~( (long)1 << shift );
170 mtMutexUnlock( &bitmap->mutex );
175 static inline int mmBitMapMaskGet( mmBitMap *bitmap, size_t entryindex, long mask )
179 index = entryindex >> CPUCONF_LONG_BITSHIFT;
180 shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
181 #ifdef MM_ATOMIC_SUPPORT
182 value = (int)(( mmAtomicReadL( &bitmap->map[index] ) >> shift ) & mask);
184 mtMutexLock( &bitmap->mutex );
185 value = ( bitmap->map[index] >> shift ) & mask;
186 mtMutexUnlock( &bitmap->mutex );
191 static inline void mmBitMapMaskSet( mmBitMap *bitmap, size_t entryindex, long value, long mask )
194 long oldvalue, newvalue;
195 index = entryindex >> CPUCONF_LONG_BITSHIFT;
196 shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
197 #ifdef MM_ATOMIC_SUPPORT
200 oldvalue = (int)mmAtomicReadL( &bitmap->map[index] );
201 newvalue = ( oldvalue & ~( mask << shift ) ) | ( value << shift );
202 if( mmAtomicCmpReplaceL( &bitmap->map[index], oldvalue, newvalue ) )
206 mtMutexLock( &bitmap->mutex );
207 bitmap->map[index] = ( bitmap->map[index] & ~( mask << shift ) ) | ( value << shift );
208 mtMutexUnlock( &bitmap->mutex );