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

📄 tsktask.c

📁 一个多任务操作系统CTask的源代码 用C语言编写
💻 C
字号:
/*
   --- Version 2.2 93-03-04 15:27 ---

   TSKTASK.C - CTask - Task creation and deletion.

   CTask - a Multitasking Kernel for C

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

   No rights reserved.

   This file is new with version 2.1.
   Version 2.1 separates the functions previously collected in tskmain.c into
         tskmain.c - Front ends for installation/removal
         tskinst.c - Install/Remove main kernel
         tskgrp.c  - Create/remove groups
         tsktask.c - Task creation and deletion
         tsktutl.c - Task utilities (get/set priority etc.)
         tskutil.c - General utilities (preemption, t_delay)
*/

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

#if (DOS)
extern void Localfunc tsk_get_dosswap (tcbptr task);
#endif

/*
   tsk_use_ndp is initialized by install_tasker, and may be changed
   to 0 by the user to enable or disable ndp handling for tasks
   being created.

   Note that setting tsk_use_ndp to 1 will have no effect if 
   install_tasker has determined that there is no NDP present, or
   if the NDP configuration flag is FALSE.
*/

int tsk_use_ndp = 0;


#pragma check_stack(off)

/*
   tsk_kill
      mark task as killed.

      CAUTION: Critical section assumed entered.
*/

local void Staticfunc tsk_kill (tcbptr task, int currtask)
{
   /*
      Note: The following test shouldn't be necessary. However,
      if ever an interrupt handler should cause the current task to
      be killed 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, and the task is the current
      task, we have to stop everything.
      The test is ommitted when we're not running under DOS.
   */

#if (DOS)
   if (currtask && GLOBDATA in_sched)
      tsk_fatal ("Kill while in Scheduler");
#endif

   task->state = ST_KILLED;
   task->qhead = LNULL;
   tsk_deqtimer (&task->timerq.link);

#if (TSK_NAMED)
   tsk_dequeue ((queptr)&task->name.list);
#endif

#if (TSK_DYNAMIC)
   if (!currtask)
      {
      if (task->flags & F_STTEMP)
         tsk_pfree (task->stkbot);   /* Bug fixed in 2.1, was 'task->stack' */
      if (task->flags & F_TEMP)
         tsk_pfree (task);
      }
   else if (task->flags & (F_STTEMP | F_TEMP))
      {
      task->qhead = &GLOBDATA kill_queue;
      if (GLOBDATA kill_task->state == ST_STOPPED)
         tsk_runable (GLOBDATA kill_task);
      }
#endif

   if (currtask)
      schedule ();
}

/*
   Killretn kills the current active task. It is used internally, but
   can also be called from outside. (However, *never* call it from an 
   interrupt handler!)
*/

void Taskfunc killretn (void)
{
   tsk_cli ();
   tsk_kill (GLOBDATA current_task, 1);
}


/*
   tsk_kill_queue
      Removes all tasks from a queue, and marks queue invalid. 
      For internal use only.

      CAUTION: Critical section assumed entered.
*/

void Localfunc tsk_kill_queue (queheadptr que)
{
   queptr curr, next;

   CHECK_QHEAD (que, "Task Kill Queue");

   for (curr = que->first; !(curr->kind & Q_HEAD); )
      {
      next = curr->next;
      tsk_kill ((tcbptr)curr, 0);
      curr = next;
      }
   tsk_init_qhead (que, 0xff);
}


/* ---------------------------------------------------------------------- */

/*
   create_task
      Initialises a tcb. The task is in stopped state initially.
*/

tcbptr Globalfunc create_task (tcbptr task,
                               funcptr func,
                               byteptr stack,
                               word stksz,
                               word prior,
                               farptr arg
                               TN(byteptr name)
                               )

{
   struct task_stack far *stk;
#if (CHECKING)
   word i;
#endif

#if (TSK_DYNAMIC)
   if (task == LNULL)
      {
      if ((task = (tcbptr) tsk_palloc (sizeof(tcb))) == LNULL)
         return LNULL;
      task->flags = F_TEMP;
      }
   else
      task->flags = 0;

   if (stack == LNULL)
      {
      if ((stack = (byteptr) tsk_palloc (stksz)) == LNULL)
         {
         if (task->flags & F_TEMP)
            tsk_pfree (task);
         return LNULL;
         }
      task->flags |= F_STTEMP;
      }
#else
   task->flags = 0;
#endif

   stk = (struct task_stack far *)(stack + stksz - sizeof (struct task_stack));
   stk->r_ds = task->t_es = tsk_dseg ();
   stk->r_flags = tsk_flags ();
   stk->retn = func;
   stk->dummyret = killretn;
   stk->arg = arg;
   task->t_bp = 0;

   task->stkbot = stack;
#if (CHECKING)
   for (i = 0; i < stksz - sizeof (struct task_stack); i++)
      *stack++ = (byte)i;
#endif
   task->stack = (byteptr) stk;
   task->cqueue.kind = TYP_TCB;
   task->cqueue.next = LNULL;
   task->qhead = LNULL;
   task->state = ST_STOPPED;
   task->cqueue.el.pri.prior = task->cqueue.el.pri.ini_prior = prior;
   task->timerq.link.el.ticks = task->timerq.elem.time.reload = 0L;
   task->timerq.link.kind = TYP_TIMER;
   task->timerq.link.next = LNULL;
   task->timerq.strucp = (farptr) task;
   task->timerq.struckind = TKIND_WAKE;
   task->timerq.flags = 0;
   task->save_func = task->rest_func = LNULL;
#if (DOS)
   task->sched_ent_func = LNULL;
#endif
   task->user_ptr = LNULL;

#if (GROUPS)
   task->group = task->homegroup = GLOBDATA current_task->group;
#endif
#if (DOS)
   task->indos = 0;
   task->t_new = 1;
   task->base_psp = task->group->create_psp;
   tsk_get_dosswap (task);
#endif

#if (TSK_NAMED)
   tsk_add_name (&task->name, name, TYP_TCB, task);
#endif

#if (EMS)
   if (GLOBDATA ems_savetsk != LNULL)
      GLOBDATA ems_savetsk (task);
#endif

#if (NDP)
   if (tsk_use_ndp && GLOBDATA ndp_present)
      task->flags |= F_USES_NDP;
#endif

   return task;
}


/*
   kill_task
      Removes a task from the system.
*/

void Globalfunc kill_task (tcbptr task)
{
   CRITICAL;

   CHECK_TCBPTR (task, "Kill Task");

   C_ENTER;
   if (task != GLOBDATA current_task)
      {
      if (task->state == ST_KILLED)
         return;
      else
         tsk_dequeue (&task->cqueue);

      tsk_kill (task, 0);
      }
   else
      tsk_kill (task, 1);

   C_LEAVE;
}


/*
   start_task
      Starts a stopped task. Returns -1 if the task was not stopped.
*/

int Globalfunc start_task (tcbptr task)
{
   CRITICAL;

   if (task == LNULL)
#if (GROUPS)
      task = GLOBDATA current_task->group->main_ptr;
#else
      task = GLOBDATA main_ptr;
#endif

   CHECK_TCBPTR (task, "Start Task");

   if (task->state == ST_STOPPED)
      {
      task->state = ST_ELIGIBLE;
      C_ENTER;
      tsk_runable (task);
      C_LEAVE;
      return 0;
      }
   return -1;
}


⌨️ 快捷键说明

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