Listing 4. Context Switch Function

void _DSP_K_SWITCH( t__DSP_K_TSKID const new_task )
{
  volatile t__DSP_K_tcb *tsk; /* context stack */
  volatile t__DSP_K_TSKID next = new_task;

    /* if task lock on then exit switcher */
  asm( "bit tst ustat2 0x4;" );
  asm( "if tf jump( pc, switchend );" );

    /* switch to same task? */
  if( next != __DSP_K_context.current )
  {
    /* 
     * perform context switch 
    */
    tsk = &__DSP_K_context.tasks
            [ __DSP_K_context.current ];
      /* no save if deleted */
    if( tsk->state != DSP_K_STATE_NULL )
    {
        /* is current thread pended? */
      if( tsk->state == DSP_K_STATE_RUN )
      {
          /* return it to ready state */
        tsk->state = DSP_K_STATE_READY;
      }

      /* push current thread context */
          /* ...assembler detail omitted... */
    }

    __DSP_K_context.current = next;
    __DSP_K_context.tasks[ next ].state = 
      DSP_K_STATE_RUN;

    /* pop next context */
      /* ...assembler detail omitted... */

    /* set up a C stack frame and run next task */
      /* ...assembler detail omitted... */

    /* jump onto new task frame */
    asm( "i12=dm( m7,i6 );" );
      /* out ISR and no schedule pending */
    asm( "bit clr ustat2 0x48;" );
    __DSP_K_OUT_KERNEL;
    asm( "jump( m14,i12 )(db);" );
      /* preserve i12 (see dsp_K.asm) */
    asm( "i12=dm( m6,i7 );" );
    asm( "rframe;" );

  }
  else
  {
    __DSP_K_OUT_KERNEL;
  }

  asm( "switchend:" );
  return;
}