Rename RCU CB context to 'cannot block' context
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 2 Nov 2018 02:10:11 +0000 (22:10 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 2 Nov 2018 02:15:59 +0000 (22:15 -0400)
RCU needed to be able to turn on assertions to check if we're blocking
or not.  It's no surprise that we can use that elsewhere, since the
concept is more general than just being an RCU callback.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/trap.h
kern/src/ns/chan.c
kern/src/rcu.c

index 0d2b680..294ff4a 100644 (file)
@@ -179,7 +179,7 @@ void __kmsg_trampoline(uint32_t srcid, long a0, long a1, long a2);
 #define __CTX_IRQ_D_MASK                       ((1 << 8) - 1)
 #define __CTX_KTRAP_D_MASK                     ((1 << 8) - 1)
 #define __CTX_NESTED_CTX_MASK          ((1 << 16) - 1)
-#define __CTX_RCU_CB                           (1 << (__CTX_FLAG_SHIFT + 0))
+#define __CTX_CANNOT_BLOCK                     (1 << (__CTX_FLAG_SHIFT + 0))
 
 /* Basic functions to get or change depths */
 
@@ -201,11 +201,11 @@ void __kmsg_trampoline(uint32_t srcid, long a0, long a1, long a2);
 #define dec_ktrap_depth(pcpui)                                                 \
        ((pcpui)->__ctx_depth -= 1 << __CTX_KTRAP_D_SHIFT)
 
-#define set_rcu_cb(pcpui)                                                      \
-       ((pcpui)->__ctx_depth |= __CTX_RCU_CB)
+#define set_cannot_block(pcpui)                                                \
+       ((pcpui)->__ctx_depth |= __CTX_CANNOT_BLOCK)
 
-#define clear_rcu_cb(pcpui)                                                    \
-       ((pcpui)->__ctx_depth &= ~__CTX_RCU_CB)
+#define clear_cannot_block(pcpui)                                              \
+       ((pcpui)->__ctx_depth &= ~__CTX_CANNOT_BLOCK)
 
 /* Functions to query the kernel context depth/state.  I haven't fully decided
  * on whether or not 'default' context includes RKMs or not.  Will depend on
@@ -214,17 +214,14 @@ void __kmsg_trampoline(uint32_t srcid, long a0, long a1, long a2);
 #define in_irq_ctx(pcpui)                                                      \
        (irq_depth(pcpui))
 
-#define in_rcu_cb_ctx(pcpui)                                                   \
-       ((pcpui)->__ctx_depth & __CTX_RCU_CB)
-
 /* Right now, anything (KTRAP, IRQ, or RKM) makes us not 'default' */
 #define in_default_ctx(pcpui)                                                  \
        (!(pcpui)->__ctx_depth)
 
 /* Can block only if we have no nested contexts (ktraps or irqs, (which are
- * potentially nested contexts)) and not in an RCU CB*/
+ * potentially nested contexts)) and not in an explicit CANNOT_BLOCK. */
 #define can_block(pcpui)                                                       \
-       (!((pcpui)->__ctx_depth & (__CTX_NESTED_CTX_MASK | __CTX_RCU_CB)))
+       (!((pcpui)->__ctx_depth & (__CTX_NESTED_CTX_MASK | __CTX_CANNOT_BLOCK)))
 
 /* TRUE if we are allowed to spin, given that the 'lock' was declared as not
  * grabbable from IRQ context.  Meaning, we can't grab the lock from any nested
index b7d6a1d..de0694f 100644 (file)
@@ -160,8 +160,9 @@ static void chan_release(struct kref *kref)
        ERRSTACK(1);
 
        /* We can be called from RCU callbacks, but close methods can block.  In
-        * those cases, we need to defer our work to a kernel message. */
-       if (in_rcu_cb_ctx(this_pcpui_ptr())) {
+        * those cases, and any other context that cannot block, we need to defer
+        * our work to a kernel message. */
+       if (!can_block(this_pcpui_ptr())) {
                run_as_rkm(chan_release, kref);
                return;
        }
index 23a8a6c..4d90887 100644 (file)
@@ -116,10 +116,10 @@ void synchronize_rcu(void)
        struct sync_cb_blob b[1];
        struct semaphore sem[1];
 
-       if (in_rcu_cb_ctx(this_pcpui_ptr()))
-               panic("Attempted synchronize_rcu() from an RCU callback!");
+       if (!can_block(this_pcpui_ptr()))
+               panic("Attempted %s() from an unblockable context!", __func__);
        if (is_rcu_ktask(current_kthread))
-               panic("Attempted synchronize_rcu() from an RCU thread!");
+               panic("Attempted %s() from an RCU thread!", __func__);
        sem_init(sem, 0);
        init_rcu_head_on_stack(&b->h);
        b->sem = sem;
@@ -225,15 +225,14 @@ void rcu_barrier(void)
        struct sync_cb_blob *b;
        int nr_sent = 0;
 
-       if (in_rcu_cb_ctx(this_pcpui_ptr()))
-               panic("Attempted rcu_barrier() from an RCU callback!");
+       if (!can_block(this_pcpui_ptr()))
+               panic("Attempted %s() from an unblockable context!", __func__);
        if (is_rcu_ktask(current_kthread))
-               panic("Attempted rcu_barrier() from an RCU thread!");
+               panic("Attempted %s() from an RCU thread!", __func__);
        /* TODO: if we have concurrent rcu_barriers, we might be able to share the
         * CBs.  Say we have 1 CB on a core, then N rcu_barriers.  We'll have N
         * call_rcus in flight, though we could share.  Linux does this with a mtx
         * and some accounting, I think. */
-
        b = kzmalloc(sizeof(struct sync_cb_blob) * num_cores, MEM_WAIT);
        /* Remember, you block when sem is <= 0.  We'll get nr_sent ups, and we'll
         * down 1 for each.  This is just like the synchronize_rcu() case; there,
@@ -516,12 +515,12 @@ static void run_rcu_cbs(struct rcu_state *rsp, int coreid)
         * world, not blocking also means our kthread won't migrate from this core,
         * such that the pcpui pointer (and thus the specific __ctx_depth) won't
         * change. */
-       set_rcu_cb(this_pcpui_ptr());
+       set_cannot_block(this_pcpui_ptr());
        list_for_each_entry_safe(head, temp, &work, link) {
                list_del(&head->link);
                rcu_exec_cb(head);
        }
-       clear_rcu_cb(this_pcpui_ptr());
+       clear_cannot_block(this_pcpui_ptr());
 
        /* We kept nr_cbs in place until the CBs, which could block, completed.
         * This allows other readers (rcu_barrier()) of our pcpui to tell if we have