Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1210947 > unrolled thread

Re: [PATCH] x86, bitops, variable_test_bit should return 1 not -1 on a match

Started byIngo Molnar <mingo@kernel.org>
First post2015-08-21 09:00 +0200
Last post2015-08-22 11:20 +0200
Articles 6 — 3 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: [PATCH] x86, bitops, variable_test_bit should return 1 not -1 on  a match Ingo Molnar <mingo@kernel.org> - 2015-08-21 09:00 +0200
    Re: [PATCH] x86, bitops, variable_test_bit should return 1 not -1 on a match "H. Peter Anvin" <hpa@zytor.com> - 2015-08-21 10:10 +0200
      Re: [PATCH] x86, bitops, variable_test_bit should return 1 not -1  on a match Prarit Bhargava <prarit@redhat.com> - 2015-08-21 14:00 +0200
      [PATCH v2] x86, bitops, variable_test_bit should return 1 not -1 on a match Prarit Bhargava <prarit@redhat.com> - 2015-08-24 20:30 +0200
    Re: [PATCH] x86, bitops, variable_test_bit should return 1 not -1  on a match Prarit Bhargava <prarit@redhat.com> - 2015-08-21 14:00 +0200
      Re: [PATCH] x86, bitops, variable_test_bit should return 1 not -1 on  a match Ingo Molnar <mingo@kernel.org> - 2015-08-22 11:20 +0200

#1210947 — Re: [PATCH] x86, bitops, variable_test_bit should return 1 not -1 on a match

FromIngo Molnar <mingo@kernel.org>
Date2015-08-21 09:00 +0200
SubjectRe: [PATCH] x86, bitops, variable_test_bit should return 1 not -1 on a match
Message-ID<pZOsW-4qZ-5@gated-at.bofh.it>
* Prarit Bhargava <prarit@redhat.com> wrote:

> This issue was noticed while debugging a CPU hotplug issue.  On x86
> with (NR_CPUS > 1) the cpu_online() define is cpumask_test_cpu().
> cpumask_test_cpu() should return 1 if the cpu is set in cpumask and
> 0 otherwise.
> 
> However, cpumask_test_cpu() returns -1 if the cpu in the cpumask is
> set and 0 otherwise.  This happens because cpumask_test_cpu() calls
> test_bit() which is a define that will call variable_test_bit().
> 
> variable_test_bit() calls the assembler instruction sbb (Subtract
> with Borrow, " Subtracts the source from the destination, and subtracts 1
> extra if the Carry Flag is set. Results are returned in "dest".)
> 
> A bit match results in -1 being returned from variable_test_bit() if a
> match occurs, not 1 as the function is supposed to.  This can be easily
> resolved by adding a "!!" to force 0 or 1 as a return.
> 
> It looks like the code never does, for example, (test_bit() == 1) so this
> change should not have any impact.
> 
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: x86@kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Prarit Bhargava <prarit@redhat.com>
> ---
>  arch/x86/include/asm/bitops.h |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
> index cfe3b95..a87a5fb 100644
> --- a/arch/x86/include/asm/bitops.h
> +++ b/arch/x86/include/asm/bitops.h
> @@ -320,7 +320,7 @@ static inline int variable_test_bit(long nr, volatile const unsigned long *addr)
>  		     : "=r" (oldbit)
>  		     : "m" (*(unsigned long *)addr), "Ir" (nr));
>  
> -	return oldbit;
> +	return !!oldbit;
>  }
>  
>  #if 0 /* Fool kernel-doc since it doesn't do macros yet */

Ok, I think this is a good fix to improve the robustness of this primitive, unless 
someone objects.

I tried to find the CPU hotplug code that broke with cpu_online() returning -1 but 
failed - all current mainline usage sites seem to be testing for nonzero in one 
way or another. Could you please point it out?

Thanks,

	Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1210990 — Re: [PATCH] x86, bitops, variable_test_bit should return 1 not -1 on a match

From"H. Peter Anvin" <hpa@zytor.com>
Date2015-08-21 10:10 +0200
SubjectRe: [PATCH] x86, bitops, variable_test_bit should return 1 not -1 on a match
Message-ID<pZPyG-6cu-3@gated-at.bofh.it>
In reply to#1210947
Wrong fix, though.  Instead we should change it to use the set instruction, which would also make it easier to use the CC_SET/CC_OUT proposed macros to use assembly out in the future.

