You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ma...@apache.org on 2022/11/22 06:29:07 UTC

[incubator-nuttx] 01/03: nuttx/sched: remove nxsched_remove_blocked from up_unblock_task

This is an automated email from the ASF dual-hosted git repository.

masayuki pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit e54b602208c1e4451096e327d1010512f5792ffb
Author: zhangyuan21 <zh...@xiaomi.com>
AuthorDate: Tue Nov 1 09:52:11 2022 +0800

    nuttx/sched: remove nxsched_remove_blocked from up_unblock_task
    
    It takes about 10 cycles to obtain the task list according to the task
    status. In most cases, we know the task status, so we can directly
    delete the task from the specified task list to reduce time consuming.
---
 Documentation/reference/os/arch.rst          |  14 ++--
 arch/arm/src/common/arm_unblocktask.c        | 100 ++++++++---------------
 arch/arm64/src/common/arm64_unblocktask.c    | 100 ++++++++---------------
 arch/avr/src/avr/up_unblocktask.c            |  96 ++++++++--------------
 arch/avr/src/avr32/up_unblocktask.c          | 115 +++++++++-----------------
 arch/ceva/src/common/up_unblocktask.c        |  98 ++++++++--------------
 arch/hc/src/common/up_unblocktask.c          | 109 +++++++++----------------
 arch/mips/src/mips32/mips_unblocktask.c      | 101 ++++++++---------------
 arch/misoc/src/lm32/lm32_unblocktask.c       | 101 ++++++++---------------
 arch/misoc/src/minerva/minerva_unblocktask.c | 101 ++++++++---------------
 arch/or1k/src/common/up_unblocktask.c        | 115 +++++++++-----------------
 arch/renesas/src/common/up_unblocktask.c     | 109 +++++++++----------------
 arch/risc-v/src/common/riscv_unblocktask.c   | 101 ++++++++---------------
 arch/sim/src/sim/up_unblocktask.c            | 116 ++++++++++-----------------
 arch/sparc/src/sparc_v8/up_unblocktask.c     | 101 ++++++++---------------
 arch/x86/src/common/up_unblocktask.c         | 108 +++++++++----------------
 arch/x86_64/src/common/up_unblocktask.c      | 112 +++++++++-----------------
 arch/xtensa/src/common/xtensa_unblocktask.c  | 100 ++++++++---------------
 arch/z16/src/common/z16_unblocktask.c        |  99 +++++++----------------
 arch/z80/src/common/z80_unblocktask.c        | 113 +++++++++-----------------
 include/nuttx/arch.h                         |  14 ++--
 sched/group/group_continue.c                 |  14 +++-
 sched/mqueue/mq_rcvinternal.c                |  18 ++++-
 sched/mqueue/mq_sndinternal.c                |  18 ++++-
 sched/mqueue/mq_waitirq.c                    |  17 +++-
 sched/mqueue/msgrcv.c                        |  18 ++++-
 sched/mqueue/msgsnd.c                        |  18 ++++-
 sched/paging/pg_worker.c                     |  47 +++++++++--
 sched/sched/sched.h                          |   8 ++
 sched/semaphore/sem_post.c                   |  17 +++-
 sched/semaphore/sem_waitirq.c                |  19 ++++-
 sched/signal/sig_dispatch.c                  |  42 +++++++++-
 sched/signal/sig_timedwait.c                 |  33 +++++++-
 sched/task/task_activate.c                   |  17 +++-
 34 files changed, 931 insertions(+), 1378 deletions(-)

diff --git a/Documentation/reference/os/arch.rst b/Documentation/reference/os/arch.rst
index 42df537b98..12c9dbbb86 100644
--- a/Documentation/reference/os/arch.rst
+++ b/Documentation/reference/os/arch.rst
@@ -174,19 +174,17 @@ APIs Exported by Architecture-Specific Logic to NuttX
      and threads must have come from memory that is accessible to
      user
 
-.. c:function:: void up_unblock_task(FAR struct tcb_s *tcb)
+.. c:function:: void up_unblock_task(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb)
 
-  A task is currently in an inactive task list but
-  has been prepped to execute. Move the TCB to the ready-to-run
-  list, restore its context, and start execution.
+  A task is currently in the ready-to-run list but has been preppe
+  to execute. Restore its context, and start execution.
 
   This function is called only from the NuttX scheduling logic.
   Interrupts will always be disabled when this function is called.
 
-  :param tcb: Refers to the tcb to be unblocked. This tcb is in one
-    of the waiting tasks lists. It must be moved to the
-    ready-to-run list and, if it is the highest priority ready to
-    run tasks, executed.
+  :param tcb: Refers to the head task of the ready-to-run list
+     which will be executed.
+  :param rtcb: Refers to the running task which will be blocked.
 
 .. c:function:: void up_block_task(FAR struct tcb_s *tcb, tstate_t task_state)
 
diff --git a/arch/arm/src/common/arm_unblocktask.c b/arch/arm/src/common/arm_unblocktask.c
index 5b347c0dfc..af53886a1a 100644
--- a/arch/arm/src/common/arm_unblocktask.c
+++ b/arch/arm/src/common/arm_unblocktask.c
@@ -43,93 +43,61 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-              (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (CURRENT_REGS)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the CURRENT_REGS into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (CURRENT_REGS)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the CURRENT_REGS into the OLD rtcb.
-           */
-
-          arm_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
+      arm_savestate(rtcb->xcp.regs);
 
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
+      /* Update scheduler parameters */
 
-          /* Then switch contexts.  Any necessary address environment
-           * changes will be made when the interrupt returns.
-           */
+      nxsched_resume_scheduler(tcb);
 
-          arm_restorestate(rtcb->xcp.regs);
-        }
+      /* Then switch contexts.  Any necessary address environment
+       * changes will be made when the interrupt returns.
+       */
 
-      /* No, then we will need to perform the user context switch */
+      arm_restorestate(tcb->xcp.regs);
+    }
 
-      else
-        {
-          struct tcb_s *nexttcb = this_task();
+  /* No, then we will need to perform the user context switch */
 
-          /* Update scheduler parameters */
+  else
+    {
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(nexttcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Switch context to the context of the task at the head of the
-           * ready to run list.
-           */
+      /* Switch context to the context of the task at the head of the
+       * ready to run list.
+       */
 
-          arm_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);
+      arm_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs);
 
-          /* arm_switchcontext forces a context switch to the task at the
-           * head of the ready-to-run list.  It does not 'return' in the
-           * normal sense.  When it does return, it is because the blocked
-           * task is again ready to run and has execution priority.
-           */
-        }
+      /* arm_switchcontext forces a context switch to the task at the
+       * head of the ready-to-run list.  It does not 'return' in the
+       * normal sense.  When it does return, it is because the blocked
+       * task is again ready to run and has execution priority.
+       */
     }
 }
diff --git a/arch/arm64/src/common/arm64_unblocktask.c b/arch/arm64/src/common/arm64_unblocktask.c
index 68fc5d88cb..c91eddfed3 100644
--- a/arch/arm64/src/common/arm64_unblocktask.c
+++ b/arch/arm64/src/common/arm64_unblocktask.c
@@ -43,93 +43,61 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-              (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (CURRENT_REGS)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the CURRENT_REGS into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (CURRENT_REGS)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the CURRENT_REGS into the OLD rtcb.
-           */
-
-          arm64_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
+      arm64_savestate(rtcb->xcp.regs);
 
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
+      /* Update scheduler parameters */
 
-          /* Then switch contexts.  Any necessary address environment
-           * changes will be made when the interrupt returns.
-           */
+      nxsched_resume_scheduler(tcb);
 
-          arm64_restorestate(rtcb->xcp.regs);
-        }
+      /* Then switch contexts.  Any necessary address environment
+       * changes will be made when the interrupt returns.
+       */
 
-      /* No, then we will need to perform the user context switch */
+      arm64_restorestate(tcb->xcp.regs);
+    }
 
-      else
-        {
-          struct tcb_s *nexttcb = this_task();
+  /* No, then we will need to perform the user context switch */
 
-          /* Update scheduler parameters */
+  else
+    {
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(nexttcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Switch context to the context of the task at the head of the
-           * ready to run list.
-           */
+      /* Switch context to the context of the task at the head of the
+       * ready to run list.
+       */
 
-          arm64_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);
+      arm64_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs);
 
-          /* arm_switchcontext forces a context switch to the task at the
-           * head of the ready-to-run list.  It does not 'return' in the
-           * normal sense.  When it does return, it is because the blocked
-           * task is again ready to run and has execution priority.
-           */
-        }
+      /* arm_switchcontext forces a context switch to the task at the
+       * head of the ready-to-run list.  It does not 'return' in the
+       * normal sense.  When it does return, it is because the blocked
+       * task is again ready to run and has execution priority.
+       */
     }
 }
diff --git a/arch/avr/src/avr/up_unblocktask.c b/arch/avr/src/avr/up_unblocktask.c
index 8e54f5008c..1d906bb4b8 100644
--- a/arch/avr/src/avr/up_unblocktask.c
+++ b/arch/avr/src/avr/up_unblocktask.c
@@ -42,91 +42,59 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-         (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (g_current_regs)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the g_current_regs into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (g_current_regs)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the g_current_regs into the OLD rtcb.
-           */
-
-          up_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
+      up_savestate(rtcb->xcp.regs);
 
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
+      /* Update scheduler parameters */
 
-          /* Then switch contexts */
+      nxsched_resume_scheduler(tcb);
 
-          up_restorestate(rtcb->xcp.regs);
-        }
+      /* Then switch contexts */
 
