⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tsksub.c

📁 一个可以立即使用的嵌入式操作系统
💻 C
字号:
/*
   --- Version 2.2 92-09-02 12:42 ---

   CTask Subroutines

   Public Domain Software written by
      Thomas Wagner
      Ferrari electronic Gmbh
      Beusselstrasse 27
      D-1000 Berlin 21
      Germany

   Note: The find_xxx_name functions were moved to a separate file,
   'tskname.c', in version 2.1 for potential code savings.
*/

#include "tsk.h"
#include "tsklocal.h"


/*
   tsk_runable
      Make a task eligible for running. The task is removed from the
      timer queue and enqueued in the eligible queue.

      CAUTION: Critical section assumed entered.
*/

void Localfunc tsk_runable (tcbptr task)
{
   CHECK_TCBPTR (task, "Task Runable");

   task->state = ST_ELIGIBLE;
   tsk_deqtimer (&task->timerq.link);
   tsk_dequeue (&task->cqueue);
   tsk_enqueue (task->qhead = &GLOBDATA eligible_queue, &task->cqueue);
}


/*
   tsk_run_pending
      Make a task eligible for running, but don't enqueue it in the
      eligible queue.

      CAUTION: Critical section assumed entered.
*/

void Localfunc tsk_run_pending (tcbptr task)
{
   CHECK_TCBPTR (task, "Task Runable");

   task->state = ST_ELIGIBLE;
   tsk_deqtimer (&task->timerq.link);
   tsk_dequeue (&task->cqueue);
}


/*
   tsk_runable_all
      Make all tasks in a queue eligible for running.

      CAUTION: Critical section assumed entered.
*/

void Localfunc tsk_runable_all (queheadptr que)
{
   queptr curr;
   tcbptr task;

   CHECK_QHEAD (que, "Task Runable All: Queue");

   for (curr = que->first; !(curr->kind & Q_HEAD); )
      {
      task = (tcbptr)curr;
      CHECK_TCBPTR (task, "Task Runable All: TCB");
      curr = curr->next;
      task->state = ST_ELIGIBLE;
      tsk_deqtimer (&task->timerq.link);
      tsk_enqueue (task->qhead = &GLOBDATA eligible_queue, &task->cqueue);
      }
   tsk_init_qhead (que, que->kind);
}


/*
   tsk_wait
      put current running task in wait state.

      With version 2.2, the wait action was changed to immediately
      enqueue the task into the respective queue. In previous versions,
      the task was not enqueued, this was done by the scheduler based 
      on the queue head pointer. Starting with version 2.1, interrupts 
      are enabled early in the scheduler, before the scheduler gets to 
      the point where it enqueues the task. This could lead to race 
      conditions, with tasks being only partially enqueued, or never 
      dequeued, when "tsk_runable" was called by an interrupt handler
      hitting in this interval.

      CAUTION: Critical section assumed entered.
*/

void Localfunc tsk_wait (queheadptr que, dword timeout)
{
   tcbptr curr;

   /*
      Note: The following test shouldn't be necessary. However,
      if ever an interrupt handler should cause the current task to
      be made waiting while the scheduler is active, this would cause
      catastrophic effects (also see the notes in tskasm.asm).
      Well, no interrupt handler should ever do such a nasty thing, but...
      So if the in_sched flag is set, we have to stop everything.
      The test is ommitted when we're not running under DOS.
   */

#if (DOS || DEBUG)
   if (GLOBDATA in_sched)
      tsk_fatal ("Wait while in Scheduler");
#endif

   CHECK_QHEAD (que, "Task Wait: Queue");

   curr = GLOBDATA current_task;
   curr->state = ST_WAITING;
   tsk_enqueue (curr->qhead = que, &curr->cqueue);
   if (timeout)
      {
      tsk_enqtimer (&curr->timerq.link, tsk_timeout(timeout));
      curr->timerq.flags = 0;
      curr->timerq.link.kind = TYP_TIMER;
      }
   schedule ();
}


#if (TSK_NAMED)

/*
   tsk_copy_name
      A replacement for strcpy, used for copying names. The C-runtime
      strcpy is not used here to keep the kernel model independent.
*/

void Localfunc tsk_copy_name (nameptr elem, byteptr name)
{
   byteptr n;
   int i;

   n = elem->name;
   if (name != LNULL)
      for (i = 0; i < 8; i++)
         if ((*n++ = *name++) == 0)
            break;
   *n = 0;
}


/*
   tsk_add_name
      Initialise name-list element and insert it into the name list.
      NOTE: no check is made for duplicate names; names are not sorted.
      Version 2.1 allows name pointers to be LNULL. Structures with LNULL
      name pointers are not added to the list.
*/

void Localfunc tsk_add_name (nameptr elem, byteptr name, byte kind, farptr strucp)
{
   CRITICAL;

   elem->list.kind = kind;
   elem->strucp = strucp;
   if (name == LNULL)
      {
      elem->list.first = LNULL;
      elem->name [0] = 0;
      return;
      }

   tsk_copy_name (elem, name);

   C_ENTER;
#if (GROUPS)
   tsk_putqueue (&GLOBDATA current_task->group->namelist.list, (queptr)&elem->list);
#else
   tsk_putqueue (&GLOBDATA name_list.list, (queptr)&elem->list);
#endif
   C_LEAVE;
}


/*
   tsk_del_name
      delete name-element from the name-list.
*/

void Localfunc tsk_del_name (nameptr elem)
{
   CRITICAL;

   C_ENTER;
   tsk_dequeue ((queptr)&elem->list);
   C_LEAVE;
}

#endif


/*
   tsk_init_qhead
      Initializes the head of a queue.
*/

void Localfunc tsk_init_qhead (queheadptr head, byte kind)
{
   head->kind = Q_HEAD | kind;
   head->first = head->last = (queptr)head;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -