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

📄 tsktask.cpp

📁 这是一个关于C++编程开发的算法!
💻 CPP
字号:
/*
   CPPTask - A Multitasking Kernel For C++

   Version 1.0 08-12-91

   Ported by Rich Smith from:

   Public Domain Software written by
      Thomas Wagner
      Patschkauer Weg 31
      D-1000 Berlin 33
      West Germany

   TSKTASK.CPP - task class member functions

   Subroutines:
        task::task
        task::~task
        task::operator new
        task::start_task
        task::wake_task
        task::tsk_enqueue
        task::tsk_unqueue
        task::tsk_enqtimer
        task::tsk_unqtimer
        task::tsk_runable
        task::set_priority
        task::get_priority
        task::set_state
        task::get_state
        task::set_user_flags
        task::set_system_flags
        task::get_flags
        task::set_retptr
        task::get_retptr
        task::set_retsize
        task::get_retsize
        task::get_next

*/

#include "task.hpp"
#include "tsklocal.hpp"

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

task::task (funcptr func,
            byteptr stackptr,
            word stksz,
            word priority,
            farptr arg)
{
   struct task_stack far *stk;

   if (func == NULL)
      {
      stkbot = NULL;
      stack = NULL;
      queue = &tsk_eligible;
      state = ST_RUNNING;
      flags = flags | F_CRIT;
      }
   else
      {
      stk = (struct task_stack far *)
            (stackptr + stksz - sizeof (struct task_stack));
      stk->r_ds = stk->r_es = tsk_dseg ();
      stk->r_bp = 0;
      stk->r_flags = tsk_flags ();
      stk->retn = func;
      stk->dummyret = killretn;
      stk->arg = arg;

      stkbot = stackptr;
      stack = (byteptr) stk;
      queue = NULL;
      state = ST_STOPPED;
      }
   next = NULL;
   prior = initprior = priority;
   timerq = new timer(0, NULL, TKIND_TASK, 0);
   timerq->strucp = (farptr) this;
}


/*
   ~task
      Removes a task from the system.
      CAUTION: The task control block may *not* be immediately re-used
               if it was enqueued in the timer queue. Check for
               task->timerq->tstate == TSTAT_IDLE before modifying
               the tcb.
*/

task::~task (void)
{
   byte st;
   CRITICAL;

   C_ENTER;


   if (this != &main_tcb)
   {
      if ((st = state) != ST_RUNNING)
         tsk_unqueue ();

      queue = NULL;
      tsk_kill ();
      if (st == ST_RUNNING)
         {
         tsk_current = NULL;
         tasker.schedule ();
         }
   C_LEAVE;
   }
}


void* task::operator new(size_t size)
{
   void *ptr;

   ptr = tsk_alloc(size);   // call protected memory allocation procedure

   if (ptr)
     ((tcbptr) ptr)->flags = F_TEMP;

   return ptr;
}


/*
   tsk_kill - mark task as killed.
*/

void far task::tsk_kill (void)
{
   state = ST_KILLED;

   // delete timerq element only if it is IDLE, otherwise mark it for
   // deletion by the timer_main function

   if (timerq->tstate != TSTAT_IDLE)
      {
      timerq->tstate = (byte) TSTAT_REMOVE;
      if (flags & F_TEMP)
         timerq->tkind |= TKIND_TEMP;
      }
   else 
      delete timerq;

   if (flags & F_STTEMP)
      delete stack;

}


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

int far task::start_task (void)
{
   CRITICAL;

   if (state == ST_STOPPED)
      {
      state = ST_ELIGIBLE;
      C_ENTER;
      tsk_enqueue (&tsk_eligible);
      C_LEAVE;
      return 0;
      }
   return -1;
}


/*
   wake_task
      Restarts a task waiting for an event or timeout. 
      Returns -1 if the task was not waiting or stopped.
*/

int far task::wake_task (void)
{
   CRITICAL;

   C_ENTER;
   if (state >= ST_ELIGIBLE)
      {
      C_LEAVE;
      return -1;
      }

   retptr = TWAKE;
   tsk_wakeup ();
   C_LEAVE;
   return 0;
}



/*
   get_priority
      Returns the priority of a task.
*/

word far task::get_priority (void)
{
   return prior;
}