-      /* No, then we will need to perform the user context switch */
+      up_restorestate(tcb->xcp.regs);
+    }
 
-      else
-        {
-          struct tcb_s *nexttcb = this_task();
+  /* No, then we will need to perform the user context switch */
 
-          /* Update scheduler parameters */
+  else
+    {
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(nexttcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Switch context to the context of the task at the head of the
-           * ready to run list.
-           */
+      /* Switch context to the context of the task at the head of the
+       * ready to run list.
+       */
 
-          up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+      up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs);
 
-          /* up_switchcontext forces a context switch to the task at the
-           * head of the ready-to-run list.  It does not 'return' in the
-           * normal sense.  When it does return, it is because the blocked
-           * task is again ready to run and has execution priority.
-           */
-        }
+      /* up_switchcontext forces a context switch to the task at the
+       * head of the ready-to-run list.  It does not 'return' in the
+       * normal sense.  When it does return, it is because the blocked
+       * task is again ready to run and has execution priority.
+       */
     }
 }
diff --git a/arch/avr/src/avr32/up_unblocktask.c b/arch/avr/src/avr32/up_unblocktask.c
index 486bca0d7b..8dfcc80eaa 100644
--- a/arch/avr/src/avr32/up_unblocktask.c
+++ b/arch/avr/src/avr32/up_unblocktask.c
@@ -43,106 +43,69 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-         (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (g_current_regs)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the g_current_regs into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (g_current_regs)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the g_current_regs into the OLD rtcb.
-           */
-
-          up_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
-
-          rtcb = this_task();
+      up_savestate(rtcb->xcp.regs);
 
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then switch contexts.  Any new address environment needed by
-           * the new thread will be instantiated before the return from
-           * interrupt.
-           */
+      /* Update scheduler parameters */
 
-          up_restorestate(rtcb->xcp.regs);
-        }
+      nxsched_resume_scheduler(tcb);
 
-      /* No, then we will need to perform the user context switch */
+      /* Then switch contexts.  Any new address environment needed by
+       * the new thread will be instantiated before the return from
+       * interrupt.
+       */
 
-      else
-        {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
+      up_restorestate(tcb->xcp.regs);
+    }
 
-          struct tcb_s *nexttcb = this_task();
+  /* No, then we will need to perform the user context switch */
 
+  else
+    {
 #ifdef CONFIG_ARCH_ADDRENV
-          /* Make sure that the address environment for the previously
-           * running task is closed down gracefully (data caches dump,
-           * MMU flushed) and set up the address environment for the new
-           * thread at the head of the ready-to-run list.
-           */
+      /* Make sure that the address environment for the previously
+       * running task is closed down gracefully (data caches dump,
+       * MMU flushed) and set up the address environment for the new
+       * thread at the head of the ready-to-run list.
+       */
 
-          group_addrenv(nexttcb);
+      group_addrenv(tcb);
 #endif
-          /* Update scheduler parameters */
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(nexttcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Then switch contexts */
+      /* Then switch contexts */
 
-          up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+      up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs);
 
-          /* up_switchcontext forces a context switch to the task at the
-           * head of the ready-to-run list.  It does not 'return' in the
-           * normal sense.  When it does return, it is because the blocked
-           * task is again ready to run and has execution priority.
-           */
-        }
+      /* up_switchcontext forces a context switch to the task at the
+       * head of the ready-to-run list.  It does not 'return' in the
+       * normal sense.  When it does return, it is because the blocked
+       * task is again ready to run and has execution priority.
+       */
     }
 }
diff --git a/arch/ceva/src/common/up_unblocktask.c b/arch/ceva/src/common/up_unblocktask.c
index 84e7b24502..395c9db46b 100644
--- a/arch/ceva/src/common/up_unblocktask.c
+++ b/arch/ceva/src/common/up_unblocktask.c
@@ -38,91 +38,59 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
- * Inputs:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run taks, executed.
+ * Input Parameters:
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  sched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-         (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  sched_removeblocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (sched_addreadytorun(tcb))
+  if (CURRENT_REGS)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the CURRENT_REGS into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      sched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (CURRENT_REGS)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the CURRENT_REGS into the OLD rtcb.
-           */
-
-          rtcb->xcp.regs = CURRENT_REGS;
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
+      rtcb->xcp.regs = CURRENT_REGS;
 
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          sched_resume_scheduler(rtcb);
+      /* Update scheduler parameters */
 
-          /* Then switch contexts */
+      sched_resume_scheduler(tcb);
 
-          CURRENT_REGS = rtcb->xcp.regs;
-        }
+      /* Then switch contexts */
 
-      /* No, then we will need to perform the user context switch */
+      CURRENT_REGS = tcb->xcp.regs;
+    }
 
-      else
-        {
-          struct tcb_s *nexttcb = this_task();
+  /* No, then we will need to perform the user context switch */
 
-          /* Update scheduler parameters */
+  else
+    {
+      /* Update scheduler parameters */
 
-          sched_resume_scheduler(nexttcb);
+      sched_resume_scheduler(tcb);
 
-          /* Switch context to the context of the task at the head of the
-           * ready to run list.
-           */
+      /* Switch context to the context of the task at the head of the
+       * ready to run list.
+       */
 
-          up_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);
+      up_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs);
 
-          /* up_switchcontext forces a context switch to the task at the
-           * head of the ready-to-run list.  It does not 'return' in the
-           * normal sense.  When it does return, it is because the blocked
-           * task is again ready to run and has execution priority.
-           */
-        }
+      /* up_switchcontext forces a context switch to the task at the
+       * head of the ready-to-run list.  It does not 'return' in the
+       * normal sense.  When it does return, it is because the blocked
+       * task is again ready to run and has execution priority.
+       */
     }
 }
diff --git a/arch/hc/src/common/up_unblocktask.c b/arch/hc/src/common/up_unblocktask.c
index 94609a1744..75991546be 100644
--- a/arch/hc/src/common/up_unblocktask.c
+++ b/arch/hc/src/common/up_unblocktask.c
@@ -43,103 +43,66 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-              (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (g_current_regs)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the g_current_regs into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (g_current_regs)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the g_current_regs into the OLD rtcb.
-           */
-
-          up_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
+      up_savestate(rtcb->xcp.regs);
 
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then switch contexts.  Any necessary address environment
-           * changes will be made when the interrupt returns.
-           */
+      /* Update scheduler parameters */
 
-          up_restorestate(rtcb->xcp.regs);
-        }
+      nxsched_resume_scheduler(tcb);
 
-      /* We are not in an interrupt handler.  Copy the user C context
-       * into the TCB of the task that was previously active.  if
-       * up_saveusercontext returns a non-zero value, then this is really the
-       * previously running task restarting!
+      /* Then switch contexts.  Any necessary address environment
+       * changes will be made when the interrupt returns.
        */
 
-      else if (!up_saveusercontext(rtcb->xcp.regs))
-        {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
+      up_restorestate(tcb->xcp.regs);
+    }
 
-          rtcb = this_task();
+  /* We are not in an interrupt handler.  Copy the user C context
+   * into the TCB of the task that was previously active.  if
+   * up_saveusercontext returns a non-zero value, then this is really the
+   * previously running task restarting!
+   */
 
+  else if (!up_saveusercontext(rtcb->xcp.regs))
+    {
 #ifdef CONFIG_ARCH_ADDRENV
-          /* Make sure that the address environment for the previously
-           * running task is closed down gracefully (data caches dump,
-           * MMU flushed) and set up the address environment for the new
-           * thread at the head of the ready-to-run list.
-           */
+      /* Make sure that the address environment for the previously
+       * running task is closed down gracefully (data caches dump,
+       * MMU flushed) and set up the address environment for the new
+       * thread at the head of the ready-to-run list.
+       */
 
-          group_addrenv(rtcb);
+      group_addrenv(tcb);
 #endif
-          /* Update scheduler parameters */
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(rtcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Then switch contexts */
+      /* Then switch contexts */
 
-          up_fullcontextrestore(rtcb->xcp.regs);
-        }
+      up_fullcontextrestore(tcb->xcp.regs);
     }
 }
diff --git a/arch/mips/src/mips32/mips_unblocktask.c b/arch/mips/src/mips32/mips_unblocktask.c
index 586fb4b226..4cdb70e682 100644
--- a/arch/mips/src/mips32/mips_unblocktask.c
+++ b/arch/mips/src/mips32/mips_unblocktask.c
@@ -45,96 +45,59 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-              (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (CURRENT_REGS)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the g_current_regs into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (CURRENT_REGS)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the g_current_regs into the OLD rtcb.
-           */
-
-          up_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
+      up_savestate(rtcb->xcp.regs);
 
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then switch contexts.  Any necessary address environment
-           * changes will be made when the interrupt returns.
-           */
+      /* Update scheduler parameters */
 
-          up_restorestate(rtcb->xcp.regs);
-        }
+      nxsched_resume_scheduler(tcb);
 
-      /* No, then we will need to perform the user context switch */
+      /* Then switch contexts.  Any necessary address environment
+       * changes will be made when the interrupt returns.
+       */
 
