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

📄 tskinst.c

📁 一个多任务操作系统CTask的源代码 用C语言编写
💻 C
字号:
/*
   --- Version 2.2 90-11-22 12:03 ---

   TSKINST.C - CTask - Install/Remove main tasker.

   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.

   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)

   Added in version 2.1: Debug support and NDP checking.
*/

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

#define STACKSIZE 512

/*
   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.

      int8_tcb    is the tcb for the int8 chain task.
                  This task waits for the tsk_int8_counter, which is
                  increased on every system timer tick. It then chains to
                  the previous timer interrupt entry. If the IFL_INT8_EARLY
                  installation flag is set, this task will only be awakened
                  if the timer interrupt occurs during scheduler execution.
                  If the INT8_EARLY configuration flag is TRUE, this tcb
                  is not created.

      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. Since main_tcb is not used
                  if this is a secondary invocation of CTask, "main_ptr"
                  points to the main_tcb for a primary invocation, and
                  to the underlying task for a secondary invocation.

      kill_tcb    is the tcb for the "kill" task. This task is only
                  used when dynamic allocation is enabled. Its only
                  purpose is to dispose of a dynamically allocated TCB,
                  and/or a dynamically allocated task stack. This task
                  was added in version 2.1 to fix a problem with killing
                  the current task when there were dynamically allocated
                  elements in it.
*/

/* 
   The following variables are never directly accessed from shared code,
   so they can be defined locally.
*/

local tcb timer_tcb;
local tcb main_tcb;

#if (TSK_DYNAMIC)
local tcb kill_tcb;
local char kill_stack [STACKSIZE];
#endif

local char timer_stack [STACKSIZE];

#if (IBM && !INT8_EARLY)
local tcb int8_tcb;
local char int8_stack [STACKSIZE];
#endif

#if (CODE_SHARING)
extern byte tsk_jmptab [];
#endif

/* 
   The following variables are local to the primary invocation.
   They are referenced from the timer task.
*/

counter Neardata tsk_timer_counter;

#if (IBM && !INT8_EARLY)
counter Neardata tsk_int8_counter;
#endif

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

#if (TSK_DYNAMIC)

/*
   tsk_kill is awakened directly by the internal task kill routines
   if the current task is to be killed, and it has dynamically 
   allocated elements in it. Since the freeing of the dynamic elements
   may cause the task to be made waiting, this can't be done immediately 
   in certain situations. So the task is only marked as killed, and its
   queue head pointer is set to the kill_queue entry in the global variable
   block. The tsk_kill task is then marked as runable. The scheduler will
   enter the TCB into the kill_queue, and eventually activate tsk_kill.
*/

local void Taskfunc tsk_kill (void)
{
   tcbptr task;
   CRITICAL;

   while (1)
      {
      C_ENTER;
      task = (tcbptr)tsk_glob_rec.kill_queue.first;
      while (!(task->cqueue.kind & Q_HEAD))
         {
         tsk_dequeue (&task->cqueue);
         C_LEAVE;
         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);
         C_ENTER;
         task = (tcbptr)tsk_glob_rec.kill_queue.first;
         }
      kill_tcb.state = ST_STOPPED;
      kill_tcb.qhead = LNULL;
      schedule ();
      C_LEAVE;
      }
}

#endif

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

/*
   tsk_install_main
      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.
*/

