mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
rcu: add assertions to debug build
Xen's RCU implementation relies on no softirq handling taking place while being in a RCU critical section. Add ASSERT()s in debug builds in order to catch any violations. For that purpose modify rcu_read_[un]lock() to use a dedicated percpu counter additional to preempt_[en|dis]able() as this enables to test that condition in __do_softirq() (ASSERT_NOT_IN_ATOMIC() is not usable there due to __cpu_up() calling process_pending_softirqs() while holding the cpu hotplug lock). While at it switch the rcu_read_[un]lock() implementation to static inline functions instead of macros. Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
cef21210fb
commit
a6fe79a597
3 files changed
+39
-4
No files matched your search
@@ -46,6 +46,8 @@
|
||||
#include <xen/cpu.h>
|
||||
#include <xen/stop_machine.h>
|
||||
|
||||
DEFINE_PER_CPU(unsigned int, rcu_lock_cnt);
|
||||
|
||||
/* Global control variables for rcupdate callback mechanism. */
|
||||
static struct rcu_ctrlblk {
|
||||
long cur; /* Current batch number. */
|
||||
|
||||
@@ -31,6 +31,8 @@ static void __do_softirq(unsigned long ignore_mask)
|
||||
unsigned long pending;
|
||||
bool rcu_allowed = !(ignore_mask & (1ul << RCU_SOFTIRQ));
|
||||
|
||||
ASSERT(!rcu_allowed || rcu_quiesce_allowed());
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
/*
|
||||
@@ -58,7 +60,7 @@ void process_pending_softirqs(void)
|
||||
(1ul << SCHED_SLAVE_SOFTIRQ);
|
||||
|
||||
/* Block RCU processing in case of rcu_read_lock() held. */
|
||||
if ( preempt_count() )
|
||||
if ( !rcu_quiesce_allowed() )
|
||||
ignore_mask |= 1ul << RCU_SOFTIRQ;
|
||||
|
||||
ASSERT(!in_irq() && local_irq_is_enabled());
|
||||
|
||||
@@ -32,12 +32,35 @@
|
||||
#define __XEN_RCUPDATE_H
|
||||
|
||||
#include <xen/cache.h>
|
||||
#include <xen/compiler.h>
|
||||
#include <xen/spinlock.h>
|
||||
#include <xen/cpumask.h>
|
||||
#include <xen/percpu.h>
|
||||
#include <xen/preempt.h>
|
||||
|
||||
#define __rcu
|
||||
|
||||
DECLARE_PER_CPU(unsigned int, rcu_lock_cnt);
|
||||
|
||||
static inline void rcu_quiesce_disable(void)
|
||||
{
|
||||
preempt_disable();
|
||||
this_cpu(rcu_lock_cnt)++;
|
||||
barrier();
|
||||
}
|
||||
|
||||
static inline void rcu_quiesce_enable(void)
|
||||
{
|
||||
barrier();
|
||||
this_cpu(rcu_lock_cnt)--;
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
static inline bool rcu_quiesce_allowed(void)
|
||||
{
|
||||
return !this_cpu(rcu_lock_cnt);
|
||||
}
|
||||
|
||||
/**
|
||||
* struct rcu_head - callback structure for use with RCU
|
||||
* @next: next update requests in a list
|
||||
@@ -91,16 +114,24 @@ typedef struct _rcu_read_lock rcu_read_lock_t;
|
||||
* will be deferred until the outermost RCU read-side critical section
|
||||
* completes.
|
||||
*
|
||||
* It is illegal to block while in an RCU read-side critical section.
|
||||
* It is illegal to process softirqs or block while in an RCU read-side
|
||||
* critical section.
|
||||
*/
|
||||
#define rcu_read_lock(x) ({ ((void)(x)); preempt_disable(); })
|
||||
static inline void rcu_read_lock(rcu_read_lock_t *lock)
|
||||
{
|
||||
rcu_quiesce_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* rcu_read_unlock - marks the end of an RCU read-side critical section.
|
||||
*
|
||||
* See rcu_read_lock() for more information.
|
||||
*/
|
||||
#define rcu_read_unlock(x) ({ ((void)(x)); preempt_enable(); })
|
||||
static inline void rcu_read_unlock(rcu_read_lock_t *lock)
|
||||
{
|
||||
ASSERT(!rcu_quiesce_allowed());
|
||||
rcu_quiesce_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* So where is rcu_write_lock()? It does not exist, as there is no
|
||||
|
||||