2 * bitext.c: kernel little helper (of bit shuffling variety).
4 * Copyright (C) 2002 Pete Zaitcev <zaitcev@yahoo.com>
6 * The algorithm to search a zero bit string is geared towards its application.
7 * We expect a couple of fixed sizes of requests, so a rotating counter, reset
8 * by align size, should provide fast enough search while maintaining low
12 #include <linux/string.h>
13 #include <linux/bitmap.h>
15 #include <asm/bitext.h>
18 * bit_map_string_get - find and set a bit string in bit map.
20 * @len: requested string length
21 * @align: requested alignment
23 * Returns offset in the map or -1 if out of space.
25 * Not safe to call from an interrupt (uses spin_lock).
27 int bit_map_string_get(struct bit_map
*t
, int len
, int align
)
29 int offset
, count
; /* siamese twins */
35 /* align is overloaded to be the page color */
37 align
= t
->num_colors
;
44 if ((align
& align1
) != 0)
46 if (align
< 0 || align
>= t
->size
)
48 if (len
<= 0 || len
> t
->size
)
53 if (len
< t
->last_size
)
54 offset
= t
->first_free
;
56 offset
= t
->last_off
& ~align1
;
59 off_new
= find_next_zero_bit(t
->map
, t
->size
, offset
);
60 off_new
= ((off_new
+ align1
) & ~align1
) + color
;
61 count
+= off_new
- offset
;
63 if (offset
>= t
->size
)
65 if (count
+ len
> t
->size
) {
66 spin_unlock(&t
->lock
);
67 /* P3 */ printk(KERN_ERR
68 "bitmap out: size %d used %d off %d len %d align %d count %d\n",
69 t
->size
, t
->used
, offset
, len
, align
, count
);
73 if (offset
+ len
> t
->size
) {
74 count
+= t
->size
- offset
;
80 while (test_bit(offset
+ i
, t
->map
) == 0) {
83 bitmap_set(t
->map
, offset
, len
);
84 if (offset
== t
->first_free
)
85 t
->first_free
= find_next_zero_bit
88 if ((t
->last_off
= offset
+ len
) >= t
->size
)
92 spin_unlock(&t
->lock
);
97 if ((offset
+= i
+ 1) >= t
->size
)
102 void bit_map_clear(struct bit_map
*t
, int offset
, int len
)
107 BUG(); /* Much too late to do any good, but alas... */
109 for (i
= 0; i
< len
; i
++) {
110 if (test_bit(offset
+ i
, t
->map
) == 0)
112 __clear_bit(offset
+ i
, t
->map
);
114 if (offset
< t
->first_free
)
115 t
->first_free
= offset
;
117 spin_unlock(&t
->lock
);
120 void bit_map_init(struct bit_map
*t
, unsigned long *map
, int size
)
123 if ((size
& 07) != 0)
125 memset(map
, 0, size
>>3);
127 memset(t
, 0, sizeof *t
);
128 spin_lock_init(&t
->lock
);