int Globalfunc tsk_install_main (byte varpri, int speedup, word flags
                                TN(byteptr name))
{
   word divisor, sys_ticks;


   tsk_instflags = flags;

   tsk_glob_rec.current_task = &main_tcb;
#if (GROUPS)
   tsk_glob_rec.group.main_ptr = &main_tcb;
#else
   tsk_glob_rec.main_ptr = &main_tcb;
#endif

#if (!SINGLE_DATA)
   tsk_global = &tsk_glob_rec;
#endif
#if (GROUPS)
   main_tcb.group = &tsk_glob_rec.group;
#endif

#if (CODE_SHARING)
   tsk_glob_rec.stub_table = tsk_jmptab;
#else
   tsk_glob_rec.stub_table = LNULL;
#endif

   tsk_init_qhead (&tsk_glob_rec.eligible_queue, 0);
   tsk_init_qhead (&tsk_glob_rec.timer_queue, 0);
   tsk_init_qhead (&tsk_glob_rec.watch_queue, 0);

   tsk_glob_rec.preempt = 1;
   tsk_glob_rec.pretick = 0;
   tsk_glob_rec.var_prior = varpri;
   tsk_glob_rec.in_sched = 0;
   tsk_glob_rec.ticker_chain = LNULL;
#if (NDP)
   tsk_glob_rec.ndp_present = 0;  /* Init to 0 for creation of system tasks */
#endif

#if (GROUPS)
   tsk_glob_rec.group.branch = LNULL;
   tsk_create_group (&tsk_glob_rec.group, name);
   tsk_glob_rec.group.branch = LNULL;
   tsk_glob_rec.group.home = LNULL;

#if (DOS)
   tsk_glob_rec.group.save_psp = 0;
   tsk_glob_rec.emergency_exit = tsk_emergency_exit;

   tsk_install_dos ();
#endif
#else
   tsk_glob_rec.remove = LNULL;
#if (TSK_NAMED)
   tsk_init_qhead (&tsk_glob_rec.name_list.list, 0);
   tsk_glob_rec.name_list.name [0] = 0;
#endif
#endif
#if (EMS)
   tsk_install_ems ();
#endif

   /* 
      Call create_task to initialise the main task's TCB.
      Note that the function pointer and stack parameters are
      insignificant, but must be valid pointers (the stack is
      initialised, but not used).
   */

   create_task (&main_tcb, tsk_timer, timer_stack, STACKSIZE, 
                PRI_TIMER - 1, LNULL TN("-MAIN-"));

   main_tcb.qhead = &tsk_glob_rec.eligible_queue;
   main_tcb.state = ST_RUNNING;
   main_tcb.flags |= F_PERM;

#if (TSK_DYNAMIC && TSK_DYNLOAD)
   create_resource (&alloc_resource TN("ALLOCRSC"));
#endif

#if (TSK_DYNAMIC)
   tsk_init_qhead (&tsk_glob_rec.kill_queue, 0);
   create_task (&kill_tcb, tsk_kill, kill_stack, STACKSIZE, 
                PRI_STD, LNULL TN("-KILLER-"));
   kill_tcb.flags |= F_PERM;
   tsk_glob_rec.kill_task = &kill_tcb;
#endif

   create_task (&timer_tcb, tsk_timer, timer_stack, STACKSIZE, 
                PRI_TIMER, LNULL TN("-TIMER-"));
   timer_tcb.flags |= F_PERM;

   create_counter (&tsk_timer_counter TN("TIMCOUNT"));

   start_task (&timer_tcb);

#if (IBM && !INT8_EARLY)

   /* Note: to allow delayed timer ticks even with the INT8_DIR
      installation flag active, we must create the int8 task and
      counter without checking for the flag. Delayed ticks are 
      possible under the new interrupt handler scheme in version 2.1.
   */

   create_task (&int8_tcb, tsk_int8, int8_stack, STACKSIZE, PRI_INT8, LNULL
                  TN("-INT8-"));
   int8_tcb.flags |= F_PERM;

   create_counter (&tsk_int8_counter TN("INT8CNT"));
   start_task (&int8_tcb);

#endif

   /* NOTE: divisor/sys_ticks calculations are machine dependent. */

   if (speedup <= 0 || speedup > 8)
      {
      divisor = 0;
      sys_ticks = 1;
      tsk_glob_rec.ticks_per_sec = 0x0012;
      tsk_glob_rec.tick_factor = 0x36ED;
      }
   else
      {
      divisor = 1 << (16 - speedup);
      sys_ticks = 1 << speedup;
      tsk_glob_rec.ticks_per_sec =
         (0x1235 + (0x0080 >> speedup)) >> (8 - speedup);
      tsk_glob_rec.tick_factor =
         (0x36ED + (0x0080 >> (8 - speedup))) >> speedup;
      }

   tsk_install_timer (divisor, sys_ticks);

#if (HOTKEYS)
   tsk_init_qhead (&tsk_glob_rec.hotkey_scan, 0);
   tsk_init_qhead (&tsk_glob_rec.hotkey_noscan, 0);
#endif

#if (IBM)
   tsk_install_kbd ();

   if (flags & IFL_PRINTER)
      tsk_install_int17 ();
#endif

#if (AT_BIOS)
   if (flags & IFL_INT15)
      tsk_install_bios ();
#endif

#if (NDP)
   tsk_glob_rec.ndp_present = tsk_use_ndp = tsk_check_ndp ();
#endif

   return 0;
}


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

/*
   tsk_remove_chain
      Calls the chained remove routines.
*/

void Globalfunc tsk_remove_chain (callchainptr chain)
{
   callchainptr curr;
   funcptr_ccp fn;

   while (chain != LNULL)
      {
      curr = chain;
      chain = chain->next;
      if ((fn = curr->func) != LNULL)
         {
         curr->func = LNULL;
         tsk_callfunc ((farptr)fn, curr);
         }
#if (TSK_DYNAMIC)
      if (curr->flags & F_TEMP)
         tsk_pfree (curr);
#endif
      }
}


/*
   tsk_remove_tasker
      Calls the interrupt handler un-install routines.
*/

void Globalfunc tsk_remove_tasker (void)
{
#if (!GROUPS)
   tsk_remove_chain (tsk_glob_rec.remove);
#endif

   tsk_glob_rec.preempt = 0;

#if (AT_BIOS)
   if (tsk_instflags & IFL_INT15)
      tsk_remove_bios ();
#endif

#if (IBM && !INT8_EARLY)

   /* Allow all stored clock ticks to be processed */

   if (!(tsk_instflags & IFL_INT8_DIR))
      {
      set_priority (&int8_tcb, 0xffff);
      while (check_counter (&tsk_int8_counter))
         schedule();
      }
#endif

#if (IBM)
   if (tsk_instflags & IFL_PRINTER)
      tsk_remove_int17 ();

   tsk_remove_kbd ();
#endif

   tsk_remove_timer ();

#if (DOS)
   tsk_remove_dos ();
#endif

   ctask_active = 0;
}

⌨️ 快捷键说明

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