Beispiel #1
0
/**
 *
 * @param evf
 *
 * @return TN_BOOL
 */
TN_BOOL scan_event_waitqueue (TN_EVENT_S *evf)
{
    CDLL_QUEUE_S *que;
    CDLL_QUEUE_S *tmp_que;
    TN_TCB_S     *task;
    TN_BOOL       fCond;
    TN_BOOL       wcflag;
    TN_BOOL       fBreak;

    /* Scan event wait queue (checking for empty - before function call) */

    wcflag = TN_FALSE;
    fBreak = TN_FALSE;
    que    = evf->wait_queue.next;

    for (;;)
    {
        task = get_task_by_tsk_queue(que);

        if (task->ewait_mode & TN_EVENT_WCOND_OR)
        {
            fCond = (TN_BOOL)((evf->pattern & task->ewait_pattern) != 0);
        }
        else
        {
            fCond = (TN_BOOL)((evf->pattern & task->ewait_pattern) == task->ewait_pattern);
        }

        if (fCond)
        {
            if (que->next == &(evf->wait_queue))
            {
                queue_remove_entry(que);
                fBreak = TN_TRUE;
            }
            else
            {
                tmp_que = que->next;
                queue_remove_entry(que);
                que = tmp_que;
            }

            task->ewait_pattern = evf->pattern;

            if (task_wait_complete(task, TN_FALSE))
                wcflag = TN_TRUE;

            if (fBreak)
                break;
        }
        else
        {
            if (que->next == &(evf->wait_queue))
                break;
            else
                que = que->next;
        }
    }
    return wcflag;
}
Beispiel #2
0
/**
 *
 * @param task
 *
 * @return TN_BOOL
 */
TN_BOOL try_lock_mutex (TN_TCB_S * task)
{
    TN_MUTEX_S *mutex;
    TN_BOOL     need_switch_context;

    need_switch_context = TN_FALSE;
    mutex = get_mutex_by_task_wait_queue(task->pwait_queue);

    if (mutex == TN_NULL)
        return need_switch_context;

    if (mutex->holder == TN_NULL)
    {
        if (enable_lock_mutex(task, TN_NULL))
        {
            queue_remove_entry(&(task->task_queue));
            queue_remove_entry(&(task->block_queue));

            if (task_wait_complete(task, TN_FALSE))
                need_switch_context = TN_TRUE;

            mutex->holder  = task;
            task->blk_task = TN_NULL;

            queue_add_tail(&(task->mutex_queue),&(mutex->mutex_queue));
            queue_add_tail(&tn_locked_mutexes_list,&(mutex->lock_mutex_queue));
        }
    }

    return need_switch_context;
}
Beispiel #3
0
//----------------------------------------------------------------------------
int change_running_task_priority(TN_TCB * task, int new_priority)
{
   int old_priority;

   old_priority = task->priority;

  //-- remove curr task from any (wait/ready) queue

   queue_remove_entry(&(task->task_queue));

  //-- If there are no ready tasks for the old priority
  //-- clear ready bit for old priority

   if(is_queue_empty(&(tn_ready_list[old_priority])))
      tn_ready_to_run_bmp &= ~(1<<old_priority);

   task->priority = new_priority;

  //-- Add task to the end of ready queue for current priority

   queue_add_tail(&(tn_ready_list[new_priority]), &(task->task_queue));
   tn_ready_to_run_bmp |= 1 << new_priority;
   find_next_task_to_run();

   return TRUE;
}
Beispiel #4
0
//-----------------------------------------------------------------------------
void task_to_non_runnable(TN_TCB * task)
{
   int priority;
   CDLL_QUEUE * que;

   priority = task->priority;
   que = &(tn_ready_list[priority]);

   //-- remove the curr task from any queue (now - from ready queue)

   queue_remove_entry(&(task->task_queue));

   if(is_queue_empty(que))  //-- No ready tasks for the curr priority
   {
      //-- remove 'ready to run' from the curr priority

      tn_ready_to_run_bmp &= ~(1<<priority);

      //-- Find highest priority ready to run -
      //-- at least, MSB bit must be set for the idle task

      find_next_task_to_run();   //-- v.2.6
   }
   else //-- There are 'ready to run' task(s) for the curr priority
   {
      if(tn_next_task_to_run == task)
         tn_next_task_to_run = get_task_by_tsk_queue(que->next);
   }
}
Beispiel #5
0
//-----------------------------------------------------------------------------
int tn_task_delete(TN_TCB * task)
{
   TN_INTSAVE_DATA
   int rc;

#if TN_CHECK_PARAM
   if(task == NULL)
      return TERR_WRONG_PARAM;
   if(task->id_task != TN_ID_TASK)
      return TERR_NOEXS;
#endif

   TN_CHECK_NON_INT_CONTEXT

   tn_disable_interrupt();

   rc = TERR_NO_ERR;

   if(task->task_state != TSK_STATE_DORMANT)
      rc = TERR_WCONTEXT;  //-- Cannot delete not-terminated task
   else
   {
      queue_remove_entry(&(task->create_queue));
      tn_created_tasks_qty--;
      task->id_task = 0;
   }

   tn_enable_interrupt();

   return rc;
}
Beispiel #6
0
//----------------------------------------------------------------------------
int tn_task_irelease_wait(TN_TCB * task)
{
   TN_INTSAVE_DATA_INT
   int rc;

#if TN_CHECK_PARAM
   if(task == NULL)
      return  TERR_WRONG_PARAM;
   if(task->id_task != TN_ID_TASK)
      return TERR_NOEXS;
#endif

   TN_CHECK_INT_CONTEXT

   tn_idisable_interrupt();

   if((task->task_state & TSK_STATE_WAIT) == 0)
      rc = TERR_WCONTEXT;
   else
   {
      queue_remove_entry(&(task->task_queue));
      task_wait_complete(task);

      rc = TERR_NO_ERR;
   }

   tn_ienable_interrupt();

   return rc;
}
Beispiel #7
0
/**
 *
 * @param task
 *
 * @return TN_RETVAL
 */
