diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2013-10-15 15:47:04 -0400 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2013-10-15 15:47:04 -0400 |
commit | 25e03a74e4a14e0d52a66fb56c728f049a6a26d3 (patch) | |
tree | 7302bd505a14a05e0ad1f9c595259a54e6bff66f | |
parent | 460aebac739df78b0e40a347934fdea377310577 (diff) | |
parent | 15f5191b6acbbb38029b06284e8fd20275e7cfe8 (diff) |
Merge branch 'gp.2013.09.25a' into HEAD
gp.2013.09.25a: Topic branch for grace-period updates.
-rw-r--r-- | include/trace/events/rcu.h | 80 | ||||
-rw-r--r-- | kernel/rcutiny.c | 2 | ||||
-rw-r--r-- | kernel/rcutree.c | 56 | ||||
-rw-r--r-- | kernel/rcutree_plugin.h | 35 |
4 files changed, 144 insertions, 29 deletions
diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h index ee2376cfaab3..aca382266411 100644 --- a/include/trace/events/rcu.h +++ b/include/trace/events/rcu.h | |||
@@ -39,15 +39,26 @@ TRACE_EVENT(rcu_utilization, | |||
39 | #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) | 39 | #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) |
40 | 40 | ||
41 | /* | 41 | /* |
42 | * Tracepoint for grace-period events: starting and ending a grace | 42 | * Tracepoint for grace-period events. Takes a string identifying the |
43 | * period ("start" and "end", respectively), a CPU noting the start | 43 | * RCU flavor, the grace-period number, and a string identifying the |
44 | * of a new grace period or the end of an old grace period ("cpustart" | 44 | * grace-period-related event as follows: |
45 | * and "cpuend", respectively), a CPU passing through a quiescent | 45 | * |
46 | * state ("cpuqs"), a CPU coming online or going offline ("cpuonl" | 46 | * "AccReadyCB": CPU acclerates new callbacks to RCU_NEXT_READY_TAIL. |
47 | * and "cpuofl", respectively), a CPU being kicked for being too | 47 | * "AccWaitCB": CPU accelerates new callbacks to RCU_WAIT_TAIL. |
48 | * long in dyntick-idle mode ("kick"), a CPU accelerating its new | 48 | * "newreq": Request a new grace period. |
49 | * callbacks to RCU_NEXT_READY_TAIL ("AccReadyCB"), and a CPU | 49 | * "start": Start a grace period. |
50 | * accelerating its new callbacks to RCU_WAIT_TAIL ("AccWaitCB"). | 50 | * "cpustart": CPU first notices a grace-period start. |
51 | * "cpuqs": CPU passes through a quiescent state. | ||
52 | * "cpuonl": CPU comes online. | ||
53 | * "cpuofl": CPU goes offline. | ||
54 | * "reqwait": GP kthread sleeps waiting for grace-period request. | ||
55 | * "reqwaitsig": GP kthread awakened by signal from reqwait state. | ||
56 | * "fqswait": GP kthread waiting until time to force quiescent states. | ||
57 | * "fqsstart": GP kthread starts forcing quiescent states. | ||
58 | * "fqsend": GP kthread done forcing quiescent states. | ||
59 | * "fqswaitsig": GP kthread awakened by signal from fqswait state. | ||
60 | * "end": End a grace period. | ||
61 | * "cpuend": CPU first notices a grace-period end. | ||
51 | */ | 62 | */ |
52 | TRACE_EVENT(rcu_grace_period, | 63 | TRACE_EVENT(rcu_grace_period, |
53 | 64 | ||
@@ -161,6 +172,46 @@ TRACE_EVENT(rcu_grace_period_init, | |||
161 | ); | 172 | ); |
162 | 173 | ||
163 | /* | 174 | /* |
175 | * Tracepoint for RCU no-CBs CPU callback handoffs. This event is intended | ||
176 | * to assist debugging of these handoffs. | ||
177 | * | ||
178 | * The first argument is the name of the RCU flavor, and the second is | ||
179 | * the number of the offloaded CPU are extracted. The third and final | ||
180 | * argument is a string as follows: | ||
181 | * | ||
182 | * "WakeEmpty": Wake rcuo kthread, first CB to empty list. | ||
183 | * "WakeOvf": Wake rcuo kthread, CB list is huge. | ||
184 | * "WakeNot": Don't wake rcuo kthread. | ||
185 | * "WakeNotPoll": Don't wake rcuo kthread because it is polling. | ||
186 | * "Poll": Start of new polling cycle for rcu_nocb_poll. | ||
187 | * "Sleep": Sleep waiting for CBs for !rcu_nocb_poll. | ||
188 | * "WokeEmpty": rcuo kthread woke to find empty list. | ||
189 | * "WokeNonEmpty": rcuo kthread woke to find non-empty list. | ||
190 | * "WaitQueue": Enqueue partially done, timed wait for it to complete. | ||
191 | * "WokeQueue": Partial enqueue now complete. | ||
192 | */ | ||
193 | TRACE_EVENT(rcu_nocb_wake, | ||
194 | |||
195 | TP_PROTO(const char *rcuname, int cpu, const char *reason), | ||
196 | |||
197 | TP_ARGS(rcuname, cpu, reason), | ||
198 | |||
199 | TP_STRUCT__entry( | ||
200 | __field(const char *, rcuname) | ||
201 | __field(int, cpu) | ||
202 | __field(const char *, reason) | ||
203 | ), | ||
204 | |||
205 | TP_fast_assign( | ||
206 | __entry->rcuname = rcuname; | ||
207 | __entry->cpu = cpu; | ||
208 | __entry->reason = reason; | ||
209 | ), | ||
210 | |||
211 | TP_printk("%s %d %s", __entry->rcuname, __entry->cpu, __entry->reason) | ||
212 | ); | ||
213 | |||
214 | /* | ||
164 | * Tracepoint for tasks blocking within preemptible-RCU read-side | 215 | * Tracepoint for tasks blocking within preemptible-RCU read-side |
165 | * critical sections. Track the type of RCU (which one day might | 216 | * critical sections. Track the type of RCU (which one day might |
166 | * include SRCU), the grace-period number that the task is blocking | 217 | * include SRCU), the grace-period number that the task is blocking |
@@ -540,17 +591,17 @@ TRACE_EVENT(rcu_invoke_kfree_callback, | |||
540 | TRACE_EVENT(rcu_batch_end, | 591 | TRACE_EVENT(rcu_batch_end, |
541 | 592 | ||
542 | TP_PROTO(const char *rcuname, int callbacks_invoked, | 593 | TP_PROTO(const char *rcuname, int callbacks_invoked, |
543 | bool cb, bool nr, bool iit, bool risk), | 594 | char cb, char nr, char iit, char risk), |
544 | 595 | ||
545 | TP_ARGS(rcuname, callbacks_invoked, cb, nr, iit, risk), | 596 | TP_ARGS(rcuname, callbacks_invoked, cb, nr, iit, risk), |
546 | 597 | ||
547 | TP_STRUCT__entry( | 598 | TP_STRUCT__entry( |
548 | __field(const char *, rcuname) | 599 | __field(const char *, rcuname) |
549 | __field(int, callbacks_invoked) | 600 | __field(int, callbacks_invoked) |
550 | __field(bool, cb) | 601 | __field(char, cb) |
551 | __field(bool, nr) | 602 | __field(char, nr) |
552 | __field(bool, iit) | 603 | __field(char, iit) |
553 | __field(bool, risk) | 604 | __field(char, risk) |
554 | ), | 605 | ), |
555 | 606 | ||
556 | TP_fast_assign( | 607 | TP_fast_assign( |
@@ -656,6 +707,7 @@ TRACE_EVENT(rcu_barrier, | |||
656 | #define trace_rcu_future_grace_period(rcuname, gpnum, completed, c, \ | 707 | #define trace_rcu_future_grace_period(rcuname, gpnum, completed, c, \ |
657 | level, grplo, grphi, event) \ | 708 | level, grplo, grphi, event) \ |
658 | do { } while (0) | 709 | do { } while (0) |
710 | #define trace_rcu_nocb_wake(rcuname, cpu, reason) do { } while (0) | ||
659 | #define trace_rcu_preempt_task(rcuname, pid, gpnum) do { } while (0) | 711 | #define trace_rcu_preempt_task(rcuname, pid, gpnum) do { } while (0) |
660 | #define trace_rcu_unlock_preempted_task(rcuname, gpnum, pid) do { } while (0) | 712 | #define trace_rcu_unlock_preempted_task(rcuname, gpnum, pid) do { } while (0) |
661 | #define trace_rcu_quiescent_state_report(rcuname, gpnum, mask, qsmask, level, \ | 713 | #define trace_rcu_quiescent_state_report(rcuname, gpnum, mask, qsmask, level, \ |
diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c index e99eb5fb10af..7e3b0d6fc6e2 100644 --- a/kernel/rcutiny.c +++ b/kernel/rcutiny.c | |||
@@ -275,7 +275,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp) | |||
275 | if (&rcp->rcucblist == rcp->donetail) { | 275 | if (&rcp->rcucblist == rcp->donetail) { |
276 | RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, 0, -1)); | 276 | RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, 0, -1)); |
277 | RCU_TRACE(trace_rcu_batch_end(rcp->name, 0, | 277 | RCU_TRACE(trace_rcu_batch_end(rcp->name, 0, |
278 | ACCESS_ONCE(rcp->rcucblist), | 278 | !!ACCESS_ONCE(rcp->rcucblist), |
279 | need_resched(), | 279 | need_resched(), |
280 | is_idle_task(current), | 280 | is_idle_task(current), |
281 | false)); | 281 | false)); |
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 62aab5ceefe9..a06d172c75e0 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
@@ -1326,7 +1326,7 @@ static void note_gp_changes(struct rcu_state *rsp, struct rcu_data *rdp) | |||
1326 | } | 1326 | } |
1327 | 1327 | ||
1328 | /* | 1328 | /* |
1329 | * Initialize a new grace period. | 1329 | * Initialize a new grace period. Return 0 if no grace period required. |
1330 | */ | 1330 | */ |
1331 | static int rcu_gp_init(struct rcu_state *rsp) | 1331 | static int rcu_gp_init(struct rcu_state *rsp) |
1332 | { | 1332 | { |
@@ -1335,10 +1335,18 @@ static int rcu_gp_init(struct rcu_state *rsp) | |||
1335 | 1335 | ||
1336 | rcu_bind_gp_kthread(); | 1336 | rcu_bind_gp_kthread(); |
1337 | raw_spin_lock_irq(&rnp->lock); | 1337 | raw_spin_lock_irq(&rnp->lock); |
1338 | if (rsp->gp_flags == 0) { | ||
1339 | /* Spurious wakeup, tell caller to go back to sleep. */ | ||
1340 | raw_spin_unlock_irq(&rnp->lock); | ||
1341 | return 0; | ||
1342 | } | ||
1338 | rsp->gp_flags = 0; /* Clear all flags: New grace period. */ | 1343 | rsp->gp_flags = 0; /* Clear all flags: New grace period. */ |
1339 | 1344 | ||
1340 | if (rcu_gp_in_progress(rsp)) { | 1345 | if (WARN_ON_ONCE(rcu_gp_in_progress(rsp))) { |
1341 | /* Grace period already in progress, don't start another. */ | 1346 | /* |
1347 | * Grace period already in progress, don't start another. | ||
1348 | * Not supposed to be able to happen. | ||
1349 | */ | ||
1342 | raw_spin_unlock_irq(&rnp->lock); | 1350 | raw_spin_unlock_irq(&rnp->lock); |
1343 | return 0; | 1351 | return 0; |
1344 | } | 1352 | } |
@@ -1481,8 +1489,12 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) | |||
1481 | rsp->fqs_state = RCU_GP_IDLE; | 1489 | rsp->fqs_state = RCU_GP_IDLE; |
1482 | rdp = this_cpu_ptr(rsp->rda); | 1490 | rdp = this_cpu_ptr(rsp->rda); |
1483 | rcu_advance_cbs(rsp, rnp, rdp); /* Reduce false positives below. */ | 1491 | rcu_advance_cbs(rsp, rnp, rdp); /* Reduce false positives below. */ |
1484 | if (cpu_needs_another_gp(rsp, rdp)) | 1492 | if (cpu_needs_another_gp(rsp, rdp)) { |
1485 | rsp->gp_flags = RCU_GP_FLAG_INIT; | 1493 | rsp->gp_flags = RCU_GP_FLAG_INIT; |
1494 | trace_rcu_grace_period(rsp->name, | ||
1495 | ACCESS_ONCE(rsp->gpnum), | ||
1496 | TPS("newreq")); | ||
1497 | } | ||
1486 | raw_spin_unlock_irq(&rnp->lock); | 1498 | raw_spin_unlock_irq(&rnp->lock); |
1487 | } | 1499 | } |
1488 | 1500 | ||
@@ -1492,6 +1504,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) | |||
1492 | static int __noreturn rcu_gp_kthread(void *arg) | 1504 | static int __noreturn rcu_gp_kthread(void *arg) |
1493 | { | 1505 | { |
1494 | int fqs_state; | 1506 | int fqs_state; |
1507 | int gf; | ||
1495 | unsigned long j; | 1508 | unsigned long j; |
1496 | int ret; | 1509 | int ret; |
1497 | struct rcu_state *rsp = arg; | 1510 | struct rcu_state *rsp = arg; |
@@ -1501,14 +1514,19 @@ static int __noreturn rcu_gp_kthread(void *arg) | |||
1501 | 1514 | ||
1502 | /* Handle grace-period start. */ | 1515 | /* Handle grace-period start. */ |
1503 | for (;;) { | 1516 | for (;;) { |
1517 | trace_rcu_grace_period(rsp->name, | ||
1518 | ACCESS_ONCE(rsp->gpnum), | ||
1519 | TPS("reqwait")); | ||
1504 | wait_event_interruptible(rsp->gp_wq, | 1520 | wait_event_interruptible(rsp->gp_wq, |
1505 | rsp->gp_flags & | 1521 | ACCESS_ONCE(rsp->gp_flags) & |
1506 | RCU_GP_FLAG_INIT); | 1522 | RCU_GP_FLAG_INIT); |
1507 | if ((rsp->gp_flags & RCU_GP_FLAG_INIT) && | 1523 | if (rcu_gp_init(rsp)) |
1508 | rcu_gp_init(rsp)) | ||
1509 | break; | 1524 | break; |
1510 | cond_resched(); | 1525 | cond_resched(); |
1511 | flush_signals(current); | 1526 | flush_signals(current); |
1527 | trace_rcu_grace_period(rsp->name, | ||
1528 | ACCESS_ONCE(rsp->gpnum), | ||
1529 | TPS("reqwaitsig")); | ||
1512 | } | 1530 | } |
1513 | 1531 | ||
1514 | /* Handle quiescent-state forcing. */ | 1532 | /* Handle quiescent-state forcing. */ |
@@ -1518,10 +1536,16 @@ static int __noreturn rcu_gp_kthread(void *arg) | |||
1518 | j = HZ; | 1536 | j = HZ; |
1519 | jiffies_till_first_fqs = HZ; | 1537 | jiffies_till_first_fqs = HZ; |
1520 | } | 1538 | } |
1539 | ret = 0; | ||
1521 | for (;;) { | 1540 | for (;;) { |
1522 | rsp->jiffies_force_qs = jiffies + j; | 1541 | if (!ret) |
1542 | rsp->jiffies_force_qs = jiffies + j; | ||
1543 | trace_rcu_grace_period(rsp->name, | ||
1544 | ACCESS_ONCE(rsp->gpnum), | ||
1545 | TPS("fqswait")); | ||
1523 | ret = wait_event_interruptible_timeout(rsp->gp_wq, | 1546 | ret = wait_event_interruptible_timeout(rsp->gp_wq, |
1524 | (rsp->gp_flags & RCU_GP_FLAG_FQS) || | 1547 | ((gf = ACCESS_ONCE(rsp->gp_flags)) & |
1548 | RCU_GP_FLAG_FQS) || | ||
1525 | (!ACCESS_ONCE(rnp->qsmask) && | 1549 | (!ACCESS_ONCE(rnp->qsmask) && |
1526 | !rcu_preempt_blocked_readers_cgp(rnp)), | 1550 | !rcu_preempt_blocked_readers_cgp(rnp)), |
1527 | j); | 1551 | j); |
@@ -1530,13 +1554,23 @@ static int __noreturn rcu_gp_kthread(void *arg) | |||
1530 | !rcu_preempt_blocked_readers_cgp(rnp)) | 1554 | !rcu_preempt_blocked_readers_cgp(rnp)) |
1531 | break; | 1555 | break; |
1532 | /* If time for quiescent-state forcing, do it. */ | 1556 | /* If time for quiescent-state forcing, do it. */ |
1533 | if (ret == 0 || (rsp->gp_flags & RCU_GP_FLAG_FQS)) { | 1557 | if (ULONG_CMP_GE(jiffies, rsp->jiffies_force_qs) || |
1558 | (gf & RCU_GP_FLAG_FQS)) { | ||
1559 | trace_rcu_grace_period(rsp->name, | ||
1560 | ACCESS_ONCE(rsp->gpnum), | ||
1561 | TPS("fqsstart")); | ||
1534 | fqs_state = rcu_gp_fqs(rsp, fqs_state); | 1562 | fqs_state = rcu_gp_fqs(rsp, fqs_state); |
1563 | trace_rcu_grace_period(rsp->name, | ||
1564 | ACCESS_ONCE(rsp->gpnum), | ||
1565 | TPS("fqsend")); | ||
1535 | cond_resched(); | 1566 | cond_resched(); |
1536 | } else { | 1567 | } else { |
1537 | /* Deal with stray signal. */ | 1568 | /* Deal with stray signal. */ |
1538 | cond_resched(); | 1569 | cond_resched(); |
1539 | flush_signals(current); | 1570 | flush_signals(current); |
1571 | trace_rcu_grace_period(rsp->name, | ||
1572 | ACCESS_ONCE(rsp->gpnum), | ||
1573 | TPS("fqswaitsig")); | ||
1540 | } | 1574 | } |
1541 | j = jiffies_till_next_fqs; | 1575 | j = jiffies_till_next_fqs; |
1542 | if (j > HZ) { | 1576 | if (j > HZ) { |
@@ -1584,6 +1618,8 @@ rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp, | |||
1584 | return; | 1618 | return; |
1585 | } | 1619 | } |
1586 | rsp->gp_flags = RCU_GP_FLAG_INIT; | 1620 | rsp->gp_flags = RCU_GP_FLAG_INIT; |
1621 | trace_rcu_grace_period(rsp->name, ACCESS_ONCE(rsp->gpnum), | ||
1622 | TPS("newreq")); | ||
1587 | 1623 | ||
1588 | /* | 1624 | /* |
1589 | * We can't do wakeups while holding the rnp->lock, as that | 1625 | * We can't do wakeups while holding the rnp->lock, as that |
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 1855d66bf705..cd95efa1da48 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h | |||
@@ -2113,15 +2113,22 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, | |||
2113 | 2113 | ||
2114 | /* If we are not being polled and there is a kthread, awaken it ... */ | 2114 | /* If we are not being polled and there is a kthread, awaken it ... */ |
2115 | t = ACCESS_ONCE(rdp->nocb_kthread); | 2115 | t = ACCESS_ONCE(rdp->nocb_kthread); |
2116 | if (rcu_nocb_poll || !t) | 2116 | if (rcu_nocb_poll || !t) { |
2117 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | ||
2118 | TPS("WakeNotPoll")); | ||
2117 | return; | 2119 | return; |
2120 | } | ||
2118 | len = atomic_long_read(&rdp->nocb_q_count); | 2121 | len = atomic_long_read(&rdp->nocb_q_count); |
2119 | if (old_rhpp == &rdp->nocb_head) { | 2122 | if (old_rhpp == &rdp->nocb_head) { |
2120 | wake_up(&rdp->nocb_wq); /* ... only if queue was empty ... */ | 2123 | wake_up(&rdp->nocb_wq); /* ... only if queue was empty ... */ |
2121 | rdp->qlen_last_fqs_check = 0; | 2124 | rdp->qlen_last_fqs_check = 0; |
2125 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeEmpty")); | ||
2122 | } else if (len > rdp->qlen_last_fqs_check + qhimark) { | 2126 | } else if (len > rdp->qlen_last_fqs_check + qhimark) { |
2123 | wake_up_process(t); /* ... or if many callbacks queued. */ | 2127 | wake_up_process(t); /* ... or if many callbacks queued. */ |
2124 | rdp->qlen_last_fqs_check = LONG_MAX / 2; | 2128 | rdp->qlen_last_fqs_check = LONG_MAX / 2; |
2129 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeOvf")); | ||
2130 | } else { | ||
2131 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeNot")); | ||
2125 | } | 2132 | } |
2126 | return; | 2133 | return; |
2127 | } | 2134 | } |
@@ -2145,10 +2152,12 @@ static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, | |||
2145 | if (__is_kfree_rcu_offset((unsigned long)rhp->func)) | 2152 | if (__is_kfree_rcu_offset((unsigned long)rhp->func)) |
2146 | trace_rcu_kfree_callback(rdp->rsp->name, rhp, | 2153 | trace_rcu_kfree_callback(rdp->rsp->name, rhp, |
2147 | (unsigned long)rhp->func, | 2154 | (unsigned long)rhp->func, |
2148 | rdp->qlen_lazy, rdp->qlen); | 2155 | -atomic_long_read(&rdp->nocb_q_count_lazy), |
2156 | -atomic_long_read(&rdp->nocb_q_count)); | ||
2149 | else | 2157 | else |
2150 | trace_rcu_callback(rdp->rsp->name, rhp, | 2158 | trace_rcu_callback(rdp->rsp->name, rhp, |
2151 | rdp->qlen_lazy, rdp->qlen); | 2159 | -atomic_long_read(&rdp->nocb_q_count_lazy), |
2160 | -atomic_long_read(&rdp->nocb_q_count)); | ||
2152 | return 1; | 2161 | return 1; |
2153 | } | 2162 | } |
2154 | 2163 | ||
@@ -2226,6 +2235,7 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp) | |||
2226 | static int rcu_nocb_kthread(void *arg) | 2235 | static int rcu_nocb_kthread(void *arg) |
2227 | { | 2236 | { |
2228 | int c, cl; | 2237 | int c, cl; |
2238 | bool firsttime = 1; | ||
2229 | struct rcu_head *list; | 2239 | struct rcu_head *list; |
2230 | struct rcu_head *next; | 2240 | struct rcu_head *next; |
2231 | struct rcu_head **tail; | 2241 | struct rcu_head **tail; |
@@ -2234,14 +2244,27 @@ static int rcu_nocb_kthread(void *arg) | |||
2234 | /* Each pass through this loop invokes one batch of callbacks */ | 2244 | /* Each pass through this loop invokes one batch of callbacks */ |
2235 | for (;;) { | 2245 | for (;;) { |
2236 | /* If not polling, wait for next batch of callbacks. */ | 2246 | /* If not polling, wait for next batch of callbacks. */ |
2237 | if (!rcu_nocb_poll) | 2247 | if (!rcu_nocb_poll) { |
2248 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | ||
2249 | TPS("Sleep")); | ||
2238 | wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head); | 2250 | wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head); |
2251 | } else if (firsttime) { | ||
2252 | firsttime = 0; | ||
2253 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | ||
2254 | TPS("Poll")); | ||
2255 | } | ||
2239 | list = ACCESS_ONCE(rdp->nocb_head); | 2256 | list = ACCESS_ONCE(rdp->nocb_head); |
2240 | if (!list) { | 2257 | if (!list) { |
2258 | if (!rcu_nocb_poll) | ||
2259 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | ||
2260 | TPS("WokeEmpty")); | ||
2241 | schedule_timeout_interruptible(1); | 2261 | schedule_timeout_interruptible(1); |
2242 | flush_signals(current); | 2262 | flush_signals(current); |
2243 | continue; | 2263 | continue; |
2244 | } | 2264 | } |
2265 | firsttime = 1; | ||
2266 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | ||
2267 | TPS("WokeNonEmpty")); | ||
2245 | 2268 | ||
2246 | /* | 2269 | /* |
2247 | * Extract queued callbacks, update counts, and wait | 2270 | * Extract queued callbacks, update counts, and wait |
@@ -2262,7 +2285,11 @@ static int rcu_nocb_kthread(void *arg) | |||
2262 | next = list->next; | 2285 | next = list->next; |
2263 | /* Wait for enqueuing to complete, if needed. */ | 2286 | /* Wait for enqueuing to complete, if needed. */ |
2264 | while (next == NULL && &list->next != tail) { | 2287 | while (next == NULL && &list->next != tail) { |
2288 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | ||
2289 | TPS("WaitQueue")); | ||
2265 | schedule_timeout_interruptible(1); | 2290 | schedule_timeout_interruptible(1); |
2291 | trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, | ||
2292 | TPS("WokeQueue")); | ||
2266 | next = list->next; | 2293 | next = list->next; |
2267 | } | 2294 | } |
2268 | debug_rcu_head_unqueue(list); | 2295 | debug_rcu_head_unqueue(list); |