The downside with set is that it only sets a single byte, the upside is that it always outputs 0 or 1, and apparently if the output variable is your bool gcc can use that for optimization.


On August 20, 2015 11:51:03 PM PDT, Ingo Molnar <mingo@kernel.org> wrote:
>
>* Prarit Bhargava <prarit@redhat.com> wrote:
>
>> This issue was noticed while debugging a CPU hotplug issue.  On x86
>> with (NR_CPUS > 1) the cpu_online() define is cpumask_test_cpu().
>> cpumask_test_cpu() should return 1 if the cpu is set in cpumask and
>> 0 otherwise.
>> 
>> However, cpumask_test_cpu() returns -1 if the cpu in the cpumask is
>> set and 0 otherwise.  This happens because cpumask_test_cpu() calls
>> test_bit() which is a define that will call variable_test_bit().
>> 
>> variable_test_bit() calls the assembler instruction sbb (Subtract
>> with Borrow, " Subtracts the source from the destination, and
>subtracts 1
>> extra if the Carry Flag is set. Results are returned in "dest".)
>> 
>> A bit match results in -1 being returned from variable_test_bit() if
>a
>> match occurs, not 1 as the function is supposed to.  This can be
>easily
>> resolved by adding a "!!" to force 0 or 1 as a return.
>> 
>> It looks like the code never does, for example, (test_bit() == 1) so
>this
>> change should not have any impact.
>> 
>> Cc: Thomas Gleixner <tglx@linutronix.de>
>> Cc: Ingo Molnar <mingo@redhat.com>
>> Cc: "H. Peter Anvin" <hpa@zytor.com>
>> Cc: x86@kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> Signed-off-by: Prarit Bhargava <prarit@redhat.com>
>> ---
>>  arch/x86/include/asm/bitops.h |    2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>> 
>> diff --git a/arch/x86/include/asm/bitops.h
>b/arch/x86/include/asm/bitops.h
>> index cfe3b95..a87a5fb 100644
>> --- a/arch/x86/include/asm/bitops.h
>> +++ b/arch/x86/include/asm/bitops.h
>> @@ -320,7 +320,7 @@ static inline int variable_test_bit(long nr,
>volatile const unsigned long *addr)
>>  		     : "=r" (oldbit)
>>  		     : "m" (*(unsigned long *)addr), "Ir" (nr));
>>  
>> -	return oldbit;
>> +	return !!oldbit;
>>  }
>>  
>>  #if 0 /* Fool kernel-doc since it doesn't do macros yet */
>
>Ok, I think this is a good fix to improve the robustness of this
>primitive, unless 
>someone objects.
>
>I tried to find the CPU hotplug code that broke with cpu_online()
>returning -1 but 
>failed - all current mainline usage sites seem to be testing for
>nonzero in one 
>way or another. Could you please point it out?
>
>Thanks,
>
>	Ingo

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1211125 — Re: [PATCH] x86, bitops, variable_test_bit should return 1 not -1 on a match

FromPrarit Bhargava <prarit@redhat.com>
Date2015-08-21 14:00 +0200
SubjectRe: [PATCH] x86, bitops, variable_test_bit should return 1 not -1 on a match
Message-ID<pZT9g-2Il-21@gated-at.bofh.it>
In reply to#1210990

On 08/21/2015 04:08 AM, H. Peter Anvin wrote:
> Wrong fix, though.  Instead we should change it to use the set instruction, which would also make it easier to use the CC_SET/CC_OUT proposed macros to use assembly out in the future.
> 
> The downside with set is that it only sets a single byte, the upside is that it always outputs 0 or 1, and apparently if the output variable is your bool gcc can use that for optimization.
> 

hpa -- can you send a pointer to that discussion?

Thanks,

P.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1212402 — [PATCH v2] x86, bitops, variable_test_bit should return 1 not -1 on a match

FromPrarit Bhargava <prarit@redhat.com>
Date2015-08-24 20:30 +0200
Subject[PATCH v2] x86, bitops, variable_test_bit should return 1 not -1 on a match
Message-ID<q14Fk-7f0-17@gated-at.bofh.it>
In reply to#1210990
This issue was noticed while debugging a CPU hotplug issue.  On x86
with (NR_CPUS > 1) the cpu_online() define is cpumask_test_cpu().
cpumask_test_cpu() should return 1 if the cpu is set in cpumask and
0 otherwise.

