patch for .samba-2.0.7/source/lib/bitmap.c
Kenichi Okuyama
okuyamak at dd.iij4u.or.jp
Tue May 2 01:23:05 GMT 2000
Dear all,
I have made patch for
samba-2.0.7/source/lib/bitmap.c
With this patch
1) constant '32' is now named.
2) make only one malloc on bitmap_allocate().
( This will make bitmap to fit within same page, which will cause
lesser pagefault, I wish )
3) totally changed bitmap_find(). I guess this should work faster
then testing each bits one-by-one.
--- ./source/lib/bitmap.c 2000/04/29 15:35:49 1.1
+++ ./source/lib/bitmap.c 2000/05/01 09:00:59
@@ -21,35 +21,42 @@
#include "includes.h"
extern int DEBUGLEVEL;
+#define BITMAP_ALIGN 32
+#define UINT32_BITS 32
+#define UINT32_ALLONE (0xffffffffUL)
+
/* these functions provide a simple way to allocate integers from a
pool without repitition */
+static int find_bitmap_one( uint32 bitmaps );
+
+
/****************************************************************************
allocate a bitmap of the specified size
****************************************************************************/
struct bitmap *bitmap_allocate(int n)
{
- struct bitmap *bm;
+ size_t structsize, bitmapsize;
+ struct bitmap *bm;
- bm = (struct bitmap *)malloc(sizeof(*bm));
+ structsize = ( sizeof(*bm) + BITMAP_ALIGN - 1 )&( ~( BITMAP_ALIGN - 1));
+ bitmapsize = ( sizeof( bm->b[0] ) * ( n + UINT32_BITS-1 )/ UINT32_BITS );
- if (!bm) return NULL;
-
- bm->n = n;
- bm->b = (uint32 *)malloc(sizeof(bm->b[0])*(n+31)/32);
- if (!bm->b) {
- free(bm);
- return NULL;
- }
+ bm = (struct bitmap *)malloc( structsize + bitmapsize );
+ if (!bm) {
+ return NULL;
+ }
- memset(bm->b, 0, sizeof(bm->b[0])*(n+31)/32);
+ bm->n = n;
+ bm->b = (uint32 *)((char *)bm + structsize);
- return bm;
+ memset( bm->b, 0, bitmapsize );
+ return bm;
}
/****************************************************************************
set a bit in a bitmap
****************************************************************************/
@@ -58,11 +65,11 @@
if (i >= bm->n) {
DEBUG(0,("Setting invalid bitmap entry %d (of %d)\n",
i, bm->n));
return False;
}
- bm->b[i/32] |= (1<<(i%32));
+ bm->b[i/UINT32_BITS] |= (1<<(i%UINT32_BITS));
return True;
}
/****************************************************************************
clear a bit in a bitmap
@@ -72,21 +79,21 @@
if (i >= bm->n) {
DEBUG(0,("clearing invalid bitmap entry %d (of %d)\n",
i, bm->n));
return False;
}
- bm->b[i/32] &= ~(1<<(i%32));
+ bm->b[i/UINT32_BITS] &= ~(1<<(i%UINT32_BITS));
return True;
}
/****************************************************************************
query a bit in a bitmap
****************************************************************************/
BOOL bitmap_query(struct bitmap *bm, unsigned i)
{
if (i >= bm->n) return False;
- if (bm->b[i/32] & (1<<(i%32))) {
+ if (bm->b[i/UINT32_BITS] & (1<<(i%UINT32_BITS))) {
return True;
}
return False;
}
@@ -94,37 +101,109 @@
find a zero bit in a bitmap starting at the specified offset, with
wraparound
****************************************************************************/
int bitmap_find(struct bitmap *bm, unsigned ofs)
{
- int i, j;
+ uint32 ofs_negimage;
+ uint32 cur_negimage;
+ int ofsseg, ofsoff;
+ int iseg;
+ int result;
+
+ if ( ofs >= bm->n ) {
+ ofs = 0;
+ }
+
+ ofsseg = ofs / UINT32_BITS;
+ ofsoff = ofs % UINT32_BITS;
+
+ /* first, we have to treat first segment special */
+ ofs_negimage = ( ~( bm->b[ofsseg] ));
+
+ cur_negimage = ofs_negimage & ( UINT32_ALLONE << ofsoff );
+ ofs_negimage = ofs_negimage & ( ~( UINT32_ALLONE << ofsoff ));
+
+ result = find_bitmap_one( cur_negimage );
+ if ( result >= 0 ) {
+ if ( result + ( ofsseg * UINT32_BITS ) < bm->n ) {
+ return result + ( ofsseg * UINT32_BITS );
+ }
+ }
+
+ for ( iseg = ofsseg+1;
+ iseg < (( bm->n + UINT32_BITS - 1) / UINT32_BITS ); iseg++ ) {
+ result = find_bitmap_one( ~(bm->b[iseg]) );
+ if ( result >= 0 ) {
+
+ /* This is bit special case. you might be over-running */
+ if ( result + ( iseg * UINT32_BITS ) < bm->n ) {
+ return result + ( iseg * UINT32_BITS );
+ }
+ }
+ }
+
+ for ( iseg = 0; iseg < ofsseg; iseg++ ) {
+ result = find_bitmap_one( ~(bm->b[iseg]) );
+ if ( result >= 0 ) {
+ return result + ( iseg * UINT32_BITS );
+ }
+ }
+
+ /* finally look at first segment again */
+ if ( ofs_negimage ) {
+ result = find_bitmap_one( ofs_negimage );
+ if ( result >= 0 ) {
+ return result + ( ofsseg * UINT32_BITS );
+ }
+ }
+
+ return -1;
+}
- if (ofs > bm->n) ofs = 0;
- i = ofs;
- while (i < bm->n) {
- if (~(bm->b[i/32])) {
- j = i;
- do {
- if (!bitmap_query(bm, j)) return j;
- j++;
- } while (j & 31 && j < bm->n);
- }
- i += 32;
- i &= ~31;
- }
+/*
+ * find bit with 1, from LSB.
+ *
+ * I first saw this hack at X11R3's source code. I don't know where it
+ * came from. --- Kenichi Okuyama.
+ */
+static int
+find_bitmap_one( uint32 bitmaps )
+{
+ uint32 only_lsb_is_one;
+ int result;
- i = 0;
- while (i < ofs) {
- if (~(bm->b[i/32])) {
- j = i;
- do {
- if (!bitmap_query(bm, j)) return j;
- j++;
- } while (j & 31 && j < bm->n);
- }
- i += 32;
- i &= ~31;
- }
+ /* Somebody, tell me if you know. Who first found this ? */
+ only_lsb_is_one = bitmaps & (( ~bitmaps )+ 1 );
+
+ if ( only_lsb_is_one ) {
+ result = 0;
- return -1;
+ if ( !( only_lsb_is_one & 0xffff )) {
+ result += 16;
+ only_lsb_is_one >>= 16;
+ }
+
+ if ( !( only_lsb_is_one & 0xff )) {
+ result += 8;
+ only_lsb_is_one >>= 8;
+ }
+
+ if ( !( only_lsb_is_one & 0xf )) {
+ result += 4;
+ only_lsb_is_one >>= 4;
+ }
+
+ if ( !( only_lsb_is_one & 0x3 )) {
+ result += 2;
+ only_lsb_is_one >>= 2;
+ }
+
+ if ( !( only_lsb_is_one & 0x1 )) {
+ result += 1;
+ only_lsb_is_one >>= 1;
+ }
+
+ return result;
+ }
+ return -1;
}
More information about the samba
mailing list