-      else
-        {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
+      up_restorestate(tcb->xcp.regs);
+    }
 
-          struct tcb_s *nexttcb = this_task();
+  /* No, then we will need to perform the user context switch */
 
-          /* Update scheduler parameters */
+  else
+    {
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(nexttcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Then switch contexts */
+      /* Then switch contexts */
 
-          up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+      up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs);
 
-          /* up_switchcontext forces a context switch to the task at the
-           * head of the ready-to-run list.  It does not 'return' in the
-           * normal sense.  When it does return, it is because the blocked
-           * task is again ready to run and has execution priority.
-           */
-        }
+      /* up_switchcontext forces a context switch to the task at the
+       * head of the ready-to-run list.  It does not 'return' in the
+       * normal sense.  When it does return, it is because the blocked
+       * task is again ready to run and has execution priority.
+       */
     }
 }
diff --git a/arch/misoc/src/lm32/lm32_unblocktask.c b/arch/misoc/src/lm32/lm32_unblocktask.c
index 4a6e69decb..51e7c01b99 100644
--- a/arch/misoc/src/lm32/lm32_unblocktask.c
+++ b/arch/misoc/src/lm32/lm32_unblocktask.c
@@ -45,96 +45,59 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-              (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (g_current_regs)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the g_current_regs into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (g_current_regs)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the g_current_regs into the OLD rtcb.
-           */
-
-          up_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
+      up_savestate(rtcb->xcp.regs);
 
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then switch contexts.  Any necessary address environment
-           * changes will be made when the interrupt returns.
-           */
+      /* Update scheduler parameters */
 
-          up_restorestate(rtcb->xcp.regs);
-        }
+      nxsched_resume_scheduler(tcb);
 
-      /* No, then we will need to perform the user context switch */
+      /* Then switch contexts.  Any necessary address environment
+       * changes will be made when the interrupt returns.
+       */
 
-      else
-        {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
+      up_restorestate(tcb->xcp.regs);
+    }
 
-          struct tcb_s *nexttcb = this_task();
+  /* No, then we will need to perform the user context switch */
 
-          /* Update scheduler parameters */
+  else
+    {
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(nexttcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Then switch contexts */
+      /* Then switch contexts */
 
-          up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+      up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs);
 
-          /* up_switchcontext forces a context switch to the task at the
-           * head of the ready-to-run list.  It does not 'return' in the
-           * normal sense.  When it does return, it is because the blocked
-           * task is again ready to run and has execution priority.
-           */
-        }
+      /* up_switchcontext forces a context switch to the task at the
+       * head of the ready-to-run list.  It does not 'return' in the
+       * normal sense.  When it does return, it is because the blocked
+       * task is again ready to run and has execution priority.
+       */
     }
 }
diff --git a/arch/misoc/src/minerva/minerva_unblocktask.c b/arch/misoc/src/minerva/minerva_unblocktask.c
index 69c4e0a340..a8b74afc0e 100644
--- a/arch/misoc/src/minerva/minerva_unblocktask.c
+++ b/arch/misoc/src/minerva/minerva_unblocktask.c
@@ -45,96 +45,59 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-              (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized ready-to-run
-   * task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (g_current_regs)
     {
-      /* The currently active task has changed! We need to do a context
-       * switch to the new task.
+      /* Yes, then we have to do things differently. Just copy the
+       * g_current_regs into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (g_current_regs)
-        {
-          /* Yes, then we have to do things differently. Just copy the
-           * g_current_regs into the OLD rtcb.
-           */
-
-          up_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head of
-           * the ready-to-run task list.
-           */
+      up_savestate(rtcb->xcp.regs);
 
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then switch contexts.  Any necessary address environment changes
-           * will be made when the interrupt returns.
-           */
+      /* Update scheduler parameters */
 
-          up_restorestate(rtcb->xcp.regs);
-        }
+      nxsched_resume_scheduler(tcb);
 
-      /* No, then we will need to perform the user context switch */
+      /* Then switch contexts.  Any necessary address environment changes
+       * will be made when the interrupt returns.
+       */
 
-      else
-        {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
+      up_restorestate(tcb->xcp.regs);
+    }
 
-          struct tcb_s *nexttcb = this_task();
+  /* No, then we will need to perform the user context switch */
 
-          /* Update scheduler parameters */
+  else
+    {
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(nexttcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Then switch contexts */
+      /* Then switch contexts */
 
-          up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+      up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs);
 
-          /* up_switchcontext forces a context switch to the task at the head
-           * of the ready-to-run list.  It does not 'return' in the normal
-           * sense.  When it does return, it is because the blocked task is
-           * again ready to run and has execution priority.
-           */
-        }
+      /* up_switchcontext forces a context switch to the task at the head
+       * of the ready-to-run list.  It does not 'return' in the normal
+       * sense.  When it does return, it is because the blocked task is
+       * again ready to run and has execution priority.
+       */
     }
 }
diff --git a/arch/or1k/src/common/up_unblocktask.c b/arch/or1k/src/common/up_unblocktask.c
index be26e53062..01e80d3c48 100644
--- a/arch/or1k/src/common/up_unblocktask.c
+++ b/arch/or1k/src/common/up_unblocktask.c
@@ -43,107 +43,70 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-         (tcb->task_state <= LAST_BLOCKED_STATE));
-
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
-    {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
-       */
-
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
+  /* Are we in an interrupt handler? */
 
 #if 0  /* REVISIT */
-      if (CURRENT_REGS)
+  if (CURRENT_REGS)
 #else
-      if (0)
+  if (0)
 #endif
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the CURRENT_REGS into the OLD rtcb.
-           */
-
-          up_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
-
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
+    {
+      /* Yes, then we have to do things differently.
+       * Just copy the CURRENT_REGS into the OLD rtcb.
+       */
 
-          nxsched_resume_scheduler(rtcb);
+      up_savestate(rtcb->xcp.regs);
 
-          /* Then switch contexts.  Any necessary address environment
-           * changes will be made when the interrupt returns.
-           */
+      /* Update scheduler parameters */
 
-          up_restorestate(rtcb->xcp.regs);
-        }
+      nxsched_resume_scheduler(tcb);
 
-      /* We are not in an interrupt handler.  Copy the user C context
-       * into the TCB of the task that was previously active.  if
-       * up_saveusercontext returns a non-zero value, then this is really the
-       * previously running task restarting!
+      /* Then switch contexts.  Any necessary address environment
+       * changes will be made when the interrupt returns.
        */
 
-      else if (!up_saveusercontext(rtcb->xcp.regs))
-        {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
+      up_restorestate(tcb->xcp.regs);
+    }
 
-          rtcb = this_task();
+  /* We are not in an interrupt handler.  Copy the user C context
+   * into the TCB of the task that was previously active.  if
+   * up_saveusercontext returns a non-zero value, then this is really the
+   * previously running task restarting!
+   */
 
+  else if (!up_saveusercontext(rtcb->xcp.regs))
+    {
 #ifdef CONFIG_ARCH_ADDRENV
-          /* Make sure that the address environment for the previously
-           * running task is closed down gracefully (data caches dump,
-           * MMU flushed) and set up the address environment for the new
-           * thread at the head of the ready-to-run list.
-           */
+      /* Make sure that the address environment for the previously
+       * running task is closed down gracefully (data caches dump,
+       * MMU flushed) and set up the address environment for the new
+       * thread at the head of the ready-to-run list.
+       */
 
-          group_addrenv(rtcb);
+      group_addrenv(tcb);
 #endif
-          /* Update scheduler parameters */
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(rtcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Then switch contexts */
+      /* Then switch contexts */
 
-          up_fullcontextrestore(rtcb->xcp.regs);
-        }
+      up_fullcontextrestore(tcb->xcp.regs);
     }
 }
diff --git a/arch/renesas/src/common/up_unblocktask.c b/arch/renesas/src/common/up_unblocktask.c
index a7df03de61..de0987019c 100644
--- a/arch/renesas/src/common/up_unblocktask.c
+++ b/arch/renesas/src/common/up_unblocktask.c
@@ -43,103 +43,66 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-              (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (g_current_regs)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the g_current_regs into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (g_current_regs)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the g_current_regs into the OLD rtcb.
-           */
-
-          up_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
+      up_savestate(rtcb->xcp.regs);
 
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then switch contexts.  Any necessary address environment
-           * changes will be made when the interrupt returns.
-           */
+      /* Update scheduler parameters */
 
-          g_current_regs = rtcb->xcp.regs;
-        }
+      nxsched_resume_scheduler(tcb);
 
-      /* We are not in an interrupt handler.  Copy the user C context
-       * into the TCB of the task that was previously active.  if
-       * up_saveusercontext returns a non-zero value, then this is really the
-       * previously running task restarting!
+      /* Then switch contexts.  Any necessary address environment
+       * changes will be made when the interrupt returns.
        */
 
-      else if (!up_saveusercontext(rtcb->xcp.regs))
-        {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
+      g_current_regs = tcb->xcp.regs;
+    }
 
-          rtcb = this_task();
+  /* We are not in an interrupt handler.  Copy the user C context
+   * into the TCB of the task that was previously active.  if
+   * up_saveusercontext returns a non-zero value, then this is really the
+   * previously running task restarting!
+   */
 
