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

📄 tskmain.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

   TSKMAIN.CPP - Main routines for task handling.

   Subroutines:
        timer_main
        int9
        tasker_class::tasker_class
        tasker_class::~tasker_class
        tasker_class::preempt_on
        tasker_class::preempt_off
        tasker_class::tsk_ena_preempt
        tasker_class::tsk_dis_preempt
        tasker_class::schedule
        tasker_class::c_schedule
        asm_remove_tasker

*/

#include <stdio.h>

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

#define STACKSIZE 512

/*
   The task queues:
      All tasks using a timeout, either through "t_delay" or an event wait,
      are enqueued into the "tsk_timer" queue, using the "timerq" link.
      All tasks eligible for running are enqueued in "tsk_eligible".
      The tcb-address of the current running task is stored in "tsk_current".
*/

tlinkptr   tsk_timer = NULL;
timer      null_timer_node(0, NULL, TKIND_TASK, 0);
tcbptr     tsk_eligible;
tcbptr     tsk_current;

/*
   System flags:
      tsk_preempt is zero if preemption is allowed.
                  Bit 0 is set if preemption has been disabled globally.
                  Bit 1 is set for temporary disabling preemption.
                  Temporary preemption is automatically removed by the
                  scheduler.

      tsk_pretick is nonzero if a schedule request from an interrupt handler
                  was rejected due to tsk_preempt nonzero. This allows
                  an immediate scheduling whenever tsk_preempt is set to 0.

      tsk_var_prior Can be set nonzero to enable variable priority.
                    Variable priority will increase the priority of
                    eligible tasks on each scheduler call while they 
                    are waiting to be executed, so that low priority 
                    tasks will slowly get to the head of the eligible
                    queue, getting a chance to be run. With variable
                    priority off, lower priority tasks will never be
                    executed while higher priority tasks are eligible.
                    
*/

byte  tsk_preempt;
byte  tsk_pretick;
byte  tsk_var_prior;

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

/*
   The tcb's of the standard tasks.

      timer_tcb   is the tcb for the timer task.
                  This task waits for the tsk_timer_counter, which is
                  increased on every timer tick. It processes the entries
                  in the timeout queue.

      int9_tcb    is the tcb for the int9 chain task.
                  This task waits for the tsk_int9_counter, which is
                  increased on every system timer tick. It then chains to
                  the previous timer interrupt entry.

      main_tcb    is the "main" task which called "install_tasker". This
                  task has no separate stack, rather the stack on entry
                  to the scheduler is used.

*/

counter tsk_timer_counter;
local char timer_stack [STACKSIZE];
local void far timer_main (void);
local task timer_tcb((funcptr) timer_main, (byteptr) timer_stack,
                     STACKSIZE, PRI_TIMER, NULL);

local task main_tcb(NULL, NULL, STACKSIZE, PRI_TIMER, NULL);

#if (IBM)
counter tsk_int9_counter;
local void far int9 (void);
local char int9_stack [STACKSIZE];
local task int9_tcb((funcptr) int9, (byteptr) int9_stack,
                    STACKSIZE, PRI_INT9, NULL);
#endif

resource alloc_resource;

#if (DOS)
resource lower_dos;
resource upper_dos;
flag critical;
#endif

word keyboardbuffer[80];
wpipe key_avail((farptr) keyboardbuffer, sizeof(keyboardbuffer));

tasker_class tasker(0, 0);

#if (CLOCK_MSEC)
double  tick_factor;
#endif

word  ticks_per_sec;


/*
   Un-Install-Function pointers for the optional serial and printer 
   drivers. If ports are installed, the driver inserts the address
   of a remove-function here, to be called on removal of the main
   tasker.
*/

funcptr v24_remove_func = NULL;
funcptr prt_remove_func = NULL;


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

#pragma check_stack(off)

/*
   The timer_main task handles all timeouts.
   It maintains a single timer queue, which contains elements of the
   "tlink" structure. No other task is allowed to manipulate this queue,
   except for the insertion of new elements at the queue head. This allows
   stepping through the queue with interrupts enabled.
   CAUTION: This assumes that the operation of loading a far pointer
            is indivisible!
*/

