enum rcu_sync_type gp_type;
};
+extern bool __rcu_sync_is_idle(struct rcu_sync *);
+
/**
* rcu_sync_is_idle() - Are readers permitted to use their fastpaths?
* @rsp: Pointer to rcu_sync structure to use for synchronization
*/
static inline bool rcu_sync_is_idle(struct rcu_sync *rsp)
{
+#ifdef CONFIG_PROVE_RCU
+ return __rcu_sync_is_idle(rsp);
+#else
return !rsp->gp_state; /* GP_IDLE */
+#endif
}
extern void rcu_sync_init(struct rcu_sync *, enum rcu_sync_type);
#include <linux/rcu_sync.h>
#include <linux/sched.h>
+#ifdef CONFIG_PROVE_RCU
+#define __INIT_HELD(func) .held = func,
+#else
+#define __INIT_HELD(func)
+#endif
+
static const struct {
void (*sync)(void);
void (*call)(struct rcu_head *, void (*)(struct rcu_head *));
+#ifdef CONFIG_PROVE_RCU
+ int (*held)(void);
+#endif
} gp_ops[] = {
[RCU_SYNC] = {
.sync = synchronize_rcu,
.call = call_rcu,
+ __INIT_HELD(rcu_read_lock_held)
},
[RCU_SCHED_SYNC] = {
.sync = synchronize_sched,
.call = call_rcu_sched,
+ __INIT_HELD(rcu_read_lock_sched_held)
},
[RCU_BH_SYNC] = {
.sync = synchronize_rcu_bh,
.call = call_rcu_bh,
+ __INIT_HELD(rcu_read_lock_bh_held)
},
};
#define rss_lock gp_wait.lock
+#ifdef CONFIG_PROVE_RCU
+bool __rcu_sync_is_idle(struct rcu_sync *rsp)
+{
+ WARN_ON(!gp_ops[rsp->gp_type].held());
+ return rsp->gp_state == GP_IDLE;
+}
+#endif
+
/**
* rcu_sync_init() - Initialize an rcu_sync structure
* @rsp: Pointer to rcu_sync structure to be initialized