diff mbox

[v2,06/13] qemu-thread: add simple test-and-set spinlock

Message ID 1460050358-25025-7-git-send-email-cota@braap.org
State New
Headers show

Commit Message

Emilio Cota April 7, 2016, 5:32 p.m. UTC
From: Guillaume Delbergue <guillaume.delbergue@greensocs.com>

Signed-off-by: Guillaume Delbergue <guillaume.delbergue@greensocs.com>
[Rewritten. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/qemu/thread.h | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

Comments

Alex Bennée April 8, 2016, 1:02 p.m. UTC | #1
Emilio G. Cota <cota@braap.org> writes:

> From: Guillaume Delbergue <guillaume.delbergue@greensocs.com>
>
> Signed-off-by: Guillaume Delbergue <guillaume.delbergue@greensocs.com>
> [Rewritten. - Paolo]
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  include/qemu/thread.h | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>
> diff --git a/include/qemu/thread.h b/include/qemu/thread.h
> index bdae6df..1aa843b 100644
> --- a/include/qemu/thread.h
> +++ b/include/qemu/thread.h
> @@ -1,6 +1,8 @@
>  #ifndef __QEMU_THREAD_H
>  #define __QEMU_THREAD_H 1
>
> +#include <errno.h>
> +#include "qemu/atomic.h"
>
>  typedef struct QemuMutex QemuMutex;
>  typedef struct QemuCond QemuCond;
> @@ -60,4 +62,33 @@ struct Notifier;
>  void qemu_thread_atexit_add(struct Notifier *notifier);
>  void qemu_thread_atexit_remove(struct Notifier *notifier);
>
> +typedef struct QemuSpin {
> +    int value;

If we are throwing true and false around as the only two values can we
use bool here and be consistent when setting/clearing.

> +} QemuSpin;
> +
> +static inline void qemu_spin_init(QemuSpin *spin)
> +{
> +    spin->value = 0;
> +}
> +
> +static inline void qemu_spin_lock(QemuSpin *spin)
> +{
> +    do {
> +        while (atomic_read(&spin->value));
> +    } while (atomic_xchg(&spin->value, true));
> +}
> +
> +static inline int qemu_spin_trylock(QemuSpin *spin)
> +{
> +    if (atomic_read(&spin->value) || atomic_xchg(&spin->value, true)) {
> +        return -EBUSY;
> +    }
> +    return 0;
> +}
> +
> +static inline void qemu_spin_unlock(QemuSpin *spin)
> +{
> +    atomic_mb_set(&spin->value, 0);
> +}
> +
>  #endif


--
Alex Bennée
Richard Henderson April 8, 2016, 6:35 p.m. UTC | #2
On 04/07/2016 10:32 AM, Emilio G. Cota wrote:
> +        while (atomic_read(&spin->value));

I really really don't like ; snuggled up behind loop conditions.
Isn't this where you want to use pause, anyway?


r~
Richard Henderson April 8, 2016, 6:38 p.m. UTC | #3
On 04/08/2016 06:02 AM, Alex Bennée wrote:
>> > +typedef struct QemuSpin {
>> > +    int value;
> If we are throwing true and false around as the only two values can we
> use bool here and be consistent when setting/clearing.
> 

Except that quite a lot of hosts can only (efficiently) do atomic operations on
a minimum of 4 byte quantities.  I'd rather continue to use int here.


r~
Alex Bennée April 8, 2016, 9:24 p.m. UTC | #4
Richard Henderson <rth@twiddle.net> writes:

> On 04/08/2016 06:02 AM, Alex Bennée wrote:
>>> > +typedef struct QemuSpin {
>>> > +    int value;
>> If we are throwing true and false around as the only two values can we
>> use bool here and be consistent when setting/clearing.
>>
>
> Except that quite a lot of hosts can only (efficiently) do atomic operations on
> a minimum of 4 byte quantities.  I'd rather continue to use int here.

I suspect bool == unsigned int underneath. But having true/false and 0/1 mixed up
gets confusing even if they are equivalent.

>
>
> r~


--
Alex Bennée
Paolo Bonzini April 8, 2016, 9:26 p.m. UTC | #5
On 08/04/2016 23:24, Alex Bennée wrote:
> > Except that quite a lot of hosts can only (efficiently) do atomic operations on
> > a minimum of 4 byte quantities.  I'd rather continue to use int here.
> 
> I suspect bool == unsigned int underneath. But having true/false and 0/1 mixed up
> gets confusing even if they are equivalent.

Sometimes sizeof(bool) == 1.

Paolo
Richard Henderson April 8, 2016, 9:31 p.m. UTC | #6
On 04/08/2016 02:26 PM, Paolo Bonzini wrote:
> 
> 
> On 08/04/2016 23:24, Alex Bennée wrote:
>>> Except that quite a lot of hosts can only (efficiently) do atomic operations on
>>> a minimum of 4 byte quantities.  I'd rather continue to use int here.
>>
>> I suspect bool == unsigned int underneath. But having true/false and 0/1 mixed up
>> gets confusing even if they are equivalent.
> 
> Sometimes sizeof(bool) == 1.

sizeof(bool) == 1 everywhere except MacOSX, where it's 4.


r~
Sergey Fedorov April 8, 2016, 9:35 p.m. UTC | #7
On 09/04/16 00:31, Richard Henderson wrote:
> On 04/08/2016 02:26 PM, Paolo Bonzini wrote:
>>
>> On 08/04/2016 23:24, Alex Bennée wrote:
>>>> Except that quite a lot of hosts can only (efficiently) do atomic operations on
>>>> a minimum of 4 byte quantities.  I'd rather continue to use int here.
>>> I suspect bool == unsigned int underneath. But having true/false and 0/1 mixed up
>>> gets confusing even if they are equivalent.
>> Sometimes sizeof(bool) == 1.
> sizeof(bool) == 1 everywhere except MacOSX, where it's 4.
>

Hm, that's too strange:

$ gcc a.c
a.c: In function ‘main’:
a.c:6:5: warning: format ‘%d’ expects argument of type ‘int’, but
argument 2 has type ‘long unsigned int’ [-Wformat=]
     printf("%d\n", sizeof(bool));
     ^
$ ./a.out
1


Kind regards,
Sergey
diff mbox

Patch

diff --git a/include/qemu/thread.h b/include/qemu/thread.h
index bdae6df..1aa843b 100644
--- a/include/qemu/thread.h
+++ b/include/qemu/thread.h
@@ -1,6 +1,8 @@ 
 #ifndef __QEMU_THREAD_H
 #define __QEMU_THREAD_H 1
 
+#include <errno.h>
+#include "qemu/atomic.h"
 
 typedef struct QemuMutex QemuMutex;
 typedef struct QemuCond QemuCond;
@@ -60,4 +62,33 @@  struct Notifier;
 void qemu_thread_atexit_add(struct Notifier *notifier);
 void qemu_thread_atexit_remove(struct Notifier *notifier);
 
+typedef struct QemuSpin {
+    int value;
+} QemuSpin;
+
+static inline void qemu_spin_init(QemuSpin *spin)
+{
+    spin->value = 0;
+}
+
+static inline void qemu_spin_lock(QemuSpin *spin)
+{
+    do {
+        while (atomic_read(&spin->value));
+    } while (atomic_xchg(&spin->value, true));
+}
+
+static inline int qemu_spin_trylock(QemuSpin *spin)
+{
+    if (atomic_read(&spin->value) || atomic_xchg(&spin->value, true)) {
+        return -EBUSY;
+    }
+    return 0;
+}
+
+static inline void qemu_spin_unlock(QemuSpin *spin)
+{
+    atomic_mb_set(&spin->value, 0);
+}
+
 #endif