TN_RETVAL tnec_task_delete (TN_TCB_S *task)
{
    TN_UWORD tn_save_status_reg TN_UNUSED;            /* for SR save */
    TN_RETVAL      rc;

    if (task == TN_NULL)
        return TERR_WRONG_PARAM;

    if (task->id_task != TN_ID_TASK)
        return TERR_NOEXS;

    if (tn_is_non_task_context())
        return TERR_WCONTEXT;

    tn_disable_interrupt();

    rc = TERR_NO_ERR;

    for (;;)
    {
        if (task->task_state != TSK_STATE_DORMANT)
        {
            rc = TERR_WCONTEXT;
            break;
        }

        queue_remove_entry(&(task->create_queue));
        tn_created_tasks_qty--;
        task->id_task = TN_ID_UNKNOWN;
        break;
    }

    tn_enable_interrupt();
    return rc;
}
Beispiel #8
0
/**
 *
 * @param attr
 */
void tnec_task_exit (TN_UWORD attr)
{
    TN_UWORD       tn_save_status_reg TN_UNUSED;     /* for SR save */
    TN_TCB_S      *task;
    CDLL_QUEUE_S  *que;
    TN_MUTEX_S    *mutex;
    TN_UWORD      *ptr_stack;

    if (tn_is_non_task_context())
        return;

    tn_save_sr();               /* just for PIC24/dsPIC */
    tn_disable_interrupt();

    while (!is_queue_empty(&(tn_curr_run_task->mutex_queue)))
    {
        que   = queue_remove_head(&(tn_curr_run_task->mutex_queue));
        mutex = get_mutex_by_mutex_queue(que);
        do_unlock_mutex(mutex);
    }

    task = tn_curr_run_task;

    task_to_non_runnable(tn_curr_run_task);
    task_set_dormant_state(task);

    ptr_stack = tn_stack_init(task->task_func_addr,
                              task->stk_start,
                              task->stk_size,
                              task->task_func_param
                             );

    task->task_stk = ptr_stack;

    if (task->activate_count > 0)
    {
        task->activate_count--;
        task_to_runnable(task);
    }
    else
    {
        /* Alex B. - delete task only if activate counter = 0 ! */

        if (attr == TN_EXIT_AND_DELETE_TASK)
        {
            queue_remove_entry(&(task->create_queue));
            tn_created_tasks_qty--;
            task->id_task = TN_ID_UNKNOWN;
        }
    }

    tn_switch_context_exit(tn_save_status_reg); /* Exit from task with restore saved SR*/
}
Beispiel #9
0
Datei: tn.c Projekt: ADTL/AFGUI
//----------------------------------------------------------------------------
static void tn_timer_task_func(void * par)
{
   TN_INTSAVE_DATA
   volatile TN_TCB * task;
   volatile CDLL_QUEUE * curr_que;

   //-- User application init - user's objects initial (tasks etc.) creation

   tn_app_init();

   //-- Enable interrupt here ( include tick int)

   tn_cpu_int_enable();

   //-------------------------------------------------------------------------

   for(;;)
   {

     //------------ OS timer tick -------------------------------------

      tn_disable_interrupt();

      curr_que = tn_wait_timeout_list.next;
      while(curr_que != &tn_wait_timeout_list)
      {
         task = get_task_by_timer_queque((CDLL_QUEUE*)curr_que);
         if(task->tick_count != TN_WAIT_INFINITE)
         {
            if(task->tick_count > 0)
            {
               task->tick_count--;
               if(task->tick_count == 0) //-- Time out expiried
               {
                  queue_remove_entry(&(((TN_TCB*)task)->task_queue));
                  task_wait_complete((TN_TCB*)task);
                  task->task_wait_rc = TERR_TIMEOUT;
               }
            }
         }

         curr_que = curr_que->next;
      }

      task_curr_to_wait_action(NULL,
                               TSK_WAIT_REASON_SLEEP,
                               TN_WAIT_INFINITE);
      tn_enable_interrupt();

      tn_switch_context();
   }
}
Beispiel #10
0
//----------------------------------------------------------------------------
int task_wait_complete(TN_TCB * task) //-- v. 2.6
{
#ifdef USE_MUTEXES
   int fmutex;
   int curr_priority;
   TN_MUTEX * mutex;
   TN_TCB * mt_holder_task;
   CDLL_QUEUE * t_que;
#endif
   int rc = FALSE;

   if(task == NULL)
      return 0;

#ifdef USE_MUTEXES

   t_que = NULL;
   if(task->task_wait_reason == TSK_WAIT_REASON_MUTEX_I ||
         task->task_wait_reason == TSK_WAIT_REASON_MUTEX_C)
   {
      fmutex = TRUE;
      t_que = task->pwait_queue;
   }
   else
      fmutex = FALSE;

#endif

   task->pwait_queue  = NULL;
   task->task_wait_rc = TERR_NO_ERR;

   if(task->tick_count != TN_WAIT_INFINITE)
      queue_remove_entry(&(task->timer_queue));

   task->tick_count = TN_WAIT_INFINITE;

   if(!(task->task_state & TSK_STATE_SUSPEND))
   {
      task_to_runnable(task);
      rc = TRUE;
   }
   else  //-- remove WAIT state
      task->task_state = TSK_STATE_SUSPEND;


#ifdef USE_MUTEXES

   if(fmutex)
   {
      mutex = get_mutex_by_wait_queque(t_que);

      mt_holder_task = mutex->holder;
      if(mt_holder_task != NULL)
      {
         //-- if task was blocked by another task and its pri was changed
         //--  - recalc current priority

         if(mt_holder_task->priority != mt_holder_task->base_priority &&
             mt_holder_task->priority == task->priority)
         {
            curr_priority = find_max_blocked_priority(mutex,
                                             mt_holder_task->base_priority);

            set_current_priority(mt_holder_task, curr_priority);
            rc = TRUE;
         }
      }
   }
#endif

   task->task_wait_reason = 0; //-- Clear wait reason

   return rc;
}
Beispiel #11
0
//-----------------------------------------------------------------------------
int tn_task_terminate(TN_TCB * task)
{
   TN_INTSAVE_DATA

   int rc;
/* see the structure purpose in tn_task_exit() */
	 struct // v.2.7
	 {
#ifdef USE_MUTEXES
      CDLL_QUEUE * que;
      TN_MUTEX * mutex;
#endif
      volatile int stack_exp[TN_PORT_STACK_EXPAND_AT_EXIT];
   }data; 
	 
#if TN_CHECK_PARAM
   if(task == NULL)
      return  TERR_WRONG_PARAM;
   if(task->id_task != TN_ID_TASK)
      return TERR_NOEXS;
#endif

   TN_CHECK_NON_INT_CONTEXT

   tn_disable_interrupt();


   //--------------------------------------------------

   rc = TERR_NO_ERR;

   if(task->task_state == TSK_STATE_DORMANT || tn_curr_run_task == task)
      rc = TERR_WCONTEXT; //-- Cannot terminate running task
   else
   {
      if(task->task_state == TSK_STATE_RUNNABLE)
         task_to_non_runnable(task);
      else if(task->task_state & TSK_STATE_WAIT)
      {
         //-- Free all queues, involved in the 'waiting'

         queue_remove_entry(&(task->task_queue));

         //-----------------------------------------

         if(task->tick_count != TN_WAIT_INFINITE)
            queue_remove_entry(&(task->timer_queue));
      }

      //-- Unlock all mutexes, locked by the task

#ifdef USE_MUTEXES
      while(!is_queue_empty(&(task->mutex_queue)))
      {
         data.que = queue_remove_head(&(task->mutex_queue));
         data.mutex = get_mutex_by_mutex_queque(data.que);
         do_unlock_mutex(data.mutex);
      }
#endif

      task_set_dormant_state(task);
			//-- Pointer to task top of the stack when not running

      task->task_stk = tn_stack_init(task->task_func_addr,
                                     task->stk_start,
                                     task->task_func_param);
       
      if(task->activate_count > 0) //-- Cannot terminate
      {
         task->activate_count--;

         task_to_runnable(task);
         tn_enable_interrupt();
         tn_switch_context();

         return TERR_NO_ERR;
      }
   }

   tn_enable_interrupt();

   return rc;
}
Beispiel #12
0
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void tn_task_exit(int attr)
{
	/*  
	  The structure is used to force GCC compiler properly locate and use
   	'stack_exp' - thanks to Angelo R. Di Filippo
	*/
   struct  // v.2.7
   {	
#ifdef USE_MUTEXES
      CDLL_QUEUE * que;
      TN_MUTEX * mutex;
#endif
      TN_TCB * task;
      volatile int stack_exp[TN_PORT_STACK_EXPAND_AT_EXIT];
   }data;
	 
   TN_CHECK_NON_INT_CONTEXT_NORETVAL

#ifdef TNKERNEL_PORT_MSP430X
   __disable_interrupt();
#else
   tn_cpu_save_sr();  //-- For ARM - disable interrupts without saving SPSR
#endif

   //--------------------------------------------------

   //-- Unlock all mutexes, locked by the task

#ifdef USE_MUTEXES
   while(!is_queue_empty(&(tn_curr_run_task->mutex_queue)))
   {
      data.que = queue_remove_head(&(tn_curr_run_task->mutex_queue));
      data.mutex = get_mutex_by_mutex_queque(data.que);
      do_unlock_mutex(data.mutex);
   }
#endif

   data.task = tn_curr_run_task;
   task_to_non_runnable(tn_curr_run_task);

   task_set_dormant_state(data.task);
	 //-- Pointer to task top of stack,when not running
   data.task->task_stk = tn_stack_init(data.task->task_func_addr,
                                  data.task->stk_start,
                                  data.task->task_func_param);

   if(data.task->activate_count > 0)  //-- Cannot exit
   {
      data.task->activate_count--;
      task_to_runnable(data.task);
   }
   else  // V 2.6 Thanks to Alex Borisov
   {
      if(attr == TN_EXIT_AND_DELETE_TASK)
      {
         queue_remove_entry(&(data.task->create_queue));
         tn_created_tasks_qty--;
         data.task->id_task = 0;
      }
   }

   tn_switch_context_exit();  // interrupts will be enabled inside tn_switch_context_exit()
}
Beispiel #13
0
/**
 *
 * @param mutex
 *
 * @return TN_BOOL
 */
