All of lore.kernel.org
 help / color / mirror / Atom feed
* What is the return value of test_bit() in <asm/bitops.h> on x86_64?
@ 2015-12-10  2:20 Le Tan
  2015-12-10  2:49 ` Le Tan
  0 siblings, 1 reply; 2+ messages in thread
From: Le Tan @ 2015-12-10  2:20 UTC (permalink / raw)
  To: kernelnewbies

Hi,
I was shocked when I found that `test_bit()` will return -1 or 0 to denote
whether a bit is set or not in a bitmap.
Looking at its implementation here:
```
static __always_inline int constant_test_bit(long nr, const volatile
unsigned long *addr)
{
        return ((1UL << (nr & (BITS_PER_LONG-1))) &
                (addr[nr >> _BITOPS_LONG_SHIFT])) != 0;
}

static inline int variable_test_bit(long nr, volatile const unsigned long
*addr)
{
        int oldbit;

        asm volatile("bt %2,%1\n\t"
                     "sbb %0,%0"
                     : "=r" (oldbit)
                     : "m" (*(unsigned long *)addr), "Ir" (nr));

        return oldbit;
}
```
The sbb instruction will let `det = dst - (src + CF)`. So it seems that
test_bit() will return -1 if a bit is set? And it seems to work that way in
my project.

However, when I wrote another toy function to test it, I saw that it will
return 1 for those bits set.
```
#define TEST_MAX_BITS 512

static void rr_unit_test(struct kvm_vcpu *vcpu)
{
static u64 counter = 0;
int ret;
DECLARE_BITMAP(test_map, TEST_MAX_BITS);
u64 nr;

if (vcpu->vcpu_id != 0)
return;
if (counter == 0) {
++counter;
bitmap_zero(test_map, TEST_MAX_BITS);
ret = test_bit(5, test_map);
printk(KERN_INFO "vcpu=%d ret=%d\n", vcpu->vcpu_id, ret);
set_bit(5, test_map);
ret = test_bit(5, test_map);
printk(KERN_INFO "vcpu=%d ret=%d\n", vcpu->vcpu_id, ret);
ret = test_bit(6, test_map);
printk(KERN_INFO "vcpu=%d ret=%d\n", vcpu->vcpu_id, ret);
ret = test_bit(512, test_map);
printk(KERN_INFO "vcpu=%d ret=%d\n", vcpu->vcpu_id, ret);
set_bit(512, test_map);
ret = test_bit(512, test_map);
printk(KERN_INFO "vcpu=%d ret=%d\n", vcpu->vcpu_id, ret);
nr = 448;
ret = test_bit(nr, test_map);
printk(KERN_INFO "vcpu=%d ret=%d\n", vcpu->vcpu_id, ret);
set_bit(nr, test_map);
ret = test_bit(nr, test_map);
printk(KERN_INFO "vcpu=%d ret=%d\n", vcpu->vcpu_id, ret);
}
}
```
So why will test_bit() behave differently?
Thanks very much!

Regards,
Le Tan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20151210/e240b51f/attachment.html 

^ permalink raw reply	[flat|nested] 2+ messages in thread

* What is the return value of test_bit() in <asm/bitops.h> on x86_64?
  2015-12-10  2:20 What is the return value of test_bit() in <asm/bitops.h> on x86_64? Le Tan
@ 2015-12-10  2:49 ` Le Tan
  0 siblings, 0 replies; 2+ messages in thread
From: Le Tan @ 2015-12-10  2:49 UTC (permalink / raw)
  To: kernelnewbies

Hi,

2015-12-10 10:20 GMT+08:00 Le Tan <tamlokveer@gmail.com>:
>
> Hi,
> I was shocked when I found that `test_bit()` will return -1 or 0 to denote whether a bit is set or not in a bitmap.
> Looking at its implementation here:
> ```
> static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr)
> {
>         return ((1UL << (nr & (BITS_PER_LONG-1))) &
>                 (addr[nr >> _BITOPS_LONG_SHIFT])) != 0;
> }
>
> static inline int variable_test_bit(long nr, volatile const unsigned long *addr)
> {
>         int oldbit;
>
>         asm volatile("bt %2,%1\n\t"
>                      "sbb %0,%0"
>                      : "=r" (oldbit)
>                      : "m" (*(unsigned long *)addr), "Ir" (nr));
>
>         return oldbit;
> }
> ```
> The sbb instruction will let `det = dst - (src + CF)`. So it seems that test_bit() will return -1 if a bit is set? And it seems to work that way in my project.
>
> However, when I wrote another toy function to test it, I saw that it will return 1 for those bits set.
> ```
> #define TEST_MAX_BITS 512
>
> static void rr_unit_test(struct kvm_vcpu *vcpu)
> {
> static u64 counter = 0;
> int ret;
> DECLARE_BITMAP(test_map, TEST_MAX_BITS);
> u64 nr;
>
> if (vcpu->vcpu_id != 0)
> return;
> if (counter == 0) {
> ++counter;
> bitmap_zero(test_map, TEST_MAX_BITS);
> ret = test_bit(5, test_map);
> printk(KERN_INFO "vcpu=%d ret=%d\n", vcpu->vcpu_id, ret);
> set_bit(5, test_map);
> ret = test_bit(5, test_map);
> printk(KERN_INFO "vcpu=%d ret=%d\n", vcpu->vcpu_id, ret);
> ret = test_bit(6, test_map);
> printk(KERN_INFO "vcpu=%d ret=%d\n", vcpu->vcpu_id, ret);
> ret = test_bit(512, test_map);
> printk(KERN_INFO "vcpu=%d ret=%d\n", vcpu->vcpu_id, ret);
> set_bit(512, test_map);
> ret = test_bit(512, test_map);
> printk(KERN_INFO "vcpu=%d ret=%d\n", vcpu->vcpu_id, ret);
> nr = 448;
> ret = test_bit(nr, test_map);
> printk(KERN_INFO "vcpu=%d ret=%d\n", vcpu->vcpu_id, ret);
> set_bit(nr, test_map);
> ret = test_bit(nr, test_map);
> printk(KERN_INFO "vcpu=%d ret=%d\n", vcpu->vcpu_id, ret);
> }
> }
> ```
> So why will test_bit() behave differently?
> Thanks very much!
>
> Regards,
> Le Tan

Sorry for my being careless. Though I declared nr variable here, but
it is still __builtin_constant_p. So test_bit() will return -1 for
those nr which are not builtin constant, and return 1 on the other
case.
Sorry for my disturbance! :)

Regards,
Le

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-12-10  2:49 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-10  2:20 What is the return value of test_bit() in <asm/bitops.h> on x86_64? Le Tan
2015-12-10  2:49 ` Le Tan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.