qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v8 22/35] RISC-V: Use atomic_cmpxchg to update PLIC


From: Michael Clark
Subject: [Qemu-devel] [PATCH v8 22/35] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps
Date: Thu, 26 Apr 2018 11:45:25 +1200

The PLIC previously used a mutex to protect against concurrent
access to the claimed and pending bitfields. Instead of using
a mutex, we update the bitfields using atomic_cmpxchg.

Rename sifive_plic_num_irqs_pending to sifive_plic_irqs_pending
and add an early out if any interrupts are pending as the
count of pending interrupts is not used.

Cc: Sagar Karandikar <address@hidden>
Cc: Bastian Koppelmann <address@hidden>
Cc: Palmer Dabbelt <address@hidden>
Cc: Alistair Francis <address@hidden>
Signed-off-by: Michael Clark <address@hidden>
---
 hw/riscv/sifive_plic.c         | 36 +++++++++++++++---------------------
 include/hw/riscv/sifive_plic.h |  1 -
 2 files changed, 15 insertions(+), 22 deletions(-)

diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
index 874de2e..04e39e4 100644
--- a/hw/riscv/sifive_plic.c
+++ b/hw/riscv/sifive_plic.c
@@ -84,33 +84,28 @@ static void sifive_plic_print_state(SiFivePLICState *plic)
 static
 void sifive_plic_set_pending(SiFivePLICState *plic, int irq, bool pending)
 {
-    qemu_mutex_lock(&plic->lock);
     uint32_t word = irq >> 5;
-    if (pending) {
-        plic->pending[word] |= (1 << (irq & 31));
-    } else {
-        plic->pending[word] &= ~(1 << (irq & 31));
-    }
-    qemu_mutex_unlock(&plic->lock);
+    uint32_t old, new;
+    do {
+        old = atomic_read(&plic->pending[word]);
+        new = (old & ~(1 << (irq & 31))) | (-!!pending & (1 << (irq & 31)));
+    } while (atomic_cmpxchg(&plic->pending[word], old, new) != old);
 }
 
 static
 void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool claimed)
 {
-    qemu_mutex_lock(&plic->lock);
     uint32_t word = irq >> 5;
-    if (claimed) {
-        plic->claimed[word] |= (1 << (irq & 31));
-    } else {
-        plic->claimed[word] &= ~(1 << (irq & 31));
-    }
-    qemu_mutex_unlock(&plic->lock);
+    uint32_t old, new;
+    do {
+        old = atomic_read(&plic->claimed[word]);
+        new = (old & ~(1 << (irq & 31))) | (-!!claimed & (1 << (irq & 31)));
+    } while (atomic_cmpxchg(&plic->claimed[word], old, new) != old);
 }
 
-static
-int sifive_plic_num_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
+static int sifive_plic_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
 {
-    int i, j, count = 0;
+    int i, j;
     for (i = 0; i < plic->bitfield_words; i++) {
         uint32_t pending_enabled_not_claimed =
             (plic->pending[i] & ~plic->claimed[i]) &
@@ -123,11 +118,11 @@ int sifive_plic_num_irqs_pending(SiFivePLICState *plic, 
uint32_t addrid)
             uint32_t prio = plic->source_priority[irq];
             int enabled = pending_enabled_not_claimed & (1 << j);
             if (enabled && prio > plic->target_priority[addrid]) {
-                count++;
+                return 1;
             }
         }
     }
-    return count;
+    return 0;
 }
 
 static void sifive_plic_update(SiFivePLICState *plic)
@@ -143,7 +138,7 @@ static void sifive_plic_update(SiFivePLICState *plic)
         if (!env) {
             continue;
         }
-        int level = sifive_plic_num_irqs_pending(plic, addrid) > 0;
+        int level = sifive_plic_irqs_pending(plic, addrid);
         switch (mode) {
         case PLICMode_M:
             riscv_set_local_interrupt(RISCV_CPU(cpu), MIP_MEIP, level);
@@ -440,7 +435,6 @@ static void sifive_plic_realize(DeviceState *dev, Error 
**errp)
     memory_region_init_io(&plic->mmio, OBJECT(dev), &sifive_plic_ops, plic,
                           TYPE_SIFIVE_PLIC, plic->aperture_size);
     parse_hart_config(plic);
-    qemu_mutex_init(&plic->lock);
     plic->bitfield_words = (plic->num_sources + 31) >> 5;
     plic->source_priority = g_new0(uint32_t, plic->num_sources);
     plic->target_priority = g_new(uint32_t, plic->num_addrs);
diff --git a/include/hw/riscv/sifive_plic.h b/include/hw/riscv/sifive_plic.h
index 11a5a98..ff09a28 100644
--- a/include/hw/riscv/sifive_plic.h
+++ b/include/hw/riscv/sifive_plic.h
@@ -55,7 +55,6 @@ typedef struct SiFivePLICState {
     uint32_t *pending;
     uint32_t *claimed;
     uint32_t *enable;
-    QemuMutex lock;
     qemu_irq *irqs;
 
     /* config */
-- 
2.7.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]