+  else if (!up_saveusercontext(rtcb->xcp.regs))
+    {
 #ifdef CONFIG_ARCH_ADDRENV
-          /* Make sure that the address environment for the previously
-           * running task is closed down gracefully (data caches dump,
-           * MMU flushed) and set up the address environment for the new
-           * thread at the head of the ready-to-run list.
-           */
+      /* Make sure that the address environment for the previously
+       * running task is closed down gracefully (data caches dump,
+       * MMU flushed) and set up the address environment for the new
+       * thread at the head of the ready-to-run list.
+       */
 
-          group_addrenv(rtcb);
+      group_addrenv(tcb);
 #endif
-          /* Update scheduler parameters */
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(rtcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Then switch contexts */
+      /* Then switch contexts */
 
-          up_fullcontextrestore(rtcb->xcp.regs);
-        }
+      up_fullcontextrestore(tcb->xcp.regs);
     }
 }
diff --git a/arch/risc-v/src/common/riscv_unblocktask.c b/arch/risc-v/src/common/riscv_unblocktask.c
index c72360dadc..e77b237585 100644
--- a/arch/risc-v/src/common/riscv_unblocktask.c
+++ b/arch/risc-v/src/common/riscv_unblocktask.c
@@ -45,96 +45,59 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-              (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (CURRENT_REGS)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the CURRENT_REGS into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (CURRENT_REGS)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the CURRENT_REGS into the OLD rtcb.
-           */
-
-          riscv_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
+      riscv_savestate(rtcb->xcp.regs);
 
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then switch contexts.  Any necessary address environment
-           * changes will be made when the interrupt returns.
-           */
+      /* Update scheduler parameters */
 
-          riscv_restorestate(rtcb->xcp.regs);
-        }
+      nxsched_resume_scheduler(tcb);
 
-      /* No, then we will need to perform the user context switch */
+      /* Then switch contexts.  Any necessary address environment
+       * changes will be made when the interrupt returns.
+       */
 
-      else
-        {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
+      riscv_restorestate(tcb->xcp.regs);
+    }
 
-          struct tcb_s *nexttcb = this_task();
+  /* No, then we will need to perform the user context switch */
 
-          /* Update scheduler parameters */
+  else
+    {
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(nexttcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Then switch contexts */
+      /* Then switch contexts */
 
-          riscv_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);
+      riscv_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs);
 
-          /* riscv_switchcontext forces a context switch to the task at the
-           * head of the ready-to-run list.  It does not 'return' in the
-           * normal sense.  When it does return, it is because the blocked
-           * task is again ready to run and has execution priority.
-           */
-        }
+      /* riscv_switchcontext forces a context switch to the task at the
+       * head of the ready-to-run list.  It does not 'return' in the
+       * normal sense.  When it does return, it is because the blocked
+       * task is again ready to run and has execution priority.
+       */
     }
 }
diff --git a/arch/sim/src/sim/up_unblocktask.c b/arch/sim/src/sim/up_unblocktask.c
index 3f1bd1929e..08ed9d0e07 100644
--- a/arch/sim/src/sim/up_unblocktask.c
+++ b/arch/sim/src/sim/up_unblocktask.c
@@ -42,109 +42,75 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
-
-  /* Verify that the context switch can be performed */
-
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-              (tcb->task_state <= LAST_BLOCKED_STATE));
-
   sinfo("Unblocking TCB=%p\n", tcb);
 
-  /* Remove the task from the blocked task list */
+  /* Update scheduler parameters */
 
-  nxsched_remove_blocked(tcb);
+  nxsched_suspend_scheduler(rtcb);
 
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
+  /* Are we in an interrupt handler? */
 
-  if (nxsched_add_readytorun(tcb))
+  if (CURRENT_REGS)
     {
-      /* The currently active task has changed! */
+      /* Yes, then we have to do things differently.
+       * Just copy the CURRENT_REGS into the OLD rtcb.
+       */
+
+      up_savestate(rtcb->xcp.regs);
 
       /* Update scheduler parameters */
 
-      nxsched_suspend_scheduler(rtcb);
+      nxsched_resume_scheduler(tcb);
 
-      /* Are we in an interrupt handler? */
+      /* Restore the cpu lock */
 
-      if (CURRENT_REGS)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the CURRENT_REGS into the OLD rtcb.
-           */
+      restore_critical_section();
 
-          up_savestate(rtcb->xcp.regs);
+      /* Then switch contexts */
 
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
+      up_restorestate(tcb->xcp.regs);
+    }
 
-          rtcb = this_task();
+  /* Copy the exception context into the TCB of the task that was
+   * previously active.  if setjmp returns a non-zero value, then
+   * this is really the previously running task restarting!
+   */
 
-          /* Update scheduler parameters */
+  else if (!setjmp(rtcb->xcp.regs))
+    {
+      sinfo("New Active Task TCB=%p\n", tcb);
 
-          nxsched_resume_scheduler(rtcb);
+      /* Update scheduler parameters */
 
-          /* Restore the cpu lock */
+      nxsched_resume_scheduler(tcb);
 
-          restore_critical_section();
+      /* Restore the cpu lock */
 
-          /* Then switch contexts */
+      restore_critical_section();
 
-          up_restorestate(rtcb->xcp.regs);
-        }
+      /* Then switch contexts */
 
-      /* Copy the exception context into the TCB of the task that was
-       * previously active.  if setjmp returns a non-zero value, then
-       * this is really the previously running task restarting!
+      longjmp(tcb->xcp.regs, 1);
+    }
+  else
+    {
+      /* The way that we handle signals in the simulation is kind of
+       * a kludge.  This would be unsafe in a truly multi-threaded,
+       * interrupt driven environment.
        */
 
-      else if (!setjmp(rtcb->xcp.regs))
-        {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
-
-          rtcb = this_task();
-          sinfo("New Active Task TCB=%p\n", rtcb);
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Restore the cpu lock */
-
-          restore_critical_section();
-
-          /* Then switch contexts */
-
-          longjmp(rtcb->xcp.regs, 1);
-        }
-      else
-        {
-          /* The way that we handle signals in the simulation is kind of
-           * a kludge.  This would be unsafe in a truly multi-threaded,
-           * interrupt driven environment.
-           */
-
-          sim_sigdeliver();
-        }
+      sim_sigdeliver();
     }
 }
diff --git a/arch/sparc/src/sparc_v8/up_unblocktask.c b/arch/sparc/src/sparc_v8/up_unblocktask.c
index 986b4af358..b20b52a50a 100644
--- a/arch/sparc/src/sparc_v8/up_unblocktask.c
+++ b/arch/sparc/src/sparc_v8/up_unblocktask.c
@@ -45,96 +45,59 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-              (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (CURRENT_REGS)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the CURRENT_REGS into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (CURRENT_REGS)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the CURRENT_REGS into the OLD rtcb.
-           */
-
-          up_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
+      up_savestate(rtcb->xcp.regs);
 
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then switch contexts.  Any necessary address environment
-           * changes will be made when the interrupt returns.
-           */
+      /* Update scheduler parameters */
 
-          up_restorestate(rtcb->xcp.regs);
-        }
+      nxsched_resume_scheduler(tcb);
 
-      /* No, then we will need to perform the user context switch */
+      /* Then switch contexts.  Any necessary address environment
+       * changes will be made when the interrupt returns.
+       */
 
-      else
-        {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
+      up_restorestate(tcb->xcp.regs);
+    }
 
-          struct tcb_s *nexttcb = this_task();
+  /* No, then we will need to perform the user context switch */
 
-          /* Update scheduler parameters */
+  else
+    {
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(nexttcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Then switch contexts */
+      /* Then switch contexts */
 
-          up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+      up_switchcontext(rtcb->xcp.regs, tcb->xcp.regs);
 
-          /* up_switchcontext forces a context switch to the task at the
-           * head of the ready-to-run list.  It does not 'return' in the
-           * normal sense.  When it does return, it is because the blocked
-           * task is again ready to run and has execution priority.
-           */
-        }
+      /* up_switchcontext forces a context switch to the task at the
+       * head of the ready-to-run list.  It does not 'return' in the
+       * normal sense.  When it does return, it is because the blocked
+       * task is again ready to run and has execution priority.
+       */
     }
 }
diff --git a/arch/x86/src/common/up_unblocktask.c b/arch/x86/src/common/up_unblocktask.c
index 4eaf4e529d..5003675cad 100644
--- a/arch/x86/src/common/up_unblocktask.c
+++ b/arch/x86/src/common/up_unblocktask.c
@@ -43,102 +43,66 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list but has been prepped to
- *   execute.  Move the TCB to the ready-to-run list, restore its context,
- *   and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is in one of the
- *     waiting tasks lists.  It must be moved to the ready-to-run list and,
- *     if it is the highest priority ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-              (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (g_current_regs)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the g_current_regs into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (g_current_regs)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the g_current_regs into the OLD rtcb.
-           */
-
-          up_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
+      up_savestate(rtcb->xcp.regs);
 
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then switch contexts.  Any necessary address environment
-           * changes will be made when the interrupt returns.
-           */
+      /* Update scheduler parameters */
 
-          up_restorestate(rtcb->xcp.regs);
-        }
+      nxsched_resume_scheduler(tcb);
 