TN_BOOL do_unlock_mutex (TN_MUTEX_S *mutex)
{
    CDLL_QUEUE_S *curr_que;
    TN_MUTEX_S   *tmp_mutex;
    TN_TCB_S     *task;
    TN_TCB_S     *hi_pri_task = TN_NULL;
    TN_TCB_S     *blk_task;
    TN_TCB_S     *tmp_task;
    TN_UWORD     priority;
    TN_UWORD     pr;
    TN_BOOL      need_switch_context = TN_FALSE;

    queue_remove_entry(&(mutex->mutex_queue));
    queue_remove_entry(&(mutex->lock_mutex_queue));

    if (is_queue_empty(&(tn_curr_run_task->mutex_queue)))
    {
        need_switch_context = set_current_priority(tn_curr_run_task, tn_curr_run_task->base_priority);
    }
    else
    {
        if (mutex->attr == TN_MUTEX_ATTR_INHERIT  ||
            mutex->attr == TN_MUTEX_ATTR_CEILING
           )
        {
            pr       = tn_curr_run_task->base_priority;
            curr_que = tn_curr_run_task->mutex_queue.next;

            for (;;)
            {
                tmp_mutex = get_mutex_by_mutex_queue(curr_que);
                pr        = find_max_blocked_priority(tmp_mutex,pr);

                if (curr_que->next == &(tn_curr_run_task->mutex_queue))
                    break;
                else
                {
                    curr_que = curr_que->next;
                }
            }

            if (pr != tn_curr_run_task->priority)
            {
                need_switch_context = set_current_priority(tn_curr_run_task,pr);
            }
        }
    }

    if (is_queue_empty(&(mutex->wait_queue)))
    {
        mutex->holder = TN_NULL;
        hi_pri_task   = tn_curr_run_task;
    }
    else
    {
        if (mutex->attr == TN_MUTEX_ATTR_CEILING)
        {
            priority = TN_NUM_PRIORITY - 1;
            curr_que = mutex->wait_queue.next;

            for (;;)
            {
                task = get_task_by_tsk_queue(curr_que);

                if (task->priority < priority)
                {
                    hi_pri_task = task;
                    priority    = task->priority;
                }
                if (curr_que->next == &(mutex->wait_queue))
                    break;
                else
                    curr_que = curr_que->next;
            }

            if (enable_lock_mutex(hi_pri_task,&blk_task))
            {
                queue_remove_entry(&(hi_pri_task->task_queue));
                remove_task_from_blocked_list(hi_pri_task);

                if (task_wait_complete(hi_pri_task, TN_FALSE))
                    need_switch_context = TN_TRUE;

                mutex->holder         = hi_pri_task;
                hi_pri_task->blk_task = TN_NULL;

                queue_add_tail(&(hi_pri_task->mutex_queue),&(mutex->mutex_queue));
                queue_add_tail(&tn_locked_mutexes_list,&(mutex->lock_mutex_queue));
            }
            else
            {
                if (!queue_contains_entry(&tn_blocked_tasks_list, &(hi_pri_task->block_queue)))
                {
                    queue_add_tail(&tn_blocked_tasks_list,&(hi_pri_task->block_queue));
                    hi_pri_task->task_wait_reason = TSK_WAIT_REASON_MUTEX_C_BLK;
                    hi_pri_task->blk_task         = blk_task;
                }
            }
        }
        else if (mutex->attr == TN_MUTEX_ATTR_INHERIT)
        {
            curr_que = queue_remove_head(&(mutex->wait_queue));
            task     = get_task_by_tsk_queue(curr_que);

            if (task_wait_complete(task, TN_FALSE))
                need_switch_context = TN_TRUE;

            mutex->holder = task;

            queue_add_tail(&(task->mutex_queue),&(mutex->mutex_queue));
/*--- v.2.3 */
            queue_add_tail(&tn_locked_mutexes_list,&(mutex->lock_mutex_queue));
/*---       */
        }
    }

    if (mutex->holder == TN_NULL && mutex->attr == TN_MUTEX_ATTR_CEILING)
    {
        if (!is_queue_empty(&tn_blocked_tasks_list))
        {
            curr_que = tn_blocked_tasks_list.next;
            for (;;)
            {
                tmp_task = get_task_by_block_queue(curr_que);
    
                if (tmp_task != hi_pri_task)
                {
                    if (try_lock_mutex(tmp_task))
                    {
                        need_switch_context = TN_TRUE;
                    }
                }
                if (curr_que->next == &tn_blocked_tasks_list)
                    break;
                else
                    curr_que = curr_que->next;
            }
        }
    }

    return need_switch_context;
}
Beispiel #14
0
//-----------------------------------------------------------------------------
int tn_task_terminate(TN_TCB * task)
{
   TN_INTSAVE_DATA

   int rc;
   unsigned int * ptr_stack;

#ifdef USE_MUTEXES
   CDLL_QUEUE * que;
   TN_MUTEX * mutex;
#endif

   volatile int stack_exp[TN_PORT_STACK_EXPAND_AT_EXIT];

#if TN_CHECK_PARAM
   if(task == NULL)
      return  TERR_WRONG_PARAM;
   if(task->id_task != TN_ID_TASK)
      return TERR_NOEXS;
#endif

   TN_CHECK_NON_INT_CONTEXT

   tn_disable_interrupt();

   //-- To use stack_exp[] and avoid warning message

   stack_exp[0] = (int)tn_system_state;
   ptr_stack =(unsigned int *)stack_exp[0];

   //--------------------------------------------------

   rc = TERR_NO_ERR;

   if(task->task_state == TSK_STATE_DORMANT || tn_curr_run_task == task)
      rc = TERR_WCONTEXT; //-- Cannot terminate running task
   else
   {
      if(task->task_state == TSK_STATE_RUNNABLE)
         task_to_non_runnable(task);
      else if(task->task_state & TSK_STATE_WAIT)
      {
         //-- Free all queues, involved in the 'waiting'

         queue_remove_entry(&(task->task_queue));

         //-----------------------------------------

         if(task->tick_count != TN_WAIT_INFINITE)
            queue_remove_entry(&(task->timer_queue));
      }
#if (TN_SUPPORT_FPU == 2)
      if (tn_fpu_owner_task == task)
      {
          tn_fpu_owner_task = NULL;
      }
#endif

      //-- Unlock all mutexes, locked by the task

#ifdef USE_MUTEXES
      while(!is_queue_empty(&(task->mutex_queue)))
      {
         que = queue_remove_head(&(task->mutex_queue));
         mutex = get_mutex_by_mutex_queque(que);
         do_unlock_mutex(mutex);
      }
#endif

      task_set_dormant_state(task);
      ptr_stack = tn_stack_init(task->task_func_addr,
                             task->stk_start,
                             task->task_func_param);
      task->task_stk = ptr_stack;  //-- Pointer to task top of the stack
                                   //-- when not running

      if(task->activate_count > 0) //-- Cannot terminate
      {
         task->activate_count--;

         task_to_runnable(task);
         tn_enable_interrupt();
         tn_switch_context();

         return TERR_NO_ERR;
      }
   }

   tn_enable_interrupt();

   return rc;
}
Beispiel #15
0
//----------------------------------------------------------------------------
void tn_task_exit(int attr)
{

#ifdef USE_MUTEXES
   CDLL_QUEUE * que;
   TN_MUTEX * mutex;
#endif

   TN_TCB * task;
   unsigned int * ptr_stack;
   volatile int stack_exp[TN_PORT_STACK_EXPAND_AT_EXIT];

   TN_CHECK_NON_INT_CONTEXT_NORETVAL

#ifdef TNKERNEL_PORT_MSP430X
   __disable_interrupt();
#else
   tn_cpu_save_sr();  //-- For ARM - disable interrupts without saving SPSR
#endif

   //-- To use stack_exp[] and avoid warning message

   stack_exp[0] = (int)tn_system_state;
   ptr_stack =(unsigned int *)stack_exp[0];
   //--------------------------------------------------

   //-- Unlock all mutexes, locked by the task

#ifdef USE_MUTEXES
   while(!is_queue_empty(&(tn_curr_run_task->mutex_queue)))
   {
      que = queue_remove_head(&(tn_curr_run_task->mutex_queue));
      mutex = get_mutex_by_mutex_queque(que);
      do_unlock_mutex(mutex);
   }
#endif

   task = tn_curr_run_task;
   task_to_non_runnable(tn_curr_run_task);

   task_set_dormant_state(task);
   ptr_stack = tn_stack_init(task->task_func_addr,
                             task->stk_start,
                             task->task_func_param);
   task->task_stk = ptr_stack;  //-- Pointer to task top of stack,when not running

   if(task->activate_count > 0)  //-- Cannot exit
   {
      task->activate_count--;
      task_to_runnable(task);
   }
   else  // V 2.6 Thanks to Alex Borisov
   {
      if(attr == TN_EXIT_AND_DELETE_TASK)
      {
         queue_remove_entry(&(task->create_queue));
         tn_created_tasks_qty--;
         task->id_task = 0;
      }
   }

   tn_switch_context_exit();  // interrupts will be enabled inside tn_switch_context_exit()
}
Beispiel #16
0
/**
 *
 * @param task
 *
 * @return TN_RETVAL
 */
