|
@@ -155,9 +155,8 @@ EXPORT_SYMBOL_GPL(rcu_batches_completed);
|
|
|
* not in a quiescent state. There might be any number of tasks blocked
|
|
|
* while in an RCU read-side critical section.
|
|
|
*
|
|
|
- * Unlike the other rcu_*_qs() functions, callers to this function
|
|
|
- * must disable irqs in order to protect the assignment to
|
|
|
- * ->rcu_read_unlock_special.
|
|
|
+ * As with the other rcu_*_qs() functions, callers to this function
|
|
|
+ * must disable preemption.
|
|
|
*/
|
|
|
static void rcu_preempt_qs(int cpu)
|
|
|
{
|
|
@@ -166,7 +165,7 @@ static void rcu_preempt_qs(int cpu)
|
|
|
if (rdp->passed_quiesce == 0)
|
|
|
trace_rcu_grace_period(TPS("rcu_preempt"), rdp->gpnum, TPS("cpuqs"));
|
|
|
rdp->passed_quiesce = 1;
|
|
|
- current->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS;
|
|
|
+ current->rcu_read_unlock_special.b.need_qs = false;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -190,14 +189,14 @@ static void rcu_preempt_note_context_switch(int cpu)
|
|
|
struct rcu_node *rnp;
|
|
|
|
|
|
if (t->rcu_read_lock_nesting > 0 &&
|
|
|
- (t->rcu_read_unlock_special & RCU_READ_UNLOCK_BLOCKED) == 0) {
|
|
|
+ !t->rcu_read_unlock_special.b.blocked) {
|
|
|
|
|
|
/* Possibly blocking in an RCU read-side critical section. */
|
|
|
rdp = per_cpu_ptr(rcu_preempt_state.rda, cpu);
|
|
|
rnp = rdp->mynode;
|
|
|
raw_spin_lock_irqsave(&rnp->lock, flags);
|
|
|
smp_mb__after_unlock_lock();
|
|
|
- t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED;
|
|
|
+ t->rcu_read_unlock_special.b.blocked = true;
|
|
|
t->rcu_blocked_node = rnp;
|
|
|
|
|
|
/*
|
|
@@ -239,7 +238,7 @@ static void rcu_preempt_note_context_switch(int cpu)
|
|
|
: rnp->gpnum + 1);
|
|
|
raw_spin_unlock_irqrestore(&rnp->lock, flags);
|
|
|
} else if (t->rcu_read_lock_nesting < 0 &&
|
|
|
- t->rcu_read_unlock_special) {
|
|
|
+ t->rcu_read_unlock_special.s) {
|
|
|
|
|
|
/*
|
|
|
* Complete exit from RCU read-side critical section on
|
|
@@ -257,9 +256,7 @@ static void rcu_preempt_note_context_switch(int cpu)
|
|
|
* grace period, then the fact that the task has been enqueued
|
|
|
* means that we continue to block the current grace period.
|
|
|
*/
|
|
|
- local_irq_save(flags);
|
|
|
rcu_preempt_qs(cpu);
|
|
|
- local_irq_restore(flags);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -340,7 +337,7 @@ void rcu_read_unlock_special(struct task_struct *t)
|
|
|
bool drop_boost_mutex = false;
|
|
|
#endif /* #ifdef CONFIG_RCU_BOOST */
|
|
|
struct rcu_node *rnp;
|
|
|
- int special;
|
|
|
+ union rcu_special special;
|
|
|
|
|
|
/* NMI handlers cannot block and cannot safely manipulate state. */
|
|
|
if (in_nmi())
|
|
@@ -350,12 +347,13 @@ void rcu_read_unlock_special(struct task_struct *t)
|
|
|
|
|
|
/*
|
|
|
* If RCU core is waiting for this CPU to exit critical section,
|
|
|
- * let it know that we have done so.
|
|
|
+ * let it know that we have done so. Because irqs are disabled,
|
|
|
+ * t->rcu_read_unlock_special cannot change.
|
|
|
*/
|
|
|
special = t->rcu_read_unlock_special;
|
|
|
- if (special & RCU_READ_UNLOCK_NEED_QS) {
|
|
|
+ if (special.b.need_qs) {
|
|
|
rcu_preempt_qs(smp_processor_id());
|
|
|
- if (!t->rcu_read_unlock_special) {
|
|
|
+ if (!t->rcu_read_unlock_special.s) {
|
|
|
local_irq_restore(flags);
|
|
|
return;
|
|
|
}
|
|
@@ -368,8 +366,8 @@ void rcu_read_unlock_special(struct task_struct *t)
|
|
|
}
|
|
|
|
|
|
/* Clean up if blocked during RCU read-side critical section. */
|
|
|
- if (special & RCU_READ_UNLOCK_BLOCKED) {
|
|
|
- t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_BLOCKED;
|
|
|
+ if (special.b.blocked) {
|
|
|
+ t->rcu_read_unlock_special.b.blocked = false;
|
|
|
|
|
|
/*
|
|
|
* Remove this task from the list it blocked on. The
|
|
@@ -658,7 +656,7 @@ static void rcu_preempt_check_callbacks(int cpu)
|
|
|
}
|
|
|
if (t->rcu_read_lock_nesting > 0 &&
|
|
|
per_cpu(rcu_preempt_data, cpu).qs_pending)
|
|
|
- t->rcu_read_unlock_special |= RCU_READ_UNLOCK_NEED_QS;
|
|
|
+ t->rcu_read_unlock_special.b.need_qs = true;
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_RCU_BOOST
|
|
@@ -941,7 +939,7 @@ void exit_rcu(void)
|
|
|
return;
|
|
|
t->rcu_read_lock_nesting = 1;
|
|
|
barrier();
|
|
|
- t->rcu_read_unlock_special = RCU_READ_UNLOCK_BLOCKED;
|
|
|
+ t->rcu_read_unlock_special.b.blocked = true;
|
|
|
__rcu_read_unlock();
|
|
|
}
|
|
|
|