-      /* We are not in an interrupt handler.  Copy the user C context
-       * into the TCB of the task that was previously active.  if
-       * up_saveusercontext returns a non-zero value, then this is really the
-       * previously running task restarting!
+      /* Then switch contexts.  Any necessary address environment
+       * changes will be made when the interrupt returns.
        */
 
-      else if (!up_saveusercontext(rtcb->xcp.regs))
-        {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
+      up_restorestate(tcb->xcp.regs);
+    }
 
-          rtcb = this_task();
+  /* We are not in an interrupt handler.  Copy the user C context
+   * into the TCB of the task that was previously active.  if
+   * up_saveusercontext returns a non-zero value, then this is really the
+   * previously running task restarting!
+   */
 
+  else if (!up_saveusercontext(rtcb->xcp.regs))
+    {
 #ifdef CONFIG_ARCH_ADDRENV
-          /* Make sure that the address environment for the previously
-           * running task is closed down gracefully (data caches dump,
-           * MMU flushed) and set up the address environment for the new
-           * thread at the head of the ready-to-run list.
-           */
+      /* Make sure that the address environment for the previously
+       * running task is closed down gracefully (data caches dump,
+       * MMU flushed) and set up the address environment for the new
+       * thread at the head of the ready-to-run list.
+       */
 
-          group_addrenv(rtcb);
+      group_addrenv(tcb);
 #endif
-          /* Update scheduler parameters */
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(rtcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Then switch contexts */
+      /* Then switch contexts */
 
-          up_fullcontextrestore(rtcb->xcp.regs);
-        }
+      up_fullcontextrestore(tcb->xcp.regs);
     }
 }
diff --git a/arch/x86_64/src/common/up_unblocktask.c b/arch/x86_64/src/common/up_unblocktask.c
index cd3fff6db1..5420cadc63 100644
--- a/arch/x86_64/src/common/up_unblocktask.c
+++ b/arch/x86_64/src/common/up_unblocktask.c
@@ -45,104 +45,70 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list but has been prepped to
- *   execute.  Move the TCB to the ready-to-run list, restore its context,
- *   and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is in one of the
- *     waiting tasks lists.  It must be moved to the ready-to-run list and,
- *     if it is the highest priority ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  ASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-         (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (g_current_regs)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the g_current_regs into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (g_current_regs)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the g_current_regs into the OLD rtcb.
-           */
-
-          up_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
+      up_savestate(rtcb->xcp.regs);
 
-          rtcb = this_task();
-          up_restore_auxstate(rtcb);
+      up_restore_auxstate(tcb);
 
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then switch contexts.  Any necessary address environment
-           * changes will be made when the interrupt returns.
-           */
+      /* Update scheduler parameters */
 
-          up_restorestate(rtcb->xcp.regs);
-        }
+      nxsched_resume_scheduler(tcb);
 
-      /* We are not in an interrupt handler.  Copy the user C context
-       * into the TCB of the task that was previously active.  if
-       * up_saveusercontext returns a non-zero value, then this is really the
-       * previously running task restarting!
+      /* Then switch contexts.  Any necessary address environment
+       * changes will be made when the interrupt returns.
        */
 
-      else if (!up_saveusercontext(rtcb->xcp.regs))
-        {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
+      up_restorestate(tcb->xcp.regs);
+    }
 
-          rtcb = this_task();
-          up_restore_auxstate(rtcb);
+  /* We are not in an interrupt handler.  Copy the user C context
+   * into the TCB of the task that was previously active.  if
+   * up_saveusercontext returns a non-zero value, then this is really the
+   * previously running task restarting!
+   */
+
+  else if (!up_saveusercontext(rtcb->xcp.regs))
+    {
+      up_restore_auxstate(tcb);
 
 #ifdef CONFIG_ARCH_ADDRENV
-          /* Make sure that the address environment for the previously
-           * running task is closed down gracefully (data caches dump,
-           * MMU flushed) and set up the address environment for the new
-           * thread at the head of the ready-to-run list.
-           */
+      /* Make sure that the address environment for the previously
+       * running task is closed down gracefully (data caches dump,
+       * MMU flushed) and set up the address environment for the new
+       * thread at the head of the ready-to-run list.
+       */
 
-          group_addrenv(rtcb);
+      group_addrenv(tcb);
 #endif
-          /* Update scheduler parameters */
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(rtcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Then switch contexts */
+      /* Then switch contexts */
 
-          up_fullcontextrestore(rtcb->xcp.regs);
-        }
+      up_fullcontextrestore(tcb->xcp.regs);
     }
 }
diff --git a/arch/xtensa/src/common/xtensa_unblocktask.c b/arch/xtensa/src/common/xtensa_unblocktask.c
index c1bcf7afb5..5f453cedb4 100644
--- a/arch/xtensa/src/common/xtensa_unblocktask.c
+++ b/arch/xtensa/src/common/xtensa_unblocktask.c
@@ -45,93 +45,61 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(struct tcb_s *tcb)
+void up_unblock_task(struct tcb_s *tcb, struct tcb_s *rtcb)
 {
-  struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-              (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (CURRENT_REGS)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the CURRENT_REGS into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (CURRENT_REGS)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the CURRENT_REGS into the OLD rtcb.
-           */
-
-          xtensa_savestate(rtcb->xcp.regs);
-
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
+      xtensa_savestate(rtcb->xcp.regs);
 
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
+      /* Update scheduler parameters */
 
-          /* Then switch contexts.  Any necessary address environment
-           * changes will be made when the interrupt returns.
-           */
+      nxsched_resume_scheduler(tcb);
 
-          xtensa_restorestate(rtcb->xcp.regs);
-        }
+      /* Then switch contexts.  Any necessary address environment
+       * changes will be made when the interrupt returns.
+       */
 
-      /* No, then we will need to perform the user context switch */
+      xtensa_restorestate(tcb->xcp.regs);
+    }
 
-      else
-        {
-          struct tcb_s *nexttcb = this_task();
+  /* No, then we will need to perform the user context switch */
 
-          /* Reset scheduler parameters */
+  else
+    {
+      /* Reset scheduler parameters */
 
-          nxsched_resume_scheduler(nexttcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Switch context to the context of the task at the head of the
-           * ready to run list.
-           */
+      /* Switch context to the context of the task at the head of the
+       * ready to run list.
+       */
 
-          xtensa_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);
+      xtensa_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs);
 
-          /* xtensa_switchcontext forces a context switch to the task at the
-           * head of the ready-to-run list.  It does not 'return' in the
-           * normal sense.  When it does return, it is because the blocked
-           * task is again ready to run and has execution priority.
-           */
-        }
+      /* xtensa_switchcontext forces a context switch to the task at the
+       * head of the ready-to-run list.  It does not 'return' in the
+       * normal sense.  When it does return, it is because the blocked
+       * task is again ready to run and has execution priority.
+       */
     }
 }
diff --git a/arch/z16/src/common/z16_unblocktask.c b/arch/z16/src/common/z16_unblocktask.c
index 74d2d6664e..b24d8c414c 100644
--- a/arch/z16/src/common/z16_unblocktask.c
+++ b/arch/z16/src/common/z16_unblocktask.c
@@ -44,96 +44,57 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(FAR struct tcb_s *tcb)
+void up_unblock_task(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb)
 {
-  FAR struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-              (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* sinfo("Unblocking TCB=%p\n", tcb); */
-
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (IN_INTERRUPT)
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the current context into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (IN_INTERRUPT)
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the current context into the OLD rtcb.
-           */
-
-          SAVE_IRQCONTEXT(rtcb);
+      SAVE_IRQCONTEXT(rtcb);
 
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
-
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then setup so that the context will be performed on exit
-           * from the interrupt.
-           */
+      /* Update scheduler parameters */
 
-          SET_IRQCONTEXT(rtcb);
-        }
+      nxsched_resume_scheduler(tcb);
 
-      /* We are not in an interrupt handler.  Copy the user C context
-       * into the TCB of the task that was previously active.  if
-       * SAVE_USERCONTEXT returns a non-zero value, then this is really the
-       * previously running task restarting!
+      /* Then setup so that the context will be performed on exit
+       * from the interrupt.
        */
 
-      else if (!SAVE_USERCONTEXT(rtcb))
-        {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
+      SET_IRQCONTEXT(tcb);
+    }
 
-          rtcb = this_task();
+  /* We are not in an interrupt handler.  Copy the user C context
+   * into the TCB of the task that was previously active.  if
+   * SAVE_USERCONTEXT returns a non-zero value, then this is really the
+   * previously running task restarting!
+   */
 
-          /* Update scheduler parameters */
+  else if (!SAVE_USERCONTEXT(rtcb))
+    {
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(rtcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Then switch contexts */
+      /* Then switch contexts */
 
-          RESTORE_USERCONTEXT(rtcb);
-        }
+      RESTORE_USERCONTEXT(tcb);
     }
 }
diff --git a/arch/z80/src/common/z80_unblocktask.c b/arch/z80/src/common/z80_unblocktask.c
index bad43f0be3..55fc1b2d34 100644
--- a/arch/z80/src/common/z80_unblocktask.c
+++ b/arch/z80/src/common/z80_unblocktask.c
@@ -46,106 +46,67 @@
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(FAR struct tcb_s *tcb)
+void up_unblock_task(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb)
 {
-  FAR struct tcb_s *rtcb = this_task();
+  /* Update scheduler parameters */
 
-  /* Verify that the context switch can be performed */
+  nxsched_suspend_scheduler(rtcb);
 
-  DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) &&
-         (tcb->task_state <= LAST_BLOCKED_STATE));
+  /* Are we in an interrupt handler? */
 
