summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2013-05-24 00:03:20 +0200
committerRichard Braun <rbraun@sceen.net>2013-05-24 00:03:20 +0200
commit809082a3520480925def38e10272440ef68a455b (patch)
tree24e7721d0fd72c0e313aa4b4ac413f2cf47137a5
parentb6b7c519edefe21b43e816f7e6d48fdb70f1eb8d (diff)
kern/llsync: improve concurrency
Keep a local copy of a processor registration state to avoid acquiring the global lock when attempting to commit a checkpoint from an unregistered processor.
-rw-r--r--kern/llsync.c15
-rw-r--r--kern/llsync.h4
-rw-r--r--kern/llsync_i.h7
3 files changed, 14 insertions, 12 deletions
diff --git a/kern/llsync.c b/kern/llsync.c
index d43bcefd..0fd973d0 100644
--- a/kern/llsync.c
+++ b/kern/llsync.c
@@ -51,7 +51,7 @@
#define LLSYNC_NR_WORKS_WARN 10000
-struct llsync_cpu_checkpoint llsync_cpu_checkpoints[MAX_CPUS];
+struct llsync_cpu llsync_cpus[MAX_CPUS];
/*
* Global lock protecting the remaining module data.
@@ -208,6 +208,9 @@ llsync_register_cpu(unsigned int cpu)
llsync_process_global_checkpoint(cpu);
spinlock_unlock_intr_restore(&llsync_lock, flags);
+
+ assert(!llsync_cpus[cpu].registered);
+ llsync_cpus[cpu].registered = 1;
}
static void
@@ -232,7 +235,8 @@ llsync_unregister_cpu(unsigned int cpu)
{
unsigned long flags;
- llsync_reset_checkpoint(cpu);
+ assert(llsync_cpus[cpu].registered);
+ llsync_cpus[cpu].registered = 0;
spinlock_lock_intr_save(&llsync_lock, &flags);
@@ -256,14 +260,11 @@ llsync_commit_checkpoint(unsigned int cpu)
{
unsigned long flags;
- if (!llsync_cpu_checkpoints[cpu].checked)
+ if (!(llsync_cpus[cpu].registered && llsync_cpus[cpu].checked))
return;
spinlock_lock_intr_save(&llsync_lock, &flags);
-
- if (bitmap_test(llsync_registered_cpus, cpu))
- llsync_commit_checkpoint_common(cpu);
-
+ llsync_commit_checkpoint_common(cpu);
spinlock_unlock_intr_restore(&llsync_lock, flags);
}
diff --git a/kern/llsync.h b/kern/llsync.h
index 273346fb..c58030d0 100644
--- a/kern/llsync.h
+++ b/kern/llsync.h
@@ -90,7 +90,7 @@ llsync_read_unlock(void)
static inline void
llsync_reset_checkpoint(unsigned int cpu)
{
- llsync_cpu_checkpoints[cpu].checked = 0;
+ llsync_cpus[cpu].checked = 0;
}
/*
@@ -101,7 +101,7 @@ llsync_reset_checkpoint(unsigned int cpu)
static inline void
llsync_checkin(unsigned int cpu)
{
- llsync_cpu_checkpoints[cpu].checked = 1;
+ llsync_cpus[cpu].checked = 1;
}
/*
diff --git a/kern/llsync_i.h b/kern/llsync_i.h
index 89a7fe83..034e368b 100644
--- a/kern/llsync_i.h
+++ b/kern/llsync_i.h
@@ -21,12 +21,13 @@
#include <kern/param.h>
/*
- * Per-processor flag indicating if a processor checked in.
+ * Per-processor data.
*/
-struct llsync_cpu_checkpoint {
+struct llsync_cpu {
+ int registered;
int checked;
} __aligned(CPU_L1_SIZE);
-extern struct llsync_cpu_checkpoint llsync_cpu_checkpoints[MAX_CPUS];
+extern struct llsync_cpu llsync_cpus[MAX_CPUS];
#endif /* _KERN_LLSYNC_I_H */