However, cpumask_test_cpu() returns -1 if the cpu in the cpumask is
set and 0 otherwise.  This happens because cpumask_test_cpu() calls
test_bit() which is a define that will call variable_test_bit().

variable_test_bit() calls the assembler instruction sbb (Subtract
with Borrow, " Subtracts the source from the destination, and subtracts 1
extra if the Carry Flag is set. Results are returned in "dest".)

A bit match results in -1 being returned from variable_test_bit() if a
match occurs, not 1 as the function is supposed to.

It looks like the code never does, for example, (test_bit() == 1) so this
change should not have any impact.

[v2]: hpa: Use setc, (Set if Carry, "Sets the byte in the operand to 1 if
the Carry Flag is set, otherwise sets the operand to 0.") instead of !!

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Prarit Bhargava <prarit@redhat.com>
---
 arch/x86/include/asm/bitops.h |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index cfe3b95..c0bff87 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -313,10 +313,10 @@ static __always_inline int constant_test_bit(long nr, const volatile unsigned lo
 
 static inline int variable_test_bit(long nr, volatile const unsigned long *addr)
 {
-	int oldbit;
+	u8 oldbit;
 
 	asm volatile("bt %2,%1\n\t"
-		     "sbb %0,%0"
+		     "setc %0"
 		     : "=r" (oldbit)
 		     : "m" (*(unsigned long *)addr), "Ir" (nr));
 
-- 
1.7.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1211123 — Re: [PATCH] x86, bitops, variable_test_bit should return 1 not -1 on a match

FromPrarit Bhargava <prarit@redhat.com>
Date2015-08-21 14:00 +0200
SubjectRe: [PATCH] x86, bitops, variable_test_bit should return 1 not -1 on a match
Message-ID<pZT9g-2Il-11@gated-at.bofh.it>
In reply to#1210947

On 08/21/2015 02:51 AM, Ingo Molnar wrote:
> 
> * Prarit Bhargava <prarit@redhat.com> wrote:
> 
>> This issue was noticed while debugging a CPU hotplug issue.  On x86
>> with (NR_CPUS > 1) the cpu_online() define is cpumask_test_cpu().
>> cpumask_test_cpu() should return 1 if the cpu is set in cpumask and
>> 0 otherwise.
>>
>> However, cpumask_test_cpu() returns -1 if the cpu in the cpumask is
>> set and 0 otherwise.  This happens because cpumask_test_cpu() calls
>> test_bit() which is a define that will call variable_test_bit().
>>
>> variable_test_bit() calls the assembler instruction sbb (Subtract
>> with Borrow, " Subtracts the source from the destination, and subtracts 1
>> extra if the Carry Flag is set. Results are returned in "dest".)
>>
>> A bit match results in -1 being returned from variable_test_bit() if a
>> match occurs, not 1 as the function is supposed to.  This can be easily
>> resolved by adding a "!!" to force 0 or 1 as a return.
>>
>> It looks like the code never does, for example, (test_bit() == 1) so this
>> change should not have any impact.
>>
>> Cc: Thomas Gleixner <tglx@linutronix.de>
>> Cc: Ingo Molnar <mingo@redhat.com>
>> Cc: "H. Peter Anvin" <hpa@zytor.com>
>> Cc: x86@kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> Signed-off-by: Prarit Bhargava <prarit@redhat.com>
>> ---
>>  arch/x86/include/asm/bitops.h |    2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
>> index cfe3b95..a87a5fb 100644
>> --- a/arch/x86/include/asm/bitops.h
>> +++ b/arch/x86/include/asm/bitops.h
>> @@ -320,7 +320,7 @@ static inline int variable_test_bit(long nr, volatile const unsigned long *addr)
>>  		     : "=r" (oldbit)
>>  		     : "m" (*(unsigned long *)addr), "Ir" (nr));
>>  
>> -	return oldbit;
>> +	return !!oldbit;
>>  }
>>  
>>  #if 0 /* Fool kernel-doc since it doesn't do macros yet */
> 
> Ok, I think this is a good fix to improve the robustness of this primitive, unless 
> someone objects.
> 
> I tried to find the CPU hotplug code that broke with cpu_online() returning -1 but 
> failed - all current mainline usage sites seem to be testing for nonzero in one 
> way or another. Could you please point it out?

I'm sorry Ingo, I think my description may have confused you.  I was debugging a
cpu hotplug issue[1] and did

printk("cpu %d cpu online status %d\n", cpu, cpu_online(cpu));

as a debug printk.  This printed out

cpu 3 cpu online status -1

which was really confusing.  That lead me down the rabbit hole of looking at the
sbb assembler instruction in variable_test_bit() to figure out why I was seeing -1.

P.

[1] The bug looks like it has to do with the system's firmware, not cpu hotplug.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1211434

FromIngo Molnar <mingo@kernel.org>
Date2015-08-22 11:20 +0200
Message-ID<q0d7Y-6fx-7@gated-at.bofh.it>
In reply to#1211123
* Prarit Bhargava <prarit@redhat.com> wrote:

> 
> 
> On 08/21/2015 02:51 AM, Ingo Molnar wrote:
> > 
> > * Prarit Bhargava <prarit@redhat.com> wrote:
> > 
> >> This issue was noticed while debugging a CPU hotplug issue.  On x86
> >> with (NR_CPUS > 1) the cpu_online() define is cpumask_test_cpu().
> >> cpumask_test_cpu() should return 1 if the cpu is set in cpumask and
> >> 0 otherwise.
> >>
> >> However, cpumask_test_cpu() returns -1 if the cpu in the cpumask is
> >> set and 0 otherwise.  This happens because cpumask_test_cpu() calls
> >> test_bit() which is a define that will call variable_test_bit().
> >>
> >> variable_test_bit() calls the assembler instruction sbb (Subtract
> >> with Borrow, " Subtracts the source from the destination, and subtracts 1
> >> extra if the Carry Flag is set. Results are returned in "dest".)
> >>
> >> A bit match results in -1 being returned from variable_test_bit() if a
> >> match occurs, not 1 as the function is supposed to.  This can be easily
> >> resolved by adding a "!!" to force 0 or 1 as a return.
> >>
> >> It looks like the code never does, for example, (test_bit() == 1) so this
> >> change should not have any impact.
> >>
> >> Cc: Thomas Gleixner <tglx@linutronix.de>
> >> Cc: Ingo Molnar <mingo@redhat.com>
> >> Cc: "H. Peter Anvin" <hpa@zytor.com>
> >> Cc: x86@kernel.org
> >> Cc: linux-kernel@vger.kernel.org
> >> Signed-off-by: Prarit Bhargava <prarit@redhat.com>
> >> ---
> >>  arch/x86/include/asm/bitops.h |    2 +-
> >>  1 file changed, 1 insertion(+), 1 deletion(-)
> >>
> >> diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
> >> index cfe3b95..a87a5fb 100644
> >> --- a/arch/x86/include/asm/bitops.h
> >> +++ b/arch/x86/include/asm/bitops.h
> >> @@ -320,7 +320,7 @@ static inline int variable_test_bit(long nr, volatile const unsigned long *addr)
> >>  		     : "=r" (oldbit)
> >>  		     : "m" (*(unsigned long *)addr), "Ir" (nr));
> >>  
> >> -	return oldbit;
> >> +	return !!oldbit;
> >>  }
> >>  
> >>  #if 0 /* Fool kernel-doc since it doesn't do macros yet */
> > 
> > Ok, I think this is a good fix to improve the robustness of this primitive, unless 
> > someone objects.
> > 
> > I tried to find the CPU hotplug code that broke with cpu_online() returning -1 but 
> > failed - all current mainline usage sites seem to be testing for nonzero in one 
> > way or another. Could you please point it out?
> 
> I'm sorry Ingo, I think my description may have confused you.  I was debugging a
> cpu hotplug issue[1] and did
> 
> printk("cpu %d cpu online status %d\n", cpu, cpu_online(cpu));
> 
> as a debug printk.  This printed out
> 
> cpu 3 cpu online status -1
> 
> which was really confusing.  That lead me down the rabbit hole of looking at the
> sbb assembler instruction in variable_test_bit() to figure out why I was seeing -1.

Ok, fair enough!

Still worth fixing IMHO.

Thanks,

	Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web