-  /* _info("Unblocking TCB=%p\n", tcb); */
-
-  /* Remove the task from the blocked task list */
-
-  nxsched_remove_blocked(tcb);
-
-  /* Add the task in the correct location in the prioritized
-   * ready-to-run task list
-   */
-
-  if (nxsched_add_readytorun(tcb))
+  if (IN_INTERRUPT())
     {
-      /* The currently active task has changed! We need to do
-       * a context switch to the new task.
+      /* Yes, then we have to do things differently.
+       * Just copy the current context into the OLD rtcb.
        */
 
-      /* Update scheduler parameters */
-
-      nxsched_suspend_scheduler(rtcb);
-
-      /* Are we in an interrupt handler? */
-
-      if (IN_INTERRUPT())
-        {
-          /* Yes, then we have to do things differently.
-           * Just copy the current context into the OLD rtcb.
-           */
-
-          SAVE_IRQCONTEXT(rtcb);
+      SAVE_IRQCONTEXT(rtcb);
 
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
-
-          rtcb = this_task();
-
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then setup so that the context will be performed on exit
-           * from the interrupt.  Any necessary address environment
-           * changes will be made when the interrupt returns.
-           */
+      /* Update scheduler parameters */
 
-          SET_IRQCONTEXT(rtcb);
-        }
+      nxsched_resume_scheduler(tcb);
 
-      /* We are not in an interrupt handler.  Copy the user C context
-       * into the TCB of the task that was previously active.  if
-       * SAVE_USERCONTEXT returns a non-zero value, then this is really the
-       * previously running task restarting!
+      /* Then setup so that the context will be performed on exit
+       * from the interrupt.  Any necessary address environment
+       * changes will be made when the interrupt returns.
        */
 
-      else if (!SAVE_USERCONTEXT(rtcb))
-        {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
+      SET_IRQCONTEXT(tcb);
+    }
 
-          rtcb = this_task();
+  /* We are not in an interrupt handler.  Copy the user C context
+   * into the TCB of the task that was previously active.  if
+   * SAVE_USERCONTEXT returns a non-zero value, then this is really the
+   * previously running task restarting!
+   */
 
+  else if (!SAVE_USERCONTEXT(rtcb))
+    {
 #ifdef CONFIG_ARCH_ADDRENV
-          /* Make sure that the address environment for the previously
-           * running task is closed down gracefully (data caches dump,
-           * MMU flushed) and set up the address environment for the new
-           * thread at the head of the ready-to-run list.
-           */
+      /* Make sure that the address environment for the previously
+       * running task is closed down gracefully (data caches dump,
+       * MMU flushed) and set up the address environment for the new
+       * thread at the head of the ready-to-run list.
+       */
 
-          group_addrenv(rtcb);
+      group_addrenv(tcb);
 #endif
-          /* Update scheduler parameters */
+      /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(rtcb);
+      nxsched_resume_scheduler(tcb);
 
-          /* Then switch contexts */
+      /* Then switch contexts */
 
-          RESTORE_USERCONTEXT(rtcb);
-        }
+      RESTORE_USERCONTEXT(tcb);
     }
 }
diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h
index e41adb394f..6eee128995 100644
--- a/include/nuttx/arch.h
+++ b/include/nuttx/arch.h
@@ -387,23 +387,21 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype);
  * Name: up_unblock_task
  *
  * Description:
- *   A task is currently in an inactive task list
- *   but has been prepped to execute.  Move the TCB to the
- *   ready-to-run list, restore its context, and start execution.
+ *   A task is currently in the ready-to-run list but has been prepped
+ *   to execute. Restore its context, and start execution.
  *
  *   This function is called only from the NuttX scheduling
  *   logic.  Interrupts will always be disabled when this
  *   function is called.
  *
  * Input Parameters:
- *   tcb: Refers to the tcb to be unblocked.  This tcb is
- *     in one of the waiting tasks lists.  It must be moved to
- *     the ready-to-run list and, if it is the highest priority
- *     ready to run task, executed.
+ *   tcb: Refers to the head task of the ready-to-run list
+ *     which will be executed.
+ *   rtcb: Refers to the running task which will be blocked.
  *
  ****************************************************************************/
 
-void up_unblock_task(FAR struct tcb_s *tcb);
+void up_unblock_task(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb);
 
 /****************************************************************************
  * Name: up_block_task
diff --git a/sched/group/group_continue.c b/sched/group/group_continue.c
index 9a03b0d623..b775ebbdbf 100644
--- a/sched/group/group_continue.c
+++ b/sched/group/group_continue.c
@@ -57,6 +57,7 @@
 
 static int group_continue_handler(pid_t pid, FAR void *arg)
 {
+  FAR struct tcb_s *tcb = this_task();
   FAR struct tcb_s *rtcb;
 
   /* Resume all threads */
@@ -64,7 +65,18 @@ static int group_continue_handler(pid_t pid, FAR void *arg)
   rtcb = nxsched_get_tcb(pid);
   if (rtcb != NULL)
     {
-      up_unblock_task(rtcb);
+      /* Remove the task from waitting list */
+
+      nxsched_remove_blocked(rtcb);
+
+      /* Add the task to ready-to-run task list and
+       * perform the context switch if one is needed
+       */
+
+      if (nxsched_add_readytorun(rtcb))
+        {
+          up_unblock_task(rtcb, tcb);
+        }
     }
 
   /* Always return zero.  We need to visit each member of the group */