TN_RETVAL tnnc_task_terminate (TN_TCB_S *task)
{
    TN_UWORD       tn_save_status_reg TN_UNUSED;     /* for SR save */
    TN_RETVAL      rc;
    TN_UWORD      *ptr_stack;
    CDLL_QUEUE_S  *que;
    TN_MUTEX_S    *mutex;

/*
    Not check parameter error

    if (task == TN_NULL)
        return TERR_WRONG_PARAM;

*/

    if (task->id_task != TN_ID_TASK)
        return TERR_NOEXS;

    if (tn_is_non_task_context())
    {
        return TERR_WCONTEXT;
    }

    tn_disable_interrupt();

    rc = TERR_NO_ERR;

    if ((task->task_state == TSK_STATE_DORMANT) || (tn_curr_run_task == task))
    {
        rc = TERR_WCONTEXT;
    }
    else
    {
        if (task->task_state == TSK_STATE_RUNNABLE)
        {
            task_to_non_runnable(task);
        }
        else if (task->task_state & TSK_STATE_WAIT)
        {
            queue_remove_entry(&(task->task_queue));

            if (queue_contains_entry(&tn_blocked_tasks_list, &(task->block_queue)))
            {
                queue_remove_entry(&(task->block_queue));
            }
            if (task->tick_count != TN_WAIT_INFINITE)
            {
                queue_remove_entry(&(task->timer_queue));
            }
        }


        while (!is_queue_empty(&(task->mutex_queue)))
        {
            que   = queue_remove_head(&(task->mutex_queue));
            mutex = get_mutex_by_mutex_queue(que);
            do_unlock_mutex(mutex);
        }

        task_set_dormant_state(task);

        ptr_stack = tn_stack_init(task->task_func_addr,
                                  task->stk_start,
                                  task->stk_size,
                                  task->task_func_param
                                 );

        task->task_stk = ptr_stack;

        if (task->activate_count > 0)
        {
            task->activate_count--;

            task_to_runnable(task);
            tn_enable_interrupt();

            if ((tn_next_task_to_run != tn_curr_run_task) && (tn_enable_switch_context != TN_FALSE))
            {
                tn_switch_context();
            }
            return TERR_NO_ERR;
        }
    }
    tn_enable_interrupt();
    return rc;
}