|
@@ -35,24 +35,6 @@ void rcu_cblist_init(struct rcu_cblist *rclp)
|
|
|
rclp->len_lazy = 0;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Debug function to actually count the number of callbacks.
|
|
|
- * If the number exceeds the limit specified, return -1.
|
|
|
- */
|
|
|
-long rcu_cblist_count_cbs(struct rcu_cblist *rclp, long lim)
|
|
|
-{
|
|
|
- int cnt = 0;
|
|
|
- struct rcu_head **rhpp = &rclp->head;
|
|
|
-
|
|
|
- for (;;) {
|
|
|
- if (!*rhpp)
|
|
|
- return cnt;
|
|
|
- if (++cnt > lim)
|
|
|
- return -1;
|
|
|
- rhpp = &(*rhpp)->next;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Dequeue the oldest rcu_head structure from the specified callback
|
|
|
* list. This function assumes that the callback is non-lazy, but
|
|
@@ -102,17 +84,6 @@ void rcu_segcblist_disable(struct rcu_segcblist *rsclp)
|
|
|
rsclp->tails[RCU_NEXT_TAIL] = NULL;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Is the specified segment of the specified rcu_segcblist structure
|
|
|
- * empty of callbacks?
|
|
|
- */
|
|
|
-bool rcu_segcblist_segempty(struct rcu_segcblist *rsclp, int seg)
|
|
|
-{
|
|
|
- if (seg == RCU_DONE_TAIL)
|
|
|
- return &rsclp->head == rsclp->tails[RCU_DONE_TAIL];
|
|
|
- return rsclp->tails[seg - 1] == rsclp->tails[seg];
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Does the specified rcu_segcblist structure contain callbacks that
|
|
|
* are ready to be invoked?
|
|
@@ -133,50 +104,6 @@ bool rcu_segcblist_pend_cbs(struct rcu_segcblist *rsclp)
|
|
|
!rcu_segcblist_restempty(rsclp, RCU_DONE_TAIL);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Dequeue and return the first ready-to-invoke callback. If there
|
|
|
- * are no ready-to-invoke callbacks, return NULL. Disables interrupts
|
|
|
- * to avoid interference. Does not protect from interference from other
|
|
|
- * CPUs or tasks.
|
|
|
- */
|
|
|
-struct rcu_head *rcu_segcblist_dequeue(struct rcu_segcblist *rsclp)
|
|
|
-{
|
|
|
- unsigned long flags;
|
|
|
- int i;
|
|
|
- struct rcu_head *rhp;
|
|
|
-
|
|
|
- local_irq_save(flags);
|
|
|
- if (!rcu_segcblist_ready_cbs(rsclp)) {
|
|
|
- local_irq_restore(flags);
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- rhp = rsclp->head;
|
|
|
- BUG_ON(!rhp);
|
|
|
- rsclp->head = rhp->next;
|
|
|
- for (i = RCU_DONE_TAIL; i < RCU_CBLIST_NSEGS; i++) {
|
|
|
- if (rsclp->tails[i] != &rhp->next)
|
|
|
- break;
|
|
|
- rsclp->tails[i] = &rsclp->head;
|
|
|
- }
|
|
|
- smp_mb(); /* Dequeue before decrement for rcu_barrier(). */
|
|
|
- WRITE_ONCE(rsclp->len, rsclp->len - 1);
|
|
|
- local_irq_restore(flags);
|
|
|
- return rhp;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Account for the fact that a previously dequeued callback turned out
|
|
|
- * to be marked as lazy.
|
|
|
- */
|
|
|
-void rcu_segcblist_dequeued_lazy(struct rcu_segcblist *rsclp)
|
|
|
-{
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- local_irq_save(flags);
|
|
|
- rsclp->len_lazy--;
|
|
|
- local_irq_restore(flags);
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Return a pointer to the first callback in the specified rcu_segcblist
|
|
|
* structure. This is useful for diagnostics.
|
|
@@ -202,17 +129,6 @@ struct rcu_head *rcu_segcblist_first_pend_cb(struct rcu_segcblist *rsclp)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Does the specified rcu_segcblist structure contain callbacks that
|
|
|
- * have not yet been processed beyond having been posted, that is,
|
|
|
- * does it contain callbacks in its last segment?
|
|
|
- */
|
|
|
-bool rcu_segcblist_new_cbs(struct rcu_segcblist *rsclp)
|
|
|
-{
|
|
|
- return rcu_segcblist_is_enabled(rsclp) &&
|
|
|
- !rcu_segcblist_restempty(rsclp, RCU_NEXT_READY_TAIL);
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Enqueue the specified callback onto the specified rcu_segcblist
|
|
|
* structure, updating accounting as needed. Note that the ->len
|