diff --git a/sched/mqueue/mq_rcvinternal.c b/sched/mqueue/mq_rcvinternal.c
index 48348cc01d..c22604658f 100644
--- a/sched/mqueue/mq_rcvinternal.c
+++ b/sched/mqueue/mq_rcvinternal.c
@@ -279,13 +279,15 @@ ssize_t nxmq_do_receive(FAR struct mqueue_inode_s *msgq,
 
   if (msgq->cmn.nwaitnotfull > 0)
     {
+      FAR struct tcb_s *rtcb = this_task();
+
       /* Find the highest priority task that is waiting for
        * this queue to be not-full in waitfornotfull list.
        * This must be performed in a critical section because
        * messages can be sent from interrupt handlers.
        */
 
-      btcb = (FAR struct tcb_s *)dq_peek(MQ_WNFLIST(msgq->cmn));
+      btcb = (FAR struct tcb_s *)dq_remfirst(MQ_WNFLIST(msgq->cmn));
 
       /* If one was found, unblock it.  NOTE:  There is a race
        * condition here:  the queue might be full again by the
@@ -300,7 +302,19 @@ ssize_t nxmq_do_receive(FAR struct mqueue_inode_s *msgq,
         }
 
       msgq->cmn.nwaitnotfull--;
-      up_unblock_task(btcb);
+
+      /* Indicate that the wait is over. */
+
+      btcb->waitobj = NULL;
+
+      /* Add the task to ready-to-run task list and
+       * perform the context switch if one is needed
+       */
+
+      if (nxsched_add_readytorun(btcb))
+        {
+          up_unblock_task(btcb, rtcb);
+        }
     }
 
   /* Return the length of the message transferred to the user buffer */
diff --git a/sched/mqueue/mq_sndinternal.c b/sched/mqueue/mq_sndinternal.c
index 578d8b7523..d74f9301c3 100644
--- a/sched/mqueue/mq_sndinternal.c
+++ b/sched/mqueue/mq_sndinternal.c
@@ -388,6 +388,8 @@ int nxmq_do_send(FAR struct mqueue_inode_s *msgq,
 
   if (msgq->cmn.nwaitnotempty > 0)
     {
+      FAR struct tcb_s *rtcb = this_task();
+
       /* Find the highest priority task that is waiting for
        * this queue to be non-empty in waitfornotempty
        * list. leave_critical_section() should give us sufficient
@@ -395,7 +397,7 @@ int nxmq_do_send(FAR struct mqueue_inode_s *msgq,
        * in this list
        */
 
-      btcb = (FAR struct tcb_s *)dq_peek(MQ_WNELIST(msgq->cmn));
+      btcb = (FAR struct tcb_s *)dq_remfirst(MQ_WNELIST(msgq->cmn));
 
       /* If one was found, unblock it */
 
@@ -407,7 +409,19 @@ int nxmq_do_send(FAR struct mqueue_inode_s *msgq,
         }
 
       msgq->cmn.nwaitnotempty--;
-      up_unblock_task(btcb);
+
+      /* Indicate that the wait is over. */
+
+      btcb->waitobj = NULL;
+
+      /* Add the task to ready-to-run task list and
+       * perform the context switch if one is needed
+       */
+
+      if (nxsched_add_readytorun(btcb))
+        {
+          up_unblock_task(btcb, rtcb);
+        }
     }
 
   return OK;
diff --git a/sched/mqueue/mq_waitirq.c b/sched/mqueue/mq_waitirq.c
index aa2e800c5f..58d78b2291 100644
--- a/sched/mqueue/mq_waitirq.c
+++ b/sched/mqueue/mq_waitirq.c
@@ -33,6 +33,7 @@
 #include <nuttx/mqueue.h>
 
 #include "mqueue/mqueue.h"
+#include "sched/sched.h"
 
 /****************************************************************************
  * Public Functions
@@ -61,6 +62,7 @@
 
 void nxmq_wait_irq(FAR struct tcb_s *wtcb, int errcode)
 {
+  FAR struct tcb_s *rtcb = this_task();
   FAR struct mqueue_inode_s *msgq;
 
   /* It is possible that an interrupt/context switch beat us to the punch and
@@ -80,18 +82,29 @@ void nxmq_wait_irq(FAR struct tcb_s *wtcb, int errcode)
     {
       DEBUGASSERT(msgq->cmn.nwaitnotempty > 0);
       msgq->cmn.nwaitnotempty--;
+      dq_rem((FAR dq_entry_t *)wtcb, MQ_WNELIST(msgq->cmn));
     }
   else
     {
       DEBUGASSERT(msgq->cmn.nwaitnotfull > 0);
       msgq->cmn.nwaitnotfull--;
+      dq_rem((FAR dq_entry_t *)wtcb, MQ_WNFLIST(msgq->cmn));
     }
 
+  /* Indicate that the wait is over. */
+
+  wtcb->waitobj = NULL;
+
   /* Mark the error value for the thread. */
 
   wtcb->errcode = errcode;
 
-  /* Restart the task. */
+  /* Add the task to ready-to-run task list and
+   * perform the context switch if one is needed
+   */
 
-  up_unblock_task(wtcb);
+  if (nxsched_add_readytorun(wtcb))
+    {
+      up_unblock_task(wtcb, rtcb);
+    }
 }
diff --git a/sched/mqueue/msgrcv.c b/sched/mqueue/msgrcv.c
index 1402b022d4..23a33a6abf 100644
--- a/sched/mqueue/msgrcv.c
+++ b/sched/mqueue/msgrcv.c
@@ -221,13 +221,15 @@ ssize_t msgrcv(int msqid, FAR void *msgp, size_t msgsz, long msgtyp,
 
   if (msgq->cmn.nwaitnotfull > 0)
     {
+      FAR struct tcb_s *rtcb = this_task();
+
       /* Find the highest priority task that is waiting for
        * this queue to be not-full in g_waitingformqnotfull list.
        * This must be performed in a critical section because
        * messages can be sent from interrupt handlers.
        */
 
-      btcb = (FAR struct tcb_s *)dq_peek(MQ_WNFLIST(msgq->cmn));
+      btcb = (FAR struct tcb_s *)dq_remfirst(MQ_WNFLIST(msgq->cmn));
 
       /* If one was found, unblock it.  NOTE:  There is a race
        * condition here:  the queue might be full again by the
@@ -242,7 +244,19 @@ ssize_t msgrcv(int msqid, FAR void *msgp, size_t msgsz, long msgtyp,
         }
 
       msgq->cmn.nwaitnotfull--;
-      up_unblock_task(btcb);
+
+      /* Indicate that the wait is over. */
+
+      btcb->waitobj = NULL;
+
+      /* Add the task to ready-to-run task list and
+       * perform the context switch if one is needed
+       */
+
+      if (nxsched_add_readytorun(btcb))
+        {
+          up_unblock_task(btcb, rtcb);
+        }
     }
 
 errout_with_critical:
diff --git a/sched/mqueue/msgsnd.c b/sched/mqueue/msgsnd.c
index aac4983d52..f10407b132 100644
--- a/sched/mqueue/msgsnd.c
+++ b/sched/mqueue/msgsnd.c
@@ -216,6 +216,8 @@ int msgsnd(int msqid, FAR const void *msgp, size_t msgsz, int msgflg)
 
       if (msgq->cmn.nwaitnotempty > 0)
         {
+          FAR struct tcb_s *rtcb = this_task();
+
           /* Find the highest priority task that is waiting for
            * this queue to be non-empty in g_waitingformqnotempty
            * list. enter_critical_section() should give us sufficient
@@ -223,7 +225,7 @@ int msgsnd(int msqid, FAR const void *msgp, size_t msgsz, int msgflg)
            * in this list
            */
 
-          btcb = (FAR struct tcb_s *)dq_peek(MQ_WNELIST(msgq->cmn));
+          btcb = (FAR struct tcb_s *)dq_remfirst(MQ_WNELIST(msgq->cmn));
 
           /* If one was found, unblock it */
 
@@ -235,7 +237,19 @@ int msgsnd(int msqid, FAR const void *msgp, size_t msgsz, int msgflg)
             }
 
           msgq->cmn.nwaitnotempty--;
-          up_unblock_task(btcb);
+
+          /* Indicate that the wait is over. */
+
+          btcb->waitobj = NULL;
+
+          /* Add the task to ready-to-run task list and
+           * perform the context switch if one is needed
+           */
+
+          if (nxsched_add_readytorun(btcb))
+            {
+              up_unblock_task(btcb, rtcb);
+            }
         }
     }
 
diff --git a/sched/paging/pg_worker.c b/sched/paging/pg_worker.c
index 2a08b8c1ca..82dbc6ed47 100644
--- a/sched/paging/pg_worker.c
+++ b/sched/paging/pg_worker.c
@@ -215,6 +215,8 @@ static void pg_callback(FAR struct tcb_s *tcb, int result)
 
 static inline bool pg_dequeue(void)
 {
+  FAR struct tcb_s *wtcb = this_task();
+
   /* Loop until either (1) the TCB of a task that requires a fill is found,
    * OR (2) the g_watingforfill list becomes empty.
    */
@@ -253,7 +255,6 @@ static inline bool pg_dequeue(void)
                * if a new higher priority fill is required).
                */
 
-              FAR struct tcb_s *wtcb = this_task();
               if (wtcb->sched_priority > CONFIG_PAGING_DEFPRIO &&
                   wtcb->sched_priority > g_pftcb->sched_priority)
                 {
@@ -287,7 +288,15 @@ static inline bool pg_dequeue(void)
            */
 
           pginfo("Restarting TCB: %p\n", g_pftcb);
-          up_unblock_task(g_pftcb);
+
+          /* Add the task to ready-to-run task list and
+           * perform the context switch if one is needed
+           */
+
+          if (nxsched_add_readytorun(g_pftcb))
+            {
+              up_unblock_task(g_pftcb, wtcb);
+            }
         }
     }
   while (g_pftcb != NULL);
@@ -469,12 +478,22 @@ static inline void pg_alldone(void)
 
 static inline void pg_fillcomplete(void)
 {
+  FAR struct tcb_s *wtcb = this_task();
+
   /* Call up_unblocktask(g_pftcb) to make the task that just
    * received the fill ready-to-run.
    */
 
   pginfo("Restarting TCB: %p\n", g_pftcb);
-  up_unblock_task(g_pftcb);
+
+  /* Add the task to ready-to-run task list and
+   * perform the context switch if one is needed
+   */
+
+  if (nxsched_add_readytorun(g_pftcb))
+    {
+      up_unblock_task(g_pftcb, wtcb);
+    }
 }
 
 /****************************************************************************
@@ -506,6 +525,8 @@ static inline void pg_fillcomplete(void)
 
 int pg_worker(int argc, char *argv[])
 {
+  FAR struct tcb_s *wtcb = this_task();
+
   /* Loop forever -- Notice that interrupts will be disabled at all times
    * that this thread runs.  That is so that we can't lose signals or have
    * asynchronous page faults.
@@ -567,7 +588,15 @@ int pg_worker(int argc, char *argv[])
                */
 
               pginfo("Restarting TCB: %p\n", g_pftcb);
-              up_unblock_task(g_pftcb);
+
+              /* Add the task to ready-to-run task list and
+               * perform the context switch if one is needed
+               */
+
+              if (nxsched_add_readytorun(g_pftcb))
+                {
+                  up_unblock_task(g_pftcb, wtcb);
+                }
 
               /* Yes .. Start the next asynchronous fill.  Check the return
                * value to see a fill was actually started (false means that
@@ -644,7 +673,15 @@ int pg_worker(int argc, char *argv[])
            */
 
           pginfo("Restarting TCB: %p\n", g_pftcb);
-          up_unblock_task(g_pftcb);
+
+          /* Add the task to ready-to-run task list and
+           * perform the context switch if one is needed
+           */
+
+          if (nxsched_add_readytorun(g_pftcb))
+            {
+              up_unblock_task(g_pftcb, wtcb);
+            }
         }
 
       /* All queued fills have been processed */
diff --git a/sched/sched/sched.h b/sched/sched/sched.h
index 9dbc3ab2cb..b32a0ddda4 100644
--- a/sched/sched/sched.h
+++ b/sched/sched/sched.h
@@ -186,6 +186,14 @@ extern dq_queue_t g_waitingforsignal;
 extern dq_queue_t g_waitingforfill;
 #endif
 
+/* This is the list of all tasks that have been stopped
+ * via SIGSTOP or SIGTSTP
+ */
+
+#ifdef CONFIG_SIG_SIGSTOP_ACTION
+extern dq_queue_t g_stoppedtasks;
+#endif
+
 /* This the list of all tasks that have been initialized, but not yet
  * activated. NOTE:  This is the only list that is not prioritized.
  */
diff --git a/sched/semaphore/sem_post.c b/sched/semaphore/sem_post.c
index 475bc9d121..07dc2722ed 100644
--- a/sched/semaphore/sem_post.c
+++ b/sched/semaphore/sem_post.c
@@ -132,10 +132,12 @@ int nxsem_post(FAR sem_t *sem)
        * that we want.
        */
 
