Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull RCU fixes from Ingo Molnar: "This tree includes a shutdown/cpu-hotplug deadlock fix and a documentation fix." * 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: rcu: Advise most users not to enable RCU user mode rcu: Grace-period initialization excludes only RCU notifier
This commit is contained in:
12
init/Kconfig
12
init/Kconfig
@@ -496,6 +496,12 @@ config RCU_USER_QS
|
|||||||
excluded from the global RCU state machine and thus doesn't
|
excluded from the global RCU state machine and thus doesn't
|
||||||
to keep the timer tick on for RCU.
|
to keep the timer tick on for RCU.
|
||||||
|
|
||||||
|
Unless you want to hack and help the development of the full
|
||||||
|
tickless feature, you shouldn't enable this option. It adds
|
||||||
|
unnecessary overhead.
|
||||||
|
|
||||||
|
If unsure say N
|
||||||
|
|
||||||
config RCU_USER_QS_FORCE
|
config RCU_USER_QS_FORCE
|
||||||
bool "Force userspace extended QS by default"
|
bool "Force userspace extended QS by default"
|
||||||
depends on RCU_USER_QS
|
depends on RCU_USER_QS
|
||||||
@@ -504,6 +510,12 @@ config RCU_USER_QS_FORCE
|
|||||||
test this feature that treats userspace as an extended quiescent
|
test this feature that treats userspace as an extended quiescent
|
||||||
state until we have a real user like a full adaptive nohz option.
|
state until we have a real user like a full adaptive nohz option.
|
||||||
|
|
||||||
|
Unless you want to hack and help the development of the full
|
||||||
|
tickless feature, you shouldn't enable this option. It adds
|
||||||
|
unnecessary overhead.
|
||||||
|
|
||||||
|
If unsure say N
|
||||||
|
|
||||||
config RCU_FANOUT
|
config RCU_FANOUT
|
||||||
int "Tree-based hierarchical RCU fanout value"
|
int "Tree-based hierarchical RCU fanout value"
|
||||||
range 2 64 if 64BIT
|
range 2 64 if 64BIT
|
||||||
|
@@ -74,6 +74,7 @@ static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS];
|
|||||||
.orphan_nxttail = &sname##_state.orphan_nxtlist, \
|
.orphan_nxttail = &sname##_state.orphan_nxtlist, \
|
||||||
.orphan_donetail = &sname##_state.orphan_donelist, \
|
.orphan_donetail = &sname##_state.orphan_donelist, \
|
||||||
.barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \
|
.barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \
|
||||||
|
.onoff_mutex = __MUTEX_INITIALIZER(sname##_state.onoff_mutex), \
|
||||||
.name = #sname, \
|
.name = #sname, \
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1197,7 +1198,7 @@ static int rcu_gp_init(struct rcu_state *rsp)
|
|||||||
raw_spin_unlock_irq(&rnp->lock);
|
raw_spin_unlock_irq(&rnp->lock);
|
||||||
|
|
||||||
/* Exclude any concurrent CPU-hotplug operations. */
|
/* Exclude any concurrent CPU-hotplug operations. */
|
||||||
get_online_cpus();
|
mutex_lock(&rsp->onoff_mutex);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the quiescent-state-needed bits in all the rcu_node
|
* Set the quiescent-state-needed bits in all the rcu_node
|
||||||
@@ -1234,7 +1235,7 @@ static int rcu_gp_init(struct rcu_state *rsp)
|
|||||||
cond_resched();
|
cond_resched();
|
||||||
}
|
}
|
||||||
|
|
||||||
put_online_cpus();
|
mutex_unlock(&rsp->onoff_mutex);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1700,6 +1701,7 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
|
|||||||
/* Remove the dead CPU from the bitmasks in the rcu_node hierarchy. */
|
/* Remove the dead CPU from the bitmasks in the rcu_node hierarchy. */
|
||||||
|
|
||||||
/* Exclude any attempts to start a new grace period. */
|
/* Exclude any attempts to start a new grace period. */
|
||||||
|
mutex_lock(&rsp->onoff_mutex);
|
||||||
raw_spin_lock_irqsave(&rsp->onofflock, flags);
|
raw_spin_lock_irqsave(&rsp->onofflock, flags);
|
||||||
|
|
||||||
/* Orphan the dead CPU's callbacks, and adopt them if appropriate. */
|
/* Orphan the dead CPU's callbacks, and adopt them if appropriate. */
|
||||||
@@ -1744,6 +1746,7 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
|
|||||||
init_callback_list(rdp);
|
init_callback_list(rdp);
|
||||||
/* Disallow further callbacks on this CPU. */
|
/* Disallow further callbacks on this CPU. */
|
||||||
rdp->nxttail[RCU_NEXT_TAIL] = NULL;
|
rdp->nxttail[RCU_NEXT_TAIL] = NULL;
|
||||||
|
mutex_unlock(&rsp->onoff_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* #ifdef CONFIG_HOTPLUG_CPU */
|
#else /* #ifdef CONFIG_HOTPLUG_CPU */
|
||||||
@@ -2648,6 +2651,9 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
|
|||||||
struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
|
struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
|
||||||
struct rcu_node *rnp = rcu_get_root(rsp);
|
struct rcu_node *rnp = rcu_get_root(rsp);
|
||||||
|
|
||||||
|
/* Exclude new grace periods. */
|
||||||
|
mutex_lock(&rsp->onoff_mutex);
|
||||||
|
|
||||||
/* Set up local state, ensuring consistent view of global state. */
|
/* Set up local state, ensuring consistent view of global state. */
|
||||||
raw_spin_lock_irqsave(&rnp->lock, flags);
|
raw_spin_lock_irqsave(&rnp->lock, flags);
|
||||||
rdp->beenonline = 1; /* We have now been online. */
|
rdp->beenonline = 1; /* We have now been online. */
|
||||||
@@ -2662,14 +2668,6 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
|
|||||||
rcu_prepare_for_idle_init(cpu);
|
rcu_prepare_for_idle_init(cpu);
|
||||||
raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
|
raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
|
||||||
|
|
||||||
/*
|
|
||||||
* A new grace period might start here. If so, we won't be part
|
|
||||||
* of it, but that is OK, as we are currently in a quiescent state.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Exclude any attempts to start a new GP on large systems. */
|
|
||||||
raw_spin_lock(&rsp->onofflock); /* irqs already disabled. */
|
|
||||||
|
|
||||||
/* Add CPU to rcu_node bitmasks. */
|
/* Add CPU to rcu_node bitmasks. */
|
||||||
rnp = rdp->mynode;
|
rnp = rdp->mynode;
|
||||||
mask = rdp->grpmask;
|
mask = rdp->grpmask;
|
||||||
@@ -2693,8 +2691,9 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
|
|||||||
raw_spin_unlock(&rnp->lock); /* irqs already disabled. */
|
raw_spin_unlock(&rnp->lock); /* irqs already disabled. */
|
||||||
rnp = rnp->parent;
|
rnp = rnp->parent;
|
||||||
} while (rnp != NULL && !(rnp->qsmaskinit & mask));
|
} while (rnp != NULL && !(rnp->qsmaskinit & mask));
|
||||||
|
local_irq_restore(flags);
|
||||||
|
|
||||||
raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
|
mutex_unlock(&rsp->onoff_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __cpuinit rcu_prepare_cpu(int cpu)
|
static void __cpuinit rcu_prepare_cpu(int cpu)
|
||||||
|
@@ -394,11 +394,17 @@ struct rcu_state {
|
|||||||
struct rcu_head **orphan_donetail; /* Tail of above. */
|
struct rcu_head **orphan_donetail; /* Tail of above. */
|
||||||
long qlen_lazy; /* Number of lazy callbacks. */
|
long qlen_lazy; /* Number of lazy callbacks. */
|
||||||
long qlen; /* Total number of callbacks. */
|
long qlen; /* Total number of callbacks. */
|
||||||
|
/* End of fields guarded by onofflock. */
|
||||||
|
|
||||||
|
struct mutex onoff_mutex; /* Coordinate hotplug & GPs. */
|
||||||
|
|
||||||
struct mutex barrier_mutex; /* Guards barrier fields. */
|
struct mutex barrier_mutex; /* Guards barrier fields. */
|
||||||
atomic_t barrier_cpu_count; /* # CPUs waiting on. */
|
atomic_t barrier_cpu_count; /* # CPUs waiting on. */
|
||||||
struct completion barrier_completion; /* Wake at barrier end. */
|
struct completion barrier_completion; /* Wake at barrier end. */
|
||||||
unsigned long n_barrier_done; /* ++ at start and end of */
|
unsigned long n_barrier_done; /* ++ at start and end of */
|
||||||
/* _rcu_barrier(). */
|
/* _rcu_barrier(). */
|
||||||
|
/* End of fields guarded by barrier_mutex. */
|
||||||
|
|
||||||
unsigned long jiffies_force_qs; /* Time at which to invoke */
|
unsigned long jiffies_force_qs; /* Time at which to invoke */
|
||||||
/* force_quiescent_state(). */
|
/* force_quiescent_state(). */
|
||||||
unsigned long n_force_qs; /* Number of calls to */
|
unsigned long n_force_qs; /* Number of calls to */
|
||||||
|
Reference in New Issue
Block a user