mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* surpring results of test_and_set_bit() and test_and_clear_bit()  functions in Linux-2.6.25 kernel at x86_64 architecture
       [not found] <2ab84cd80906170340w3ad8b938t64b6d0926b18daa4@mail.gmail.com>
@ 2009-06-17 10:42 ` qingbo yuan
  2009-06-29 13:27   ` Petr Tesarik
  0 siblings, 1 reply; 2+ messages in thread
From: qingbo yuan @ 2009-06-17 10:42 UTC (permalink / raw)
  To: linux-kernel

hi,all
I recently encountered a strange phenomenon about test_and_set_bit()
and test_and_clear_bit().
Here are the comments about these functions in Linux-2.6.25 kernel at
x86_64 architecture:

/**
 * test_and_set_bit - Set a bit and return its old value
 */

/**
 * test_and_clear_bit - Clear a bit and return its old value
 */

According to the comments, if the old value is '0', then these
functions will return 0 to the caller, and
if the old value is '1', then these functions will return 1. However,
in my experiment, if the old value is '1', I got -1 instead of 1. Here
is the code:

void generos_test_bitmap(void)
{
 int cur,ret_clear,ret_set;
 unsigned long bitmap =0x3721;
 for(cur = find_first_bit(&bitmap,BITS_PER_LONG);cur <
BITS_PER_LONG;cur = find_next_bit(&bitmap, BITS_PER_LONG, cur + 1)){
  ret_clear  = test_and_set_bit(cur, &bitmap);
  ret_set  = test_and_clear_bit(cur, &bitmap);
  printk("test_and_set bit [%d] ret [%d]\n",cur,ret_set);
  printk("test_and_clear bit [%d] ret [%d]\n\n\n",cur,ret_clear);
 }
}

And here is the results:
test_and_set bit [0] ret [-1]
test_and_clear bit [0] ret [-1]
test_and_set bit [5] ret [-1]
test_and_clear bit [5] ret [-1]
test_and_set bit [8] ret [-1]
test_and_clear bit [8] ret [-1]
test_and_set bit [9] ret [-1]
test_and_clear bit [9] ret [-1]
test_and_set bit [10] ret [-1]
test_and_clear bit [10] ret [-1]
test_and_set bit [12] ret [-1]
test_and_clear bit [12] ret [-1]
test_and_set bit [13] ret [-1]
test_and_clear bit [13] ret [-1]

Interesting! Let's take a look at the definition of these funtions in
Linux-2.6.25:
 static inline int test_and_set_bit(int nr, volatile void *addr)
{
 int oldbit;
 asm volatile(LOCK_PREFIX "bts %2,%1\n\t"
       "sbb %0,%0"
       : "=r" (oldbit), ADDR
       : "Ir" (nr) : "memory");
 return oldbit;
}

static inline int test_and_clear_bit(int nr, volatile void *addr)
{
 int oldbit;
 asm volatile(LOCK_PREFIX "btr %2,%1\n\t"
       "sbb %0,%0"
       : "=r" (oldbit), ADDR
       : "Ir" (nr) : "memory");
 return oldbit;
}

1. bts and btr set/clear the bit and copy the old value to CF flag.
2. sbb %0,%0 equals (%0-(%0+CF)) -> %0
3. %0 -> oldbit

So, if the old bit is '0', these functions return 0;
      if the old bit is '1', these functions return -1;
Both of these functions were right if the comments modified as
"test_and_set_bit - Set a bit and return its opposite old value".

Can anybody point out what problems exist in my analysis?

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

* Re: surpring results of test_and_set_bit() and test_and_clear_bit() functions in Linux-2.6.25 kernel at x86_64 architecture
  2009-06-17 10:42 ` surpring results of test_and_set_bit() and test_and_clear_bit() functions in Linux-2.6.25 kernel at x86_64 architecture qingbo yuan
@ 2009-06-29 13:27   ` Petr Tesarik
  0 siblings, 0 replies; 2+ messages in thread
From: Petr Tesarik @ 2009-06-29 13:27 UTC (permalink / raw)
  To: qingbo yuan; +Cc: linux-kernel

qingbo yuan píše v St 17. 06. 2009 v 18:42 +0800:
> hi,all
> I recently encountered a strange phenomenon about test_and_set_bit()
> and test_and_clear_bit().
> [...]
> So, if the old bit is '0', these functions return 0;
>       if the old bit is '1', these functions return -1;
> Both of these functions were right if the comments modified as
> "test_and_set_bit - Set a bit and return its opposite old value".
> 
> Can anybody point out what problems exist in my analysis?

None. Just, the intended return type of those functions is actually
bool, I think, so it doesn't matter if they return 1 or -1. Any non-zero
value will do.

OTOH choosing the word "opposite" is probably unfortunate, because most
people would have difficulties understanding what the function really
returns.

And while we're at nitpicking, what makes you think that a single bit
integer must be an unsigned int? If I look at one bit as a signed int,
then it can hold the values 0 and -1. The test_and_*_bit() merely
sign-extend the bit...

Petr Tesarik


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

end of thread, other threads:[~2009-06-29 13:28 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <2ab84cd80906170340w3ad8b938t64b6d0926b18daa4@mail.gmail.com>
2009-06-17 10:42 ` surpring results of test_and_set_bit() and test_and_clear_bit() functions in Linux-2.6.25 kernel at x86_64 architecture qingbo yuan
2009-06-29 13:27   ` Petr Tesarik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®