-      stcb = (FAR struct tcb_s *)dq_peek(SEM_WAITLIST(sem));
+      stcb = (FAR struct tcb_s *)dq_remfirst(SEM_WAITLIST(sem));
 
       if (stcb != NULL)
         {
+          FAR struct tcb_s *rtcb = this_task();
+
           /* The task will be the new holder of the semaphore when
            * it is awakened.
            */
@@ -149,9 +151,18 @@ int nxsem_post(FAR sem_t *sem)
               wd_cancel(&stcb->waitdog);
             }
 
-          /* Restart the waiting task. */
+          /* Indicate that the wait is over. */
+
+          stcb->waitobj = NULL;
+
+          /* Add the task to ready-to-run task list and
+           * perform the context switch if one is needed
+           */
 
-          up_unblock_task(stcb);
+          if (nxsched_add_readytorun(stcb))
+            {
+              up_unblock_task(stcb, rtcb);
+            }
         }
 #if 0 /* REVISIT:  This can fire on IOB throttle semaphore */
       else
diff --git a/sched/semaphore/sem_waitirq.c b/sched/semaphore/sem_waitirq.c
index cec1dc9804..5f732fa072 100644
--- a/sched/semaphore/sem_waitirq.c
+++ b/sched/semaphore/sem_waitirq.c
@@ -31,6 +31,7 @@
 #include <nuttx/irq.h>
 #include <nuttx/arch.h>
 
+#include "sched/sched.h"
 #include "semaphore/semaphore.h"
 
 /****************************************************************************
@@ -67,6 +68,7 @@
 
 void nxsem_wait_irq(FAR struct tcb_s *wtcb, int errcode)
 {
+  FAR struct tcb_s *rtcb = this_task();
   FAR sem_t *sem = wtcb->waitobj;
 
   /* It is possible that an interrupt/context switch beat us to the punch
@@ -89,11 +91,24 @@ void nxsem_wait_irq(FAR struct tcb_s *wtcb, int errcode)
 
   sem->semcount++;
 
+  /* Remove task from waiting list */
+
+  dq_rem((FAR dq_entry_t *)wtcb, SEM_WAITLIST(sem));
+
+  /* Indicate that the wait is over. */
+
+  wtcb->waitobj = NULL;
+
   /* Mark the errno value for the thread. */
 
   wtcb->errcode = errcode;
 
-  /* Restart the task. */
+  /* Add the task to ready-to-run task list and
+   * perform the context switch if one is needed
+   */
 
-  up_unblock_task(wtcb);
+  if (nxsched_add_readytorun(wtcb))
+    {
+      up_unblock_task(wtcb, rtcb);
+    }
 }
diff --git a/sched/signal/sig_dispatch.c b/sched/signal/sig_dispatch.c
index b10337e4af..26eb31dcc2 100644
--- a/sched/signal/sig_dispatch.c
+++ b/sched/signal/sig_dispatch.c
@@ -36,6 +36,7 @@
 #include <nuttx/irq.h>
 #include <nuttx/arch.h>
 #include <nuttx/signal.h>
+#include <nuttx/queue.h>
 
 #include "sched/sched.h"
 #include "group/group.h"
@@ -296,6 +297,7 @@ static void nxsig_add_pendingsignal(FAR struct tcb_s *stcb,
 
 int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info)
 {
+  FAR struct tcb_s *rtcb = this_task();
   irqstate_t flags;
   int masked;
   int ret = OK;
@@ -369,7 +371,19 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info)
               wd_cancel(&stcb->waitdog);
             }
 
-          up_unblock_task(stcb);
+          /* Remove the task from waitting list */
+
+          dq_rem((FAR dq_entry_t *)stcb, &g_waitingforsignal);
+
+          /* Add the task to ready-to-run task list and
+           * perform the context switch if one is needed
+           */
+
+          if (nxsched_add_readytorun(stcb))
+            {
+              up_unblock_task(stcb, rtcb);
+            }
+
           leave_critical_section(flags);
         }
 
@@ -411,7 +425,18 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info)
               wd_cancel(&stcb->waitdog);
             }
 
-          up_unblock_task(stcb);
+          /* Remove the task from waitting list */
+
+          dq_rem((FAR dq_entry_t *)stcb, &g_waitingforsignal);
+
+          /* Add the task to ready-to-run task list and
+           * perform the context switch if one is needed
+           */
+
+          if (nxsched_add_readytorun(stcb))
+            {
+              up_unblock_task(stcb, rtcb);
+            }
         }
 
       leave_critical_section(flags);
@@ -464,7 +489,18 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info)
 #ifdef HAVE_GROUP_MEMBERS
           group_continue(stcb);
 #else
-          up_unblock_task(stcb);
+          /* Remove the task from waitting list */
+
+          dq_rem((FAR dq_entry_t *)stcb, &g_stoppedtasks);
+
+          /* Add the task to ready-to-run task list and
+           * perform the context switch if one is needed
+           */
+
+          if (nxsched_add_readytorun(stcb))
+            {
+              up_unblock_task(stcb, rtcb);
+            }
 #endif
         }
 #endif
diff --git a/sched/signal/sig_timedwait.c b/sched/signal/sig_timedwait.c
index d8c7ffe276..b0a877c228 100644
--- a/sched/signal/sig_timedwait.c
+++ b/sched/signal/sig_timedwait.c
@@ -39,6 +39,7 @@
 #include <nuttx/wdog.h>
 #include <nuttx/signal.h>
 #include <nuttx/cancelpt.h>
+#include <nuttx/queue.h>
 
 #include "sched/sched.h"
 #include "signal/signal.h"
@@ -96,6 +97,8 @@ static void nxsig_timeout(wdparm_t arg)
 
   if (wtcb->task_state == TSTATE_WAIT_SIG)
     {
+      FAR struct tcb_s *rtcb = this_task();
+
       wtcb->sigunbinfo.si_signo           = SIG_WAIT_TIMEOUT;
       wtcb->sigunbinfo.si_code            = SI_TIMER;
       wtcb->sigunbinfo.si_errno           = ETIMEDOUT;
@@ -104,7 +107,19 @@ static void nxsig_timeout(wdparm_t arg)
       wtcb->sigunbinfo.si_pid             = 0;  /* Not applicable */
       wtcb->sigunbinfo.si_status          = OK;
 #endif
-      up_unblock_task(wtcb);
+
+      /* Remove the task from waitting list */
+
+      dq_rem((FAR dq_entry_t *)wtcb, &g_waitingforsignal);
+
+      /* Add the task to ready-to-run task list, and
+       * perform the context switch if one is needed
+       */
+
+      if (nxsched_add_readytorun(wtcb))
+        {
+          up_unblock_task(wtcb, rtcb);
+        }
     }
 
 #ifdef CONFIG_SMP
@@ -149,6 +164,8 @@ void nxsig_wait_irq(FAR struct tcb_s *wtcb, int errcode)
 
   if (wtcb->task_state == TSTATE_WAIT_SIG)
     {
+      FAR struct tcb_s *rtcb = this_task();
+
       wtcb->sigunbinfo.si_signo           = SIG_CANCEL_TIMEOUT;
       wtcb->sigunbinfo.si_code            = SI_USER;
       wtcb->sigunbinfo.si_errno           = errcode;
@@ -157,7 +174,19 @@ void nxsig_wait_irq(FAR struct tcb_s *wtcb, int errcode)
       wtcb->sigunbinfo.si_pid             = 0;  /* Not applicable */
       wtcb->sigunbinfo.si_status          = OK;
 #endif
-      up_unblock_task(wtcb);
+
+      /* Remove the task from waitting list */
+
+      dq_rem((FAR dq_entry_t *)wtcb, &g_waitingforsignal);
+
+      /* Add the task to ready-to-run task list, and
+       * perform the context switch if one is needed
+       */
+
+      if (nxsched_add_readytorun(wtcb))
+        {
+          up_unblock_task(wtcb, rtcb);
+        }
     }
 
 #ifdef CONFIG_SMP
diff --git a/sched/task/task_activate.c b/sched/task/task_activate.c
index 27f53137c6..97e6caba25 100644
--- a/sched/task/task_activate.c
+++ b/sched/task/task_activate.c
@@ -32,6 +32,8 @@
 #include <nuttx/arch.h>
 #include <nuttx/sched_note.h>
 
+#include "sched/sched.h"
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -56,6 +58,7 @@
 void nxtask_activate(FAR struct tcb_s *tcb)
 {
   irqstate_t flags = enter_critical_section();
+  FAR struct tcb_s *rtcb = this_task();
 
 #ifdef CONFIG_SCHED_INSTRUMENTATION
 
@@ -77,6 +80,18 @@ void nxtask_activate(FAR struct tcb_s *tcb)
   sched_note_start(tcb);
 #endif
 
-  up_unblock_task(tcb);
+  /* Remove the task from waitting list */
+
+  nxsched_remove_blocked(tcb);
+
+  /* Add the task to ready-to-run task list, and
+   * perform the context switch if one is needed
+   */
+
+  if (nxsched_add_readytorun(tcb))
+    {
+      up_unblock_task(tcb, rtcb);
+    }
+
   leave_critical_section(flags);
 }