local void far timer_main (void)
{
   tlinkptr curr;
   tlinkptr last;
   byte state;
   CRITICAL;

   while (1)
      {
      tsk_timer_counter.wait_counter_set (0L);

      last = (tlinkptr) &tsk_timer;

      while ((curr = last->next) != NULL)
         {
         /* Enter critical section for access to state and timeout
            variables. The timer action is also critical.
         */
         C_ENTER;
         if ((state = curr->tstate) >= TSTAT_COUNTDOWN)
            if (!--curr->timeout)
               {
               if (state == TSTAT_COUNTDOWN)
                  state = (byte) TSTAT_REMOVE;
               else
                  curr->timeout = curr->reload;

               curr->tsk_timer_action();
               }
         if (state == (byte) TSTAT_REMOVE)
            {
            last->next = curr->next;
            curr->tstate = TSTAT_IDLE;

            if (curr->tkind & TKIND_TEMP)
               delete curr;

            curr = last;
            }
         C_LEAVE;
         last = curr;
         }
      }
}

/*
   int9 is the timer interrupt chain task.
*/

#if (IBM)

local void far int9 (void)
{
   while (1)
      {
      tsk_int9_counter.wait_counter_set (0L);
      tsk_chain_timer ();
      }
}

#endif

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


/*
   tasker_class
      Installs the Ctask system. The internal tasks are created,
      the queues are initialised, and the interrupt handler installation
      routines are called. Task preemption is initially off.

      Handling of the speedup parameter is system dependent.
*/

tasker_class::tasker_class (byte varpri, int speedup)
{
   word divisor, sys_ticks;

   tsk_current = &main_tcb;
   tsk_eligible = NULL;
   tsk_timer = &null_timer_node;
   tsk_preempt = 1;
   tsk_pretick = 0;
   tsk_var_prior = varpri;

   timer_tcb.start_task ();

#if (IBM)
   int9_tcb.start_task ();

   if (speedup <= 0 || speedup > 8)
      {
      divisor = 0;
      sys_ticks = 1;
      }
   else
      {
      divisor = 0x8000 >> (speedup - 1);
      sys_ticks = 1 << speedup;
      }

   ticks_per_sec = 18 * sys_ticks;  /* rough number only */

#if (CLOCK_MSEC)
   tick_factor = (65536.0 / (double)sys_ticks) / 1193.18;
#endif

     tsk_install_timer (divisor, sys_ticks);
     tsk_install_kbd ();
#endif

#if (AT_BIOS)
//   tsk_install_bios ();
#endif

#if (DOS)
     tsk_install_dos ();
#endif
}


/*
   ~tasker_class
      Calls the interrupt handler un-install routines.
*/

tasker_class::~tasker_class (void)
{
   tsk_preempt = 0;

#if (AT_BIOS)
//   tsk_remove_bios ();
#endif
#if (IBM)

   if (v24_remove_func != NULL)
      v24_remove_func ();
   if (prt_remove_func != NULL)
      prt_remove_func ();

   /* Allow all stored clock ticks to be processed */
   int9_tcb.set_priority (0xffff);
   while (tsk_int9_counter.check_counter ())
      schedule();

     tsk_remove_timer ();
     tsk_remove_kbd ();
#endif

#if (DOS)
     tsk_remove_dos ();
#endif
}


/*
   preempt_off
      Turns off task preemption (will stay off until explicitly enabled).
*/

void far tasker_class::preempt_off (void)
{
   tsk_preempt = 1;
}


/*
   preempt_on
      Resets permanent and temporary task preemption flag. If 
      preemption is pending, the scheduler is called.
*/

void far tasker_class::preempt_on (void)
{
   tsk_preempt = 0;
   tsk_cli ();
   if (tsk_pretick)
      schedule ();
   tsk_sti ();
}


/*
   tsk_ena_preempt
      Resets temporary task preemption flag. If preemption is pending,
      the scheduler is called.
*/

void far tasker_class::tsk_ena_preempt (void)
{
   tsk_cli ();
   if (!(tsk_preempt &= ~2))
      if (tsk_pretick)
         schedule ();
   tsk_sti ();
}


/*
   tsk_dis_preempt
      Sets temporary task preemption flag.
*/

void far tasker_class::tsk_dis_preempt (void)
{
   tsk_preempt |= 2;
}


void far tasker_class::schedule(void)
{
   asm_schedule();
}



void far tasker_class::c_schedule(void)
{
   asm_c_schedule();
}


void far asm_remove_tasker(void)
{
    tasker.tasker_class::~tasker_class();
}


⌨️ 快捷键说明

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