diff mbox

[kvm-unit-tests,2/7] lib/x86/smp: introduce on_cpus

Message ID 20170601154819.18831-3-drjones@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Andrew Jones June 1, 2017, 3:48 p.m. UTC
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
 lib/x86/smp.c | 20 ++++++++++++++++++++
 lib/x86/smp.h |  2 ++
 2 files changed, 22 insertions(+)

Comments

Radim Krčmář June 7, 2017, 2:48 p.m. UTC | #1
2017-06-01 17:48+0200, Andrew Jones:
> Signed-off-by: Andrew Jones <drjones@redhat.com>
> ---
> diff --git a/lib/x86/smp.c b/lib/x86/smp.c
> @@ -1,5 +1,6 @@
> @@ -91,6 +95,21 @@ void on_cpu_async(int cpu, void (*function)(void *data), void *data)
>      __on_cpu(cpu, function, data, 0);
>  }
>  

(I'm sorry the review took so long.)

> +void on_cpus(void (*func)(void))
> +{
> +    int cpu;
> +
> +    for (cpu = cpu_count() - 1; cpu >= 0; --cpu)
> +        on_cpu_async(cpu, (ipi_function_type)func, NULL);

Calling a casted function pointer is undefined behavior in C and I think
that keeping the argument is better anyway -- the API is consistent that
way and you don't need to introduce a global in some patches.

> +
> +    while (cpus_active())
> +        ;

Add a pause() here,

Thanks.
Andrew Jones June 13, 2017, 8:14 a.m. UTC | #2
On Wed, Jun 07, 2017 at 04:48:34PM +0200, Radim Krčmář wrote:
> 2017-06-01 17:48+0200, Andrew Jones:
> > Signed-off-by: Andrew Jones <drjones@redhat.com>
> > ---
> > diff --git a/lib/x86/smp.c b/lib/x86/smp.c
> > @@ -1,5 +1,6 @@
> > @@ -91,6 +95,21 @@ void on_cpu_async(int cpu, void (*function)(void *data), void *data)
> >      __on_cpu(cpu, function, data, 0);
> >  }
> >  
> 
> (I'm sorry the review took so long.)
> 
> > +void on_cpus(void (*func)(void))
> > +{
> > +    int cpu;
> > +
> > +    for (cpu = cpu_count() - 1; cpu >= 0; --cpu)
> > +        on_cpu_async(cpu, (ipi_function_type)func, NULL);
> 
> Calling a casted function pointer is undefined behavior in C and I think
> that keeping the argument is better anyway -- the API is consistent that
> way and you don't need to introduce a global in some patches.

I agree I shouldn't use undefined behavior and I have no strong preference
on the API, so I 'll change this, and I'll fix ARM too.

> 
> > +
> > +    while (cpus_active())
> > +        ;
> 
> Add a pause() here,

Will do.

Thanks,
drew
diff mbox

Patch

diff --git a/lib/x86/smp.c b/lib/x86/smp.c
index 4bdbeaeb8b68..b16c98c02ad2 100644
--- a/lib/x86/smp.c
+++ b/lib/x86/smp.c
@@ -1,5 +1,6 @@ 
 
 #include <libcflat.h>
+#include "atomic.h"
 #include "smp.h"
 #include "apic.h"
 #include "fwcfg.h"
@@ -15,6 +16,7 @@  static void *volatile ipi_data;
 static volatile int ipi_done;
 static volatile bool ipi_wait;
 static int _cpu_count;
+static atomic_t active_cpus;
 
 static __attribute__((used)) void ipi()
 {
@@ -27,6 +29,7 @@  static __attribute__((used)) void ipi()
 	apic_write(APIC_EOI, 0);
     }
     function(data);
+    atomic_dec(&active_cpus);
     if (wait) {
 	ipi_done = 1;
 	apic_write(APIC_EOI, 0);
@@ -68,6 +71,7 @@  static void __on_cpu(int cpu, void (*function)(void *data), void *data,
     if (cpu == smp_id())
 	function(data);
     else {
+	atomic_inc(&active_cpus);
 	ipi_done = 0;
 	ipi_function = function;
 	ipi_data = data;
@@ -91,6 +95,21 @@  void on_cpu_async(int cpu, void (*function)(void *data), void *data)
     __on_cpu(cpu, function, data, 0);
 }
 
+void on_cpus(void (*func)(void))
+{
+    int cpu;
+
+    for (cpu = cpu_count() - 1; cpu >= 0; --cpu)
+        on_cpu_async(cpu, (ipi_function_type)func, NULL);
+
+    while (cpus_active())
+        ;
+}
+
+int cpus_active(void)
+{
+    return atomic_read(&active_cpus) > 1;
+}
 
 void smp_init(void)
 {
@@ -106,4 +125,5 @@  void smp_init(void)
     for (i = 1; i < cpu_count(); ++i)
         on_cpu(i, setup_smp_id, 0);
 
+    atomic_inc(&active_cpus);
 }
diff --git a/lib/x86/smp.h b/lib/x86/smp.h
index afabac8495f1..5b8deb4a185e 100644
--- a/lib/x86/smp.h
+++ b/lib/x86/smp.h
@@ -6,7 +6,9 @@  void smp_init(void);
 
 int cpu_count(void);
 int smp_id(void);
+int cpus_active(void);
 void on_cpu(int cpu, void (*function)(void *data), void *data);
 void on_cpu_async(int cpu, void (*function)(void *data), void *data);
+void on_cpus(void (*func)(void));
 
 #endif