/*
   set_priority
      Changes the priority of a task. If the task is enqueued in a
      queue, its position in the queue is affected.
*/

void far task::set_priority (word newprior)
{
   tqueptr que;
   CRITICAL;

   C_ENTER;
   prior = initprior = newprior;

   if ((state != ST_RUNNING) && ((que = queue) != NULL))
      {
      tsk_unqueue ();
      tsk_enqueue (que);
      }
   C_LEAVE;
}

/*
   set_user_flags
      Changes the user modifiable flags of the task.
*/

void far task::set_user_flags (byte newflags)
{
   CRITICAL;

   C_ENTER;
   flags = (flags & FL_SYSM) | (newflags & FL_USRM);
   C_LEAVE;
}


/*
   set_system_flags
      Changes the system modifiable flags of the task.
*/

void far task::set_system_flags (byte newflags)
{
   CRITICAL;

   C_ENTER;
   flags = (newflags & FL_SYSM) | (flags & FL_USRM);
   C_LEAVE;
}


/*
   tsk_enqueue  inserts a task into a queue based on priority.
*/

void far task::tsk_enqueue (tqueptr que)
{
   tcbptr last, curr;

   last = NULL;
   curr = *que;

   while (curr != NULL && curr->prior >= prior)
      {
      last = curr;
      curr = curr->next;
      }
   next = curr;
   if (last == NULL)
      *que = this;
   else
      last->next = this;
   queue = que;
}


/*
   tsk_unqueue 
      Removes a task from somewhere in the middle of a queue. It is only
      used when stopping or prematurely waking a task, since in all other 
      circumstances a task is only removed from the head of a queue.
*/

void far task::tsk_unqueue (void)
{
   tcbptr last, curr;

   if (state == ST_RUNNING || queue == NULL)
      return;

   last = NULL;
   curr = *queue;

   while (curr != this)
      {
      if (curr == NULL)
         return;
      last = curr;
      curr = curr->next;
      }

   if (last == NULL)
      *queue = curr->next;
   else
      last->next = curr->next;
   queue = NULL;
}


/*
   tsk_enqtimer inserts a task into the timer queue.
*/

void far task::tsk_enqtimer (dword tout)
{
   tlinkptr curr;

   if (tout == 0)
      return;

   /*
      Tasks are not sorted in the timer queue, so the task is inserted
      at the queue head. The timer task has to step through all tasks
      in the queue to cont down the timeout, so sorting would not bring
      any advantages.
   */

   curr = timerq;
   curr->timeout = tsk_timeout(tout);
   if (curr->tstate == TSTAT_IDLE)
      {
      curr->next = tsk_timer;
      tsk_timer = curr;
      }
   curr->tstate = TSTAT_COUNTDOWN;
}


/*
   tsk_unqtimer marks task for removal from the timer queue.
*/

void task::tsk_unqtimer(void)
{
   if (timerq->tstate != TSTAT_IDLE)
      timerq->tstate = (byte) TSTAT_REMOVE;
}


/*
   tsk_runable
      make a task eligible for running. The task is removed from the
      timer queue and enqueued in the eligible queue. The old "next"
      pointer of the tcb is returned. This assumes that the task
      is removed from the head of a queue.
*/

tcbptr far task::tsk_runable (void)
{
   tcbptr nxt;

   nxt = next;
   state = ST_ELIGIBLE;
   tsk_unqtimer ();
   tsk_enqueue (&tsk_eligible);
   return nxt;
}


/*
   tsk_wakeup
      make a task eligible for running. The task is removed from the
      timer queue and enqueued in the eligible queue. 
      This routine assumes that the task is removed from the middle of
      a queue.
*/

void far task::tsk_wakeup (void)
{
   state = ST_ELIGIBLE;
   tsk_unqueue ();
   tsk_unqtimer ();
   tsk_enqueue (&tsk_eligible);
}


/*
   tsk_wait - put current running task in wait state.
              Note that the task is NOT enqueued in the respective queue
              here, this is done by the scheduler based on the queue head
              pointer. Only the timeout queue is affected directly.
*/

void far tsk_wait (tqueptr que, dword timeout)
{
   tsk_current->state = ST_WAITING;
   tsk_current->queue = que;
   tsk_current->tsk_enqtimer (timeout);
   tasker.schedule ();
}


⌨️ 快捷键说明

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