You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branches 'doc.2016.04.19a', 'exp.2016.03.31d', 'fixes.2016.03.31d' and 'torture.2016.04.21a' into HEAD
doc.2016.04.19a: Documentation updates exp.2016.03.31d: Expedited grace-period updates fixes.2016.03.31d: Miscellaneous fixes torture.2016.004.21a Torture-test updates
This commit is contained in:
@@ -237,17 +237,17 @@ o "ktl" is the low-order 16 bits (in hexadecimal) of the count of
|
|||||||
|
|
||||||
The output of "cat rcu/rcu_preempt/rcuexp" looks as follows:
|
The output of "cat rcu/rcu_preempt/rcuexp" looks as follows:
|
||||||
|
|
||||||
s=21872 wd0=0 wd1=0 wd2=0 wd3=5 n=0 enq=0 sc=21872
|
s=21872 wd1=0 wd2=0 wd3=5 n=0 enq=0 sc=21872
|
||||||
|
|
||||||
These fields are as follows:
|
These fields are as follows:
|
||||||
|
|
||||||
o "s" is the sequence number, with an odd number indicating that
|
o "s" is the sequence number, with an odd number indicating that
|
||||||
an expedited grace period is in progress.
|
an expedited grace period is in progress.
|
||||||
|
|
||||||
o "wd0", "wd1", "wd2", and "wd3" are the number of times that an
|
o "wd1", "wd2", and "wd3" are the number of times that an attempt
|
||||||
attempt to start an expedited grace period found that someone
|
to start an expedited grace period found that someone else had
|
||||||
else had completed an expedited grace period that satisfies the
|
completed an expedited grace period that satisfies the attempted
|
||||||
attempted request. "Our work is done."
|
request. "Our work is done."
|
||||||
|
|
||||||
o "n" is number of times that a concurrent CPU-hotplug operation
|
o "n" is number of times that a concurrent CPU-hotplug operation
|
||||||
forced a fallback to a normal grace period.
|
forced a fallback to a normal grace period.
|
||||||
|
|||||||
@@ -3284,6 +3284,44 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||||||
Lazy RCU callbacks are those which RCU can
|
Lazy RCU callbacks are those which RCU can
|
||||||
prove do nothing more than free memory.
|
prove do nothing more than free memory.
|
||||||
|
|
||||||
|
rcuperf.gp_exp= [KNL]
|
||||||
|
Measure performance of expedited synchronous
|
||||||
|
grace-period primitives.
|
||||||
|
|
||||||
|
rcuperf.holdoff= [KNL]
|
||||||
|
Set test-start holdoff period. The purpose of
|
||||||
|
this parameter is to delay the start of the
|
||||||
|
test until boot completes in order to avoid
|
||||||
|
interference.
|
||||||
|
|
||||||
|
rcuperf.nreaders= [KNL]
|
||||||
|
Set number of RCU readers. The value -1 selects
|
||||||
|
N, where N is the number of CPUs. A value
|
||||||
|
"n" less than -1 selects N-n+1, where N is again
|
||||||
|
the number of CPUs. For example, -2 selects N
|
||||||
|
(the number of CPUs), -3 selects N+1, and so on.
|
||||||
|
A value of "n" less than or equal to -N selects
|
||||||
|
a single reader.
|
||||||
|
|
||||||
|
rcuperf.nwriters= [KNL]
|
||||||
|
Set number of RCU writers. The values operate
|
||||||
|
the same as for rcuperf.nreaders.
|
||||||
|
N, where N is the number of CPUs
|
||||||
|
|
||||||
|
rcuperf.perf_runnable= [BOOT]
|
||||||
|
Start rcuperf running at boot time.
|
||||||
|
|
||||||
|
rcuperf.shutdown= [KNL]
|
||||||
|
Shut the system down after performance tests
|
||||||
|
complete. This is useful for hands-off automated
|
||||||
|
testing.
|
||||||
|
|
||||||
|
rcuperf.perf_type= [KNL]
|
||||||
|
Specify the RCU implementation to test.
|
||||||
|
|
||||||
|
rcuperf.verbose= [KNL]
|
||||||
|
Enable additional printk() statements.
|
||||||
|
|
||||||
rcutorture.cbflood_inter_holdoff= [KNL]
|
rcutorture.cbflood_inter_holdoff= [KNL]
|
||||||
Set holdoff time (jiffies) between successive
|
Set holdoff time (jiffies) between successive
|
||||||
callback-flood tests.
|
callback-flood tests.
|
||||||
|
|||||||
@@ -508,14 +508,7 @@ int rcu_read_lock_bh_held(void);
|
|||||||
* CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side
|
* CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side
|
||||||
* critical section unless it can prove otherwise.
|
* critical section unless it can prove otherwise.
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_PREEMPT_COUNT
|
|
||||||
int rcu_read_lock_sched_held(void);
|
int rcu_read_lock_sched_held(void);
|
||||||
#else /* #ifdef CONFIG_PREEMPT_COUNT */
|
|
||||||
static inline int rcu_read_lock_sched_held(void)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif /* #else #ifdef CONFIG_PREEMPT_COUNT */
|
|
||||||
|
|
||||||
#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
|
#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
|
||||||
|
|
||||||
@@ -532,18 +525,10 @@ static inline int rcu_read_lock_bh_held(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PREEMPT_COUNT
|
|
||||||
static inline int rcu_read_lock_sched_held(void)
|
static inline int rcu_read_lock_sched_held(void)
|
||||||
{
|
{
|
||||||
return preempt_count() != 0 || irqs_disabled();
|
return !preemptible();
|
||||||
}
|
}
|
||||||
#else /* #ifdef CONFIG_PREEMPT_COUNT */
|
|
||||||
static inline int rcu_read_lock_sched_held(void)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif /* #else #ifdef CONFIG_PREEMPT_COUNT */
|
|
||||||
|
|
||||||
#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
|
#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
|
||||||
|
|
||||||
#ifdef CONFIG_PROVE_RCU
|
#ifdef CONFIG_PROVE_RCU
|
||||||
|
|||||||
@@ -149,6 +149,22 @@ static inline unsigned long rcu_batches_completed_sched(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the number of expedited grace periods completed.
|
||||||
|
*/
|
||||||
|
static inline unsigned long rcu_exp_batches_completed(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the number of expedited sched grace periods completed.
|
||||||
|
*/
|
||||||
|
static inline unsigned long rcu_exp_batches_completed_sched(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void rcu_force_quiescent_state(void)
|
static inline void rcu_force_quiescent_state(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ unsigned long rcu_batches_started_sched(void);
|
|||||||
unsigned long rcu_batches_completed(void);
|
unsigned long rcu_batches_completed(void);
|
||||||
unsigned long rcu_batches_completed_bh(void);
|
unsigned long rcu_batches_completed_bh(void);
|
||||||
unsigned long rcu_batches_completed_sched(void);
|
unsigned long rcu_batches_completed_sched(void);
|
||||||
|
unsigned long rcu_exp_batches_completed(void);
|
||||||
|
unsigned long rcu_exp_batches_completed_sched(void);
|
||||||
void show_rcu_gp_kthreads(void);
|
void show_rcu_gp_kthreads(void);
|
||||||
|
|
||||||
void rcu_force_quiescent_state(void);
|
void rcu_force_quiescent_state(void);
|
||||||
|
|||||||
@@ -171,6 +171,77 @@ TRACE_EVENT(rcu_grace_period_init,
|
|||||||
__entry->grplo, __entry->grphi, __entry->qsmask)
|
__entry->grplo, __entry->grphi, __entry->qsmask)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tracepoint for expedited grace-period events. Takes a string identifying
|
||||||
|
* the RCU flavor, the expedited grace-period sequence number, and a string
|
||||||
|
* identifying the grace-period-related event as follows:
|
||||||
|
*
|
||||||
|
* "snap": Captured snapshot of expedited grace period sequence number.
|
||||||
|
* "start": Started a real expedited grace period.
|
||||||
|
* "end": Ended a real expedited grace period.
|
||||||
|
* "endwake": Woke piggybackers up.
|
||||||
|
* "done": Someone else did the expedited grace period for us.
|
||||||
|
*/
|
||||||
|
TRACE_EVENT(rcu_exp_grace_period,
|
||||||
|
|
||||||
|
TP_PROTO(const char *rcuname, unsigned long gpseq, const char *gpevent),
|
||||||
|
|
||||||
|
TP_ARGS(rcuname, gpseq, gpevent),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field(const char *, rcuname)
|
||||||
|
__field(unsigned long, gpseq)
|
||||||
|
__field(const char *, gpevent)
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->rcuname = rcuname;
|
||||||
|
__entry->gpseq = gpseq;
|
||||||
|
__entry->gpevent = gpevent;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("%s %lu %s",
|
||||||
|
__entry->rcuname, __entry->gpseq, __entry->gpevent)
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tracepoint for expedited grace-period funnel-locking events. Takes a
|
||||||
|
* string identifying the RCU flavor, an integer identifying the rcu_node
|
||||||
|
* combining-tree level, another pair of integers identifying the lowest-
|
||||||
|
* and highest-numbered CPU associated with the current rcu_node structure,
|
||||||
|
* and a string. identifying the grace-period-related event as follows:
|
||||||
|
*
|
||||||
|
* "nxtlvl": Advance to next level of rcu_node funnel
|
||||||
|
* "wait": Wait for someone else to do expedited GP
|
||||||
|
*/
|
||||||
|
TRACE_EVENT(rcu_exp_funnel_lock,
|
||||||
|
|
||||||
|
TP_PROTO(const char *rcuname, u8 level, int grplo, int grphi,
|
||||||
|
const char *gpevent),
|
||||||
|
|
||||||
|
TP_ARGS(rcuname, level, grplo, grphi, gpevent),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field(const char *, rcuname)
|
||||||
|
__field(u8, level)
|
||||||
|
__field(int, grplo)
|
||||||
|
__field(int, grphi)
|
||||||
|
__field(const char *, gpevent)
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->rcuname = rcuname;
|
||||||
|
__entry->level = level;
|
||||||
|
__entry->grplo = grplo;
|
||||||
|
__entry->grphi = grphi;
|
||||||
|
__entry->gpevent = gpevent;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("%s %d %d %d %s",
|
||||||
|
__entry->rcuname, __entry->level, __entry->grplo,
|
||||||
|
__entry->grphi, __entry->gpevent)
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tracepoint for RCU no-CBs CPU callback handoffs. This event is intended
|
* Tracepoint for RCU no-CBs CPU callback handoffs. This event is intended
|
||||||
* to assist debugging of these handoffs.
|
* to assist debugging of these handoffs.
|
||||||
@@ -704,11 +775,15 @@ TRACE_EVENT(rcu_barrier,
|
|||||||
#else /* #ifdef CONFIG_RCU_TRACE */
|
#else /* #ifdef CONFIG_RCU_TRACE */
|
||||||
|
|
||||||
#define trace_rcu_grace_period(rcuname, gpnum, gpevent) do { } while (0)
|
#define trace_rcu_grace_period(rcuname, gpnum, gpevent) do { } while (0)
|
||||||
#define trace_rcu_grace_period_init(rcuname, gpnum, level, grplo, grphi, \
|
|
||||||
qsmask) do { } while (0)
|
|
||||||
#define trace_rcu_future_grace_period(rcuname, gpnum, completed, c, \
|
#define trace_rcu_future_grace_period(rcuname, gpnum, completed, c, \
|
||||||
level, grplo, grphi, event) \
|
level, grplo, grphi, event) \
|
||||||
do { } while (0)
|
do { } while (0)
|
||||||
|
#define trace_rcu_grace_period_init(rcuname, gpnum, level, grplo, grphi, \
|
||||||
|
qsmask) do { } while (0)
|
||||||
|
#define trace_rcu_exp_grace_period(rcuname, gqseq, gpevent) \
|
||||||
|
do { } while (0)
|
||||||
|
#define trace_rcu_exp_funnel_lock(rcuname, level, grplo, grphi, gpevent) \
|
||||||
|
do { } while (0)
|
||||||
#define trace_rcu_nocb_wake(rcuname, cpu, reason) do { } while (0)
|
#define trace_rcu_nocb_wake(rcuname, cpu, reason) do { } while (0)
|
||||||
#define trace_rcu_preempt_task(rcuname, pid, gpnum) do { } while (0)
|
#define trace_rcu_preempt_task(rcuname, pid, gpnum) do { } while (0)
|
||||||
#define trace_rcu_unlock_preempted_task(rcuname, gpnum, pid) do { } while (0)
|
#define trace_rcu_unlock_preempted_task(rcuname, gpnum, pid) do { } while (0)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ KCOV_INSTRUMENT := n
|
|||||||
obj-y += update.o sync.o
|
obj-y += update.o sync.o
|
||||||
obj-$(CONFIG_SRCU) += srcu.o
|
obj-$(CONFIG_SRCU) += srcu.o
|
||||||
obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
|
obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
|
||||||
|
obj-$(CONFIG_RCU_PERF_TEST) += rcuperf.o
|
||||||
obj-$(CONFIG_TREE_RCU) += tree.o
|
obj-$(CONFIG_TREE_RCU) += tree.o
|
||||||
obj-$(CONFIG_PREEMPT_RCU) += tree.o
|
obj-$(CONFIG_PREEMPT_RCU) += tree.o
|
||||||
obj-$(CONFIG_TREE_RCU_TRACE) += tree_trace.o
|
obj-$(CONFIG_TREE_RCU_TRACE) += tree_trace.o
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -130,8 +130,8 @@ static struct rcu_torture __rcu *rcu_torture_current;
|
|||||||
static unsigned long rcu_torture_current_version;
|
static unsigned long rcu_torture_current_version;
|
||||||
static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
|
static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
|
||||||
static DEFINE_SPINLOCK(rcu_torture_lock);
|
static DEFINE_SPINLOCK(rcu_torture_lock);
|
||||||
static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) = { 0 };
|
static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count);
|
||||||
static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_batch) = { 0 };
|
static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_batch);
|
||||||
static atomic_t rcu_torture_wcount[RCU_TORTURE_PIPE_LEN + 1];
|
static atomic_t rcu_torture_wcount[RCU_TORTURE_PIPE_LEN + 1];
|
||||||
static atomic_t n_rcu_torture_alloc;
|
static atomic_t n_rcu_torture_alloc;
|
||||||
static atomic_t n_rcu_torture_alloc_fail;
|
static atomic_t n_rcu_torture_alloc_fail;
|
||||||
@@ -916,7 +916,7 @@ rcu_torture_fqs(void *arg)
|
|||||||
static int
|
static int
|
||||||
rcu_torture_writer(void *arg)
|
rcu_torture_writer(void *arg)
|
||||||
{
|
{
|
||||||
bool can_expedite = !rcu_gp_is_expedited();
|
bool can_expedite = !rcu_gp_is_expedited() && !rcu_gp_is_normal();
|
||||||
int expediting = 0;
|
int expediting = 0;
|
||||||
unsigned long gp_snap;
|
unsigned long gp_snap;
|
||||||
bool gp_cond1 = gp_cond, gp_exp1 = gp_exp, gp_normal1 = gp_normal;
|
bool gp_cond1 = gp_cond, gp_exp1 = gp_exp, gp_normal1 = gp_normal;
|
||||||
@@ -932,7 +932,7 @@ rcu_torture_writer(void *arg)
|
|||||||
VERBOSE_TOROUT_STRING("rcu_torture_writer task started");
|
VERBOSE_TOROUT_STRING("rcu_torture_writer task started");
|
||||||
if (!can_expedite) {
|
if (!can_expedite) {
|
||||||
pr_alert("%s" TORTURE_FLAG
|
pr_alert("%s" TORTURE_FLAG
|
||||||
" Grace periods expedited from boot/sysfs for %s,\n",
|
" GP expediting controlled from boot/sysfs for %s,\n",
|
||||||
torture_type, cur_ops->name);
|
torture_type, cur_ops->name);
|
||||||
pr_alert("%s" TORTURE_FLAG
|
pr_alert("%s" TORTURE_FLAG
|
||||||
" Disabled dynamic grace-period expediting.\n",
|
" Disabled dynamic grace-period expediting.\n",
|
||||||
@@ -1478,7 +1478,9 @@ static int rcu_torture_barrier_cbs(void *arg)
|
|||||||
* The above smp_load_acquire() ensures barrier_phase load
|
* The above smp_load_acquire() ensures barrier_phase load
|
||||||
* is ordered before the folloiwng ->call().
|
* is ordered before the folloiwng ->call().
|
||||||
*/
|
*/
|
||||||
|
local_irq_disable(); /* Just to test no-irq call_rcu(). */
|
||||||
cur_ops->call(&rcu, rcu_torture_barrier_cbf);
|
cur_ops->call(&rcu, rcu_torture_barrier_cbf);
|
||||||
|
local_irq_enable();
|
||||||
if (atomic_dec_and_test(&barrier_cbs_count))
|
if (atomic_dec_and_test(&barrier_cbs_count))
|
||||||
wake_up(&barrier_wq);
|
wake_up(&barrier_wq);
|
||||||
} while (!torture_must_stop());
|
} while (!torture_must_stop());
|
||||||
@@ -1585,7 +1587,7 @@ static int rcutorture_cpu_notify(struct notifier_block *self,
|
|||||||
{
|
{
|
||||||
long cpu = (long)hcpu;
|
long cpu = (long)hcpu;
|
||||||
|
|
||||||
switch (action) {
|
switch (action & ~CPU_TASKS_FROZEN) {
|
||||||
case CPU_ONLINE:
|
case CPU_ONLINE:
|
||||||
case CPU_DOWN_FAILED:
|
case CPU_DOWN_FAILED:
|
||||||
(void)rcutorture_booster_init(cpu);
|
(void)rcutorture_booster_init(cpu);
|
||||||
|
|||||||
+211
-87
File diff suppressed because it is too large
Load Diff
+10
-10
@@ -70,7 +70,6 @@
|
|||||||
# define NUM_RCU_LVL_INIT { NUM_RCU_LVL_0 }
|
# define NUM_RCU_LVL_INIT { NUM_RCU_LVL_0 }
|
||||||
# define RCU_NODE_NAME_INIT { "rcu_node_0" }
|
# define RCU_NODE_NAME_INIT { "rcu_node_0" }
|
||||||
# define RCU_FQS_NAME_INIT { "rcu_node_fqs_0" }
|
# define RCU_FQS_NAME_INIT { "rcu_node_fqs_0" }
|
||||||
# define RCU_EXP_NAME_INIT { "rcu_node_exp_0" }
|
|
||||||
#elif NR_CPUS <= RCU_FANOUT_2
|
#elif NR_CPUS <= RCU_FANOUT_2
|
||||||
# define RCU_NUM_LVLS 2
|
# define RCU_NUM_LVLS 2
|
||||||
# define NUM_RCU_LVL_0 1
|
# define NUM_RCU_LVL_0 1
|
||||||
@@ -79,7 +78,6 @@
|
|||||||
# define NUM_RCU_LVL_INIT { NUM_RCU_LVL_0, NUM_RCU_LVL_1 }
|
# define NUM_RCU_LVL_INIT { NUM_RCU_LVL_0, NUM_RCU_LVL_1 }
|
||||||
# define RCU_NODE_NAME_INIT { "rcu_node_0", "rcu_node_1" }
|
# define RCU_NODE_NAME_INIT { "rcu_node_0", "rcu_node_1" }
|
||||||
# define RCU_FQS_NAME_INIT { "rcu_node_fqs_0", "rcu_node_fqs_1" }
|
# define RCU_FQS_NAME_INIT { "rcu_node_fqs_0", "rcu_node_fqs_1" }
|
||||||
# define RCU_EXP_NAME_INIT { "rcu_node_exp_0", "rcu_node_exp_1" }
|
|
||||||
#elif NR_CPUS <= RCU_FANOUT_3
|
#elif NR_CPUS <= RCU_FANOUT_3
|
||||||
# define RCU_NUM_LVLS 3
|
# define RCU_NUM_LVLS 3
|
||||||
# define NUM_RCU_LVL_0 1
|
# define NUM_RCU_LVL_0 1
|
||||||
@@ -89,7 +87,6 @@
|
|||||||
# define NUM_RCU_LVL_INIT { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2 }
|
# define NUM_RCU_LVL_INIT { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2 }
|
||||||
# define RCU_NODE_NAME_INIT { "rcu_node_0", "rcu_node_1", "rcu_node_2" }
|
# define RCU_NODE_NAME_INIT { "rcu_node_0", "rcu_node_1", "rcu_node_2" }
|
||||||
# define RCU_FQS_NAME_INIT { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2" }
|
# define RCU_FQS_NAME_INIT { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2" }
|
||||||
# define RCU_EXP_NAME_INIT { "rcu_node_exp_0", "rcu_node_exp_1", "rcu_node_exp_2" }
|
|
||||||
#elif NR_CPUS <= RCU_FANOUT_4
|
#elif NR_CPUS <= RCU_FANOUT_4
|
||||||
# define RCU_NUM_LVLS 4
|
# define RCU_NUM_LVLS 4
|
||||||
# define NUM_RCU_LVL_0 1
|
# define NUM_RCU_LVL_0 1
|
||||||
@@ -100,7 +97,6 @@
|
|||||||
# define NUM_RCU_LVL_INIT { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2, NUM_RCU_LVL_3 }
|
# define NUM_RCU_LVL_INIT { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2, NUM_RCU_LVL_3 }
|
||||||
# define RCU_NODE_NAME_INIT { "rcu_node_0", "rcu_node_1", "rcu_node_2", "rcu_node_3" }
|
# define RCU_NODE_NAME_INIT { "rcu_node_0", "rcu_node_1", "rcu_node_2", "rcu_node_3" }
|
||||||
# define RCU_FQS_NAME_INIT { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2", "rcu_node_fqs_3" }
|
# define RCU_FQS_NAME_INIT { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2", "rcu_node_fqs_3" }
|
||||||
# define RCU_EXP_NAME_INIT { "rcu_node_exp_0", "rcu_node_exp_1", "rcu_node_exp_2", "rcu_node_exp_3" }
|
|
||||||
#else
|
#else
|
||||||
# error "CONFIG_RCU_FANOUT insufficient for NR_CPUS"
|
# error "CONFIG_RCU_FANOUT insufficient for NR_CPUS"
|
||||||
#endif /* #if (NR_CPUS) <= RCU_FANOUT_1 */
|
#endif /* #if (NR_CPUS) <= RCU_FANOUT_1 */
|
||||||
@@ -252,7 +248,9 @@ struct rcu_node {
|
|||||||
/* Counts of upcoming no-CB GP requests. */
|
/* Counts of upcoming no-CB GP requests. */
|
||||||
raw_spinlock_t fqslock ____cacheline_internodealigned_in_smp;
|
raw_spinlock_t fqslock ____cacheline_internodealigned_in_smp;
|
||||||
|
|
||||||
struct mutex exp_funnel_mutex ____cacheline_internodealigned_in_smp;
|
spinlock_t exp_lock ____cacheline_internodealigned_in_smp;
|
||||||
|
unsigned long exp_seq_rq;
|
||||||
|
wait_queue_head_t exp_wq[4];
|
||||||
} ____cacheline_internodealigned_in_smp;
|
} ____cacheline_internodealigned_in_smp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -387,11 +385,9 @@ struct rcu_data {
|
|||||||
#ifdef CONFIG_RCU_FAST_NO_HZ
|
#ifdef CONFIG_RCU_FAST_NO_HZ
|
||||||
struct rcu_head oom_head;
|
struct rcu_head oom_head;
|
||||||
#endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */
|
#endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */
|
||||||
struct mutex exp_funnel_mutex;
|
atomic_long_t exp_workdone1; /* # done by others #1. */
|
||||||
atomic_long_t expedited_workdone0; /* # done by others #0. */
|
atomic_long_t exp_workdone2; /* # done by others #2. */
|
||||||
atomic_long_t expedited_workdone1; /* # done by others #1. */
|
atomic_long_t exp_workdone3; /* # done by others #3. */
|
||||||
atomic_long_t expedited_workdone2; /* # done by others #2. */
|
|
||||||
atomic_long_t expedited_workdone3; /* # done by others #3. */
|
|
||||||
|
|
||||||
/* 7) Callback offloading. */
|
/* 7) Callback offloading. */
|
||||||
#ifdef CONFIG_RCU_NOCB_CPU
|
#ifdef CONFIG_RCU_NOCB_CPU
|
||||||
@@ -505,6 +501,8 @@ struct rcu_state {
|
|||||||
/* _rcu_barrier(). */
|
/* _rcu_barrier(). */
|
||||||
/* End of fields guarded by barrier_mutex. */
|
/* End of fields guarded by barrier_mutex. */
|
||||||
|
|
||||||
|
struct mutex exp_mutex; /* Serialize expedited GP. */
|
||||||
|
struct mutex exp_wake_mutex; /* Serialize wakeup. */
|
||||||
unsigned long expedited_sequence; /* Take a ticket. */
|
unsigned long expedited_sequence; /* Take a ticket. */
|
||||||
atomic_long_t expedited_normal; /* # fallbacks to normal. */
|
atomic_long_t expedited_normal; /* # fallbacks to normal. */
|
||||||
atomic_t expedited_need_qs; /* # CPUs left to check in. */
|
atomic_t expedited_need_qs; /* # CPUs left to check in. */
|
||||||
@@ -513,6 +511,8 @@ struct rcu_state {
|
|||||||
|
|
||||||
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 jiffies_kick_kthreads; /* Time at which to kick */
|
||||||
|
/* kthreads, if configured. */
|
||||||
unsigned long n_force_qs; /* Number of calls to */
|
unsigned long n_force_qs; /* Number of calls to */
|
||||||
/* force_quiescent_state(). */
|
/* force_quiescent_state(). */
|
||||||
unsigned long n_force_qs_lh; /* ~Number of calls leaving */
|
unsigned long n_force_qs_lh; /* ~Number of calls leaving */
|
||||||
|
|||||||
+16
-21
@@ -722,18 +722,22 @@ static void sync_rcu_exp_handler(void *info)
|
|||||||
* synchronize_rcu_expedited - Brute-force RCU grace period
|
* synchronize_rcu_expedited - Brute-force RCU grace period
|
||||||
*
|
*
|
||||||
* Wait for an RCU-preempt grace period, but expedite it. The basic
|
* Wait for an RCU-preempt grace period, but expedite it. The basic
|
||||||
* idea is to invoke synchronize_sched_expedited() to push all the tasks to
|
* idea is to IPI all non-idle non-nohz online CPUs. The IPI handler
|
||||||
* the ->blkd_tasks lists and wait for this list to drain. This consumes
|
* checks whether the CPU is in an RCU-preempt critical section, and
|
||||||
* significant time on all CPUs and is unfriendly to real-time workloads,
|
* if so, it sets a flag that causes the outermost rcu_read_unlock()
|
||||||
* so is thus not recommended for any sort of common-case code.
|
* to report the quiescent state. On the other hand, if the CPU is
|
||||||
* In fact, if you are using synchronize_rcu_expedited() in a loop,
|
* not in an RCU read-side critical section, the IPI handler reports
|
||||||
* please restructure your code to batch your updates, and then Use a
|
* the quiescent state immediately.
|
||||||
* single synchronize_rcu() instead.
|
*
|
||||||
|
* Although this is a greate improvement over previous expedited
|
||||||
|
* implementations, it is still unfriendly to real-time workloads, so is
|
||||||
|
* thus not recommended for any sort of common-case code. In fact, if
|
||||||
|
* you are using synchronize_rcu_expedited() in a loop, please restructure
|
||||||
|
* your code to batch your updates, and then Use a single synchronize_rcu()
|
||||||
|
* instead.
|
||||||
*/
|
*/
|
||||||
void synchronize_rcu_expedited(void)
|
void synchronize_rcu_expedited(void)
|
||||||
{
|
{
|
||||||
struct rcu_node *rnp;
|
|
||||||
struct rcu_node *rnp_unlock;
|
|
||||||
struct rcu_state *rsp = rcu_state_p;
|
struct rcu_state *rsp = rcu_state_p;
|
||||||
unsigned long s;
|
unsigned long s;
|
||||||
|
|
||||||
@@ -744,23 +748,14 @@ void synchronize_rcu_expedited(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
s = rcu_exp_gp_seq_snap(rsp);
|
s = rcu_exp_gp_seq_snap(rsp);
|
||||||
|
if (exp_funnel_lock(rsp, s))
|
||||||
rnp_unlock = exp_funnel_lock(rsp, s);
|
|
||||||
if (rnp_unlock == NULL)
|
|
||||||
return; /* Someone else did our work for us. */
|
return; /* Someone else did our work for us. */
|
||||||
|
|
||||||
rcu_exp_gp_seq_start(rsp);
|
|
||||||
|
|
||||||
/* Initialize the rcu_node tree in preparation for the wait. */
|
/* Initialize the rcu_node tree in preparation for the wait. */
|
||||||
sync_rcu_exp_select_cpus(rsp, sync_rcu_exp_handler);
|
sync_rcu_exp_select_cpus(rsp, sync_rcu_exp_handler);
|
||||||
|
|
||||||
/* Wait for snapshotted ->blkd_tasks lists to drain. */
|
/* Wait for ->blkd_tasks lists to drain, then wake everyone up. */
|
||||||
rnp = rcu_get_root(rsp);
|
rcu_exp_wait_wake(rsp, s);
|
||||||
synchronize_sched_expedited_wait(rsp);
|
|
||||||
|
|
||||||
/* Clean up and exit. */
|
|
||||||
rcu_exp_gp_seq_end(rsp);
|
|
||||||
mutex_unlock(&rnp_unlock->exp_funnel_mutex);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
|
EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
|
||||||
|
|
||||||
|
|||||||
@@ -185,17 +185,16 @@ static int show_rcuexp(struct seq_file *m, void *v)
|
|||||||
int cpu;
|
int cpu;
|
||||||
struct rcu_state *rsp = (struct rcu_state *)m->private;
|
struct rcu_state *rsp = (struct rcu_state *)m->private;
|
||||||
struct rcu_data *rdp;
|
struct rcu_data *rdp;
|
||||||
unsigned long s0 = 0, s1 = 0, s2 = 0, s3 = 0;
|
unsigned long s1 = 0, s2 = 0, s3 = 0;
|
||||||
|
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu) {
|
||||||
rdp = per_cpu_ptr(rsp->rda, cpu);
|
rdp = per_cpu_ptr(rsp->rda, cpu);
|
||||||
s0 += atomic_long_read(&rdp->expedited_workdone0);
|
s1 += atomic_long_read(&rdp->exp_workdone1);
|
||||||
s1 += atomic_long_read(&rdp->expedited_workdone1);
|
s2 += atomic_long_read(&rdp->exp_workdone2);
|
||||||
s2 += atomic_long_read(&rdp->expedited_workdone2);
|
s3 += atomic_long_read(&rdp->exp_workdone3);
|
||||||
s3 += atomic_long_read(&rdp->expedited_workdone3);
|
|
||||||
}
|
}
|
||||||
seq_printf(m, "s=%lu wd0=%lu wd1=%lu wd2=%lu wd3=%lu n=%lu enq=%d sc=%lu\n",
|
seq_printf(m, "s=%lu wd1=%lu wd2=%lu wd3=%lu n=%lu enq=%d sc=%lu\n",
|
||||||
rsp->expedited_sequence, s0, s1, s2, s3,
|
rsp->expedited_sequence, s1, s2, s3,
|
||||||
atomic_long_read(&rsp->expedited_normal),
|
atomic_long_read(&rsp->expedited_normal),
|
||||||
atomic_read(&rsp->expedited_need_qs),
|
atomic_read(&rsp->expedited_need_qs),
|
||||||
rsp->expedited_sequence / 2);
|
rsp->expedited_sequence / 2);
|
||||||
|
|||||||
+2
-2
@@ -67,7 +67,7 @@ static int rcu_normal_after_boot;
|
|||||||
module_param(rcu_normal_after_boot, int, 0);
|
module_param(rcu_normal_after_boot, int, 0);
|
||||||
#endif /* #ifndef CONFIG_TINY_RCU */
|
#endif /* #ifndef CONFIG_TINY_RCU */
|
||||||
|
|
||||||
#if defined(CONFIG_DEBUG_LOCK_ALLOC) && defined(CONFIG_PREEMPT_COUNT)
|
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||||
/**
|
/**
|
||||||
* rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section?
|
* rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section?
|
||||||
*
|
*
|
||||||
@@ -111,7 +111,7 @@ int rcu_read_lock_sched_held(void)
|
|||||||
return 0;
|
return 0;
|
||||||
if (debug_locks)
|
if (debug_locks)
|
||||||
lockdep_opinion = lock_is_held(&rcu_sched_lock_map);
|
lockdep_opinion = lock_is_held(&rcu_sched_lock_map);
|
||||||
return lockdep_opinion || preempt_count() != 0 || irqs_disabled();
|
return lockdep_opinion || !preemptible();
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(rcu_read_lock_sched_held);
|
EXPORT_SYMBOL(rcu_read_lock_sched_held);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+3
-1
@@ -451,6 +451,7 @@ static int torture_shutdown(void *arg)
|
|||||||
torture_shutdown_hook();
|
torture_shutdown_hook();
|
||||||
else
|
else
|
||||||
VERBOSE_TOROUT_STRING("No torture_shutdown_hook(), skipping.");
|
VERBOSE_TOROUT_STRING("No torture_shutdown_hook(), skipping.");
|
||||||
|
ftrace_dump(DUMP_ALL);
|
||||||
kernel_power_off(); /* Shut down the system. */
|
kernel_power_off(); /* Shut down the system. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -602,8 +603,9 @@ bool torture_init_begin(char *ttype, bool v, int *runnable)
|
|||||||
{
|
{
|
||||||
mutex_lock(&fullstop_mutex);
|
mutex_lock(&fullstop_mutex);
|
||||||
if (torture_type != NULL) {
|
if (torture_type != NULL) {
|
||||||
pr_alert("torture_init_begin: refusing %s init: %s running",
|
pr_alert("torture_init_begin: Refusing %s init: %s running.\n",
|
||||||
ttype, torture_type);
|
ttype, torture_type);
|
||||||
|
pr_alert("torture_init_begin: One torture test at a time!\n");
|
||||||
mutex_unlock(&fullstop_mutex);
|
mutex_unlock(&fullstop_mutex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1289,6 +1289,39 @@ config TORTURE_TEST
|
|||||||
tristate
|
tristate
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config RCU_PERF_TEST
|
||||||
|
tristate "performance tests for RCU"
|
||||||
|
depends on DEBUG_KERNEL
|
||||||
|
select TORTURE_TEST
|
||||||
|
select SRCU
|
||||||
|
select TASKS_RCU
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
This option provides a kernel module that runs performance
|
||||||
|
tests on the RCU infrastructure. The kernel module may be built
|
||||||
|
after the fact on the running kernel to be tested, if desired.
|
||||||
|
|
||||||
|
Say Y here if you want RCU performance tests to be built into
|
||||||
|
the kernel.
|
||||||
|
Say M if you want the RCU performance tests to build as a module.
|
||||||
|
Say N if you are unsure.
|
||||||
|
|
||||||
|
config RCU_PERF_TEST_RUNNABLE
|
||||||
|
bool "performance tests for RCU runnable by default"
|
||||||
|
depends on RCU_PERF_TEST = y
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
This option provides a way to build the RCU performance tests
|
||||||
|
directly into the kernel without them starting up at boot time.
|
||||||
|
You can use /sys/module to manually override this setting.
|
||||||
|
This /proc file is available only when the RCU performance
|
||||||
|
tests have been built into the kernel.
|
||||||
|
|
||||||
|
Say Y here if you want the RCU performance tests to start during
|
||||||
|
boot (you probably don't).
|
||||||
|
Say N here if you want the RCU performance tests to start only
|
||||||
|
after being manually enabled via /sys/module.
|
||||||
|
|
||||||
config RCU_TORTURE_TEST
|
config RCU_TORTURE_TEST
|
||||||
tristate "torture tests for RCU"
|
tristate "torture tests for RCU"
|
||||||
depends on DEBUG_KERNEL
|
depends on DEBUG_KERNEL
|
||||||
|
|||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Alternate sleeping and spinning on randomly selected CPUs. The purpose
|
||||||
|
# of this script is to inflict random OS jitter on a concurrently running
|
||||||
|
# test.
|
||||||
|
#
|
||||||
|
# Usage: jitter.sh me duration [ sleepmax [ spinmax ] ]
|
||||||
|
#
|
||||||
|
# me: Random-number-generator seed salt.
|
||||||
|
# duration: Time to run in seconds.
|
||||||
|
# sleepmax: Maximum microseconds to sleep, defaults to one second.
|
||||||
|
# spinmax: Maximum microseconds to spin, defaults to one millisecond.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, you can access it online at
|
||||||
|
# http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
|
#
|
||||||
|
# Copyright (C) IBM Corporation, 2016
|
||||||
|
#
|
||||||
|
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
|
||||||
|
|
||||||
|
me=$(($1 * 1000))
|
||||||
|
duration=$2
|
||||||
|
sleepmax=${3-1000000}
|
||||||
|
spinmax=${4-1000}
|
||||||
|
|
||||||
|
n=1
|
||||||
|
|
||||||
|
starttime=`awk 'BEGIN { print systime(); }' < /dev/null`
|
||||||
|
|
||||||
|
while :
|
||||||
|
do
|
||||||
|
# Check for done.
|
||||||
|
t=`awk -v s=$starttime 'BEGIN { print systime() - s; }' < /dev/null`
|
||||||
|
if test "$t" -gt "$duration"
|
||||||
|
then
|
||||||
|
exit 0;
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set affinity to randomly selected CPU
|
||||||
|
cpus=`ls /sys/devices/system/cpu/*/online |
|
||||||
|
sed -e 's,/[^/]*$,,' -e 's/^[^0-9]*//' |
|
||||||
|
grep -v '^0*$'`
|
||||||
|
cpumask=`awk -v cpus="$cpus" -v me=$me -v n=$n 'BEGIN {
|
||||||
|
srand(n + me + systime());
|
||||||
|
ncpus = split(cpus, ca);
|
||||||
|
curcpu = ca[int(rand() * ncpus + 1)];
|
||||||
|
mask = lshift(1, curcpu);
|
||||||
|
if (mask + 0 <= 0)
|
||||||
|
mask = 1;
|
||||||
|
printf("%#x\n", mask);
|
||||||
|
}' < /dev/null`
|
||||||
|
n=$(($n+1))
|
||||||
|
if ! taskset -p $cpumask $$ > /dev/null 2>&1
|
||||||
|
then
|
||||||
|
echo taskset failure: '"taskset -p ' $cpumask $$ '"'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sleep a random duration
|
||||||
|
sleeptime=`awk -v me=$me -v n=$n -v sleepmax=$sleepmax 'BEGIN {
|
||||||
|
srand(n + me + systime());
|
||||||
|
printf("%06d", int(rand() * sleepmax));
|
||||||
|
}' < /dev/null`
|
||||||
|
n=$(($n+1))
|
||||||
|
sleep .$sleeptime
|
||||||
|
|
||||||
|
# Spin a random duration
|
||||||
|
limit=`awk -v me=$me -v n=$n -v spinmax=$spinmax 'BEGIN {
|
||||||
|
srand(n + me + systime());
|
||||||
|
printf("%06d", int(rand() * spinmax));
|
||||||
|
}' < /dev/null`
|
||||||
|
n=$(($n+1))
|
||||||
|
for i in {1..$limit}
|
||||||
|
do
|
||||||
|
echo > /dev/null
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 1
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Analyze a given results directory for rcuperf performance measurements,
|
||||||
|
# looking for ftrace data. Exits with 0 if data was found, analyzed, and
|
||||||
|
# printed. Intended to be invoked from kvm-recheck-rcuperf.sh after
|
||||||
|
# argument checking.
|
||||||
|
#
|
||||||
|
# Usage: kvm-recheck-rcuperf-ftrace.sh resdir
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, you can access it online at
|
||||||
|
# http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
|
#
|
||||||
|
# Copyright (C) IBM Corporation, 2016
|
||||||
|
#
|
||||||
|
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
|
||||||
|
|
||||||
|
i="$1"
|
||||||
|
. tools/testing/selftests/rcutorture/bin/functions.sh
|
||||||
|
|
||||||
|
if test "`grep -c 'rcu_exp_grace_period.*start' < $i/console.log`" -lt 100
|
||||||
|
then
|
||||||
|
exit 10
|
||||||
|
fi
|
||||||
|
|
||||||
|
sed -e 's/^\[[^]]*]//' < $i/console.log |
|
||||||
|
grep 'us : rcu_exp_grace_period' |
|
||||||
|
sed -e 's/us : / : /' |
|
||||||
|
tr -d '\015' |
|
||||||
|
awk '
|
||||||
|
$8 == "start" {
|
||||||
|
if (starttask != "")
|
||||||
|
nlost++;
|
||||||
|
starttask = $1;
|
||||||
|
starttime = $3;
|
||||||
|
startseq = $7;
|
||||||
|
}
|
||||||
|
|
||||||
|
$8 == "end" {
|
||||||
|
if (starttask == $1 && startseq == $7) {
|
||||||
|
curgpdur = $3 - starttime;
|
||||||
|
gptimes[++n] = curgpdur;
|
||||||
|
gptaskcnt[starttask]++;
|
||||||
|
sum += curgpdur;
|
||||||
|
if (curgpdur > 1000)
|
||||||
|
print "Long GP " starttime "us to " $3 "us (" curgpdur "us)";
|
||||||
|
starttask = "";
|
||||||
|
} else {
|
||||||
|
# Lost a message or some such, reset.
|
||||||
|
starttask = "";
|
||||||
|
nlost++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$8 == "done" {
|
||||||
|
piggybackcnt[$1]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
newNR = asort(gptimes);
|
||||||
|
if (newNR <= 0) {
|
||||||
|
print "No ftrace records found???"
|
||||||
|
exit 10;
|
||||||
|
}
|
||||||
|
pct50 = int(newNR * 50 / 100);
|
||||||
|
if (pct50 < 1)
|
||||||
|
pct50 = 1;
|
||||||
|
pct90 = int(newNR * 90 / 100);
|
||||||
|
if (pct90 < 1)
|
||||||
|
pct90 = 1;
|
||||||
|
pct99 = int(newNR * 99 / 100);
|
||||||
|
if (pct99 < 1)
|
||||||
|
pct99 = 1;
|
||||||
|
div = 10 ** int(log(gptimes[pct90]) / log(10) + .5) / 100;
|
||||||
|
print "Histogram bucket size: " div;
|
||||||
|
last = gptimes[1] - 10;
|
||||||
|
count = 0;
|
||||||
|
for (i = 1; i <= newNR; i++) {
|
||||||
|
current = div * int(gptimes[i] / div);
|
||||||
|
if (last == current) {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
if (count > 0)
|
||||||
|
print last, count;
|
||||||
|
count = 1;
|
||||||
|
last = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count > 0)
|
||||||
|
print last, count;
|
||||||
|
print "Distribution of grace periods across tasks:";
|
||||||
|
for (i in gptaskcnt) {
|
||||||
|
print "\t" i, gptaskcnt[i];
|
||||||
|
nbatches += gptaskcnt[i];
|
||||||
|
}
|
||||||
|
ngps = nbatches;
|
||||||
|
print "Distribution of piggybacking across tasks:";
|
||||||
|
for (i in piggybackcnt) {
|
||||||
|
print "\t" i, piggybackcnt[i];
|
||||||
|
ngps += piggybackcnt[i];
|
||||||
|
}
|
||||||
|
print "Average grace-period duration: " sum / newNR " microseconds";
|
||||||
|
print "Minimum grace-period duration: " gptimes[1];
|
||||||
|
print "50th percentile grace-period duration: " gptimes[pct50];
|
||||||
|
print "90th percentile grace-period duration: " gptimes[pct90];
|
||||||
|
print "99th percentile grace-period duration: " gptimes[pct99];
|
||||||
|
print "Maximum grace-period duration: " gptimes[newNR];
|
||||||
|
print "Grace periods: " ngps + 0 " Batches: " nbatches + 0 " Ratio: " ngps / nbatches " Lost: " nlost + 0;
|
||||||
|
print "Computed from ftrace data.";
|
||||||
|
}'
|
||||||
|
exit 0
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Analyze a given results directory for rcuperf performance measurements.
|
||||||
|
#
|
||||||
|
# Usage: kvm-recheck-rcuperf.sh resdir
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, you can access it online at
|
||||||
|
# http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
|
#
|
||||||
|
# Copyright (C) IBM Corporation, 2016
|
||||||
|
#
|
||||||
|
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
|
||||||
|
|
||||||
|
i="$1"
|
||||||
|
if test -d $i
|
||||||
|
then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
echo Unreadable results directory: $i
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH
|
||||||
|
. tools/testing/selftests/rcutorture/bin/functions.sh
|
||||||
|
|
||||||
|
if kvm-recheck-rcuperf-ftrace.sh $i
|
||||||
|
then
|
||||||
|
# ftrace data was successfully analyzed, call it good!
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
configfile=`echo $i | sed -e 's/^.*\///'`
|
||||||
|
|
||||||
|
sed -e 's/^\[[^]]*]//' < $i/console.log |
|
||||||
|
awk '
|
||||||
|
/-perf: .* gps: .* batches:/ {
|
||||||
|
ngps = $9;
|
||||||
|
nbatches = $11;
|
||||||
|
}
|
||||||
|
|
||||||
|
/-perf: .*writer-duration/ {
|
||||||
|
gptimes[++n] = $5 / 1000.;
|
||||||
|
sum += $5 / 1000.;
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
newNR = asort(gptimes);
|
||||||
|
if (newNR <= 0) {
|
||||||
|
print "No rcuperf records found???"
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
pct50 = int(newNR * 50 / 100);
|
||||||
|
if (pct50 < 1)
|
||||||
|
pct50 = 1;
|
||||||
|
pct90 = int(newNR * 90 / 100);
|
||||||
|
if (pct90 < 1)
|
||||||
|
pct90 = 1;
|
||||||
|
pct99 = int(newNR * 99 / 100);
|
||||||
|
if (pct99 < 1)
|
||||||
|
pct99 = 1;
|
||||||
|
div = 10 ** int(log(gptimes[pct90]) / log(10) + .5) / 100;
|
||||||
|
print "Histogram bucket size: " div;
|
||||||
|
last = gptimes[1] - 10;
|
||||||
|
count = 0;
|
||||||
|
for (i = 1; i <= newNR; i++) {
|
||||||
|
current = div * int(gptimes[i] / div);
|
||||||
|
if (last == current) {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
if (count > 0)
|
||||||
|
print last, count;
|
||||||
|
count = 1;
|
||||||
|
last = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count > 0)
|
||||||
|
print last, count;
|
||||||
|
print "Average grace-period duration: " sum / newNR " microseconds";
|
||||||
|
print "Minimum grace-period duration: " gptimes[1];
|
||||||
|
print "50th percentile grace-period duration: " gptimes[pct50];
|
||||||
|
print "90th percentile grace-period duration: " gptimes[pct90];
|
||||||
|
print "99th percentile grace-period duration: " gptimes[pct99];
|
||||||
|
print "Maximum grace-period duration: " gptimes[newNR];
|
||||||
|
print "Grace periods: " ngps + 0 " Batches: " nbatches + 0 " Ratio: " ngps / nbatches;
|
||||||
|
print "Computed from rcuperf printk output.";
|
||||||
|
}'
|
||||||
@@ -48,7 +48,10 @@ do
|
|||||||
cat $i/Make.oldconfig.err
|
cat $i/Make.oldconfig.err
|
||||||
fi
|
fi
|
||||||
parse-build.sh $i/Make.out $configfile
|
parse-build.sh $i/Make.out $configfile
|
||||||
parse-torture.sh $i/console.log $configfile
|
if test "$TORTURE_SUITE" != rcuperf
|
||||||
|
then
|
||||||
|
parse-torture.sh $i/console.log $configfile
|
||||||
|
fi
|
||||||
parse-console.sh $i/console.log $configfile
|
parse-console.sh $i/console.log $configfile
|
||||||
if test -r $i/Warnings
|
if test -r $i/Warnings
|
||||||
then
|
then
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user