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

📄 rtmk.c

📁 实时多重作业操作系统内核(RTMK)。简单实时多重作业操作系统内核源程序。RTMK支持消息和事件
💻 C
字号:
/************************************************************************
*
*  Module name         : RTMK.C
*
*  Module description  :
*     This module contains task management functions for RTMK.
*
*     About jmp_buf:
*      + Borland C++ compiler defines jmp_buf as a pointer to a data structure:
*           struct __jmp_buf
*           {
*              unsigned    j_sp;
*              unsigned    j_ss;
*              unsigned    j_flag;
*              unsigned    j_cs;
*              unsigned    j_ip;
*              unsigned    j_bp;
*              unsigned    j_di;
*              unsigned    j_es;
*              unsigned    j_si;
*              unsigned    j_ds;
*           };
*           to store information of registers.
*
*      + WatCom C++ compiler defines jmp_buf as a 13 integer array to store
*        information of registers:
*              [0]  = BX
*              [1]  = CX
*              [2]  = DX
*              [3]  = SI
*              [4]  = DI
*              [5]  = BP
*              [6]  = SP
*              [7]  = ES
*              [8]  = DS
*              [9]  = CS
*              [10] = IP
*              [11] = Don't know yet (flags ?)
*              [12] = SS
*
*  Project             : RTMK
*
*  Target platform     : DOS
*
*  Compiler & Library  : BC++ 3.1
*
*  Author              : Richard Shen
*
*  Creation date       : 16 August, 1995
*
************************************************************************/
#include <memory.h>

#ifdef __DOS__
#  include <stdlib.h>
#  include <dos.h>
#  include <signal.h>
#  include <conio.h>
#endif /* __DOS__ */

#include <rtmk.h>
#include <errors.h>
#include "rtmkloc.h"

/************************************************************************
*                 S T A T I C    V A R I A B L E S                      *
************************************************************************/
/*
   NOTE: numProcess declared as FAR, when it is referenced by Borland C++
         compiler, ES register will be used.
*/
#ifdef __DOS__
static int far    numProcess; /* Number of Processes created */
#else
static int        numProcess; /* Number of Processes created */
#endif /* __DOS__ */

/************************************************************************
*  Function name   : RtmkRun
*  Description     : Main entry point of RTMK kernel
*                  :
*  Parameters      : -
*  Returns         : SUCCESSFUL
*  Author          : Richard Shen
* -----------------------------------------------------------------------
*  Date     By      Description
* -----------------------------------------------------------------------
*  16Aug95  RCS     Created.
************************************************************************/
uint RtmkRun(void)
{
   /* Initialise kernel data */
   memset(&pcsTable[0], 0, sizeof(pcsTable));

   numProcess   = 0;
   curProcess   = NULL;
   readyProcess = 0;

#ifdef __DOS__
   servingInt   = FALSE;
#endif /* __DOS__ */

   /* Create the default task */
   RtmkStartTask(&curProcess, NULL, 0);

   Scheduler(NULL, FALSE);

   return(SUCCESSFUL);
} /* RtmkRun() */

/************************************************************************
*  Function name   : RtmkStartTask
*  Description     : Create an application task
*                  :
*  Parameters      : process     - Task control block
*                  : taskEntry   - Task entry point. NULL if running code
*                  : stackSize   - Size of task's stack
*  Returns         : -
*  Author          : Richard Shen
* -----------------------------------------------------------------------
*  Date     By      Description
* -----------------------------------------------------------------------
*  16Aug95  RCS     Created.
************************************************************************/
uint RtmkStartTask(PROCESS *process, void (*taskEntry)(void), uint stackSize)
{
   uint     procMask;

#ifdef __DOS__
   char far    *stack;
#endif /* __DOS__ */

   /* Last task is the kernel task */
   if (numProcess > MAX_TASKS - 1)
   {
      *process = NULL;
      return(ERR_MAX_TASKS);
   } /* end of if */

   *process = &pcsTable[numProcess];

   if (taskEntry)
   {
#ifdef __DOS__
      /* Register application task to kernel */
#if defined __TURBOC__
      (*process)->context->j_ip   = FP_OFF(taskEntry);
      (*process)->context->j_cs   = FP_SEG(taskEntry);
      (*process)->context->j_flag = 0;

      /* Process stack */
      stack = (char far *)calloc(stackSize, sizeof(char));
      if (stack == NULL)
      {
         *process = NULL;
         return(ERR_STACK);
      } /* end of if */

      /*
         Set up segment registers.  By default, the compiler assumes that
         SS is equal to DS for small, tiny or medium module.  For large,
         huge or compact module, DS is not equal to SS.
      */
      (*process)->context->j_ss = FP_SEG((void far *)stack);
      (*process)->context->j_sp = (uint )stack + stackSize;
      (*process)->context->j_bp = (*process)->context->j_sp;   /* Assume BP = SP */

      /* Set up DS register */
#if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__)
      (*process)->context->j_ds = _DS;
#else
      (*process)->context->j_ds = (*process)->context->j_ss;
#endif /* __LARGE || __HUGE__ || __COMPACT__ */

      /* Set up ES register */
      (*process)->context->j_es = _ES;

      /* Set up flags register */
      (*process)->context->j_flag = _FLAGS;

#elif defined __WATCOMC__

      /* Process stack */
      stack = (char far *)calloc(stackSize, sizeof(char));
      if (stack == NULL)
      {
         *process = NULL;
         return(ERR_STACK);
      } /* end of if */

      (*process)->context[6]  = (uint )stack + stackSize;   /* SP      */
      (*process)->context[5]  = (*process)->context[6];     /* BP = SP */
      (*process)->context[7]  = sysContext[7];              /* ES      */
      (*process)->context[8]  = sysContext[8];              /* DS      */
      (*process)->context[9]  = FP_SEG(taskEntry);          /* CS      */
      (*process)->context[10] = FP_OFF(taskEntry);          /* IP      */
      (*process)->context[12] = FP_SEG((void far *)stack);  /* SS      */
#endif /* __TURBOC__ else __WATCOMC__ */

#else
   /* Allocate stack for application task using target specific compiler */

   /* Then set up process context */

#endif /* __DOS__ */
   } /* end of if */

   (*process)->evWait     = 0;                     /* No waiting events    */
   (*process)->evReceived = 0;                     /* No received events   */
   procMask            = READY_MASK >> numProcess; /* Set up task status   */
   (*process)->procMask   = procMask;
   (*process)->priority   = MAX_TASKS - numProcess;/* Set up priority      */
   (*process)->msgPending = FALSE;                 /* No message pending   */
   (*process)->msgSender  = NULL;

   numProcess++;                                   /* Update process counter */
   DisableInterrupt();
   readyProcess |= procMask;    /* The process is now ready to take the CPU */
   EnableInterrupt();

   return(SUCCESSFUL);
} /* RtmkStartTask() */

/************************************************************************
*  Function name   : Scheduler
*  Description     : The context of the current process is saved and the
*                  : system switch to the ready process.  If nextProcess
*                  : is NULL, the higher priority ready process is searched,
*                  : else the process is the ready process.
*                  :
*  Parameters      : nextProcess - Process to be scheduled to
*                  : ronudRobin  - TRUE if manual round robin
*  Returns         : -
*  Author          : Richard Shen
* -----------------------------------------------------------------------
*  Date     By      Description
* -----------------------------------------------------------------------
*  16Aug95  RCS     Created.
************************************************************************/
void Scheduler(PROCESS nextProcess, BOOLEAN roundRobin)
{
   PROCESS  highest;
   int      count;
   uint     mask;
   uint     maxPrior;

   /* Save the context of current process */
   if (!setjmp(curProcess->context))
   {
      if (nextProcess && roundRobin == FALSE)
         curProcess = nextProcess;
      else
      {
         highest  = NULL;
         while (highest == NULL)
         {
            mask     = READY_MASK;
            maxPrior = 0;

            for (count = 0; count < MAX_TASKS; count++)
            {
               if ((mask & readyProcess) != 0)
               {
                  /* Keep searching for highest priority process */
                  if (maxPrior < pcsTable[count].priority)
                  {
                     highest  = &pcsTable[count];
                     maxPrior = highest->priority;
                  } /* end of if */
               } /* end of if */
               mask >>= 1;
            } /* end of for */

            /*
               If highest is NULL, no ready task found, just wait.
               Some tasks might just wait for a hardware interrupt event.
            */
            if (highest)
            {
               if (highest == curProcess)
               {
                  if ((readyProcess & highest->procMask))
                     return;
                  highest = NULL;   /* Current task is in wait mode */
                  continue;
               } /* end of if */
               curProcess = highest;
            } /* end of if */
         } /* end of while */
      } /* end of else */

      longjmp(curProcess->context, 1); /* Switch to the scheduled process */
   } /* end of if */
} /* Scheduler() */

/************************************************************************
*  Function name   : RtmkChangePriority
*  Description     : Change priority of a task
*                  :
*  Parameters      : process     - Task control block
*                  : newPriority - New priority
*  Returns         : priority changed to, or ERR_TASK_ID if invalid task ID
*  Author          : Richard Shen
* -----------------------------------------------------------------------
*  Date     By      Description
* -----------------------------------------------------------------------
*  16Aug95  RCS     Created.
************************************************************************/
uchar RtmkChangePriority(PROCESS process, uchar newPriority)
{
   uchar    oldPriority;

   oldPriority       = process->priority;
   process->priority = newPriority;

   return(oldPriority);
} /* RtmkChangePriority() */

/************************************************************************
*  Function name   : RtmkGetPriority
*  Description     : Get priority of a task
*                  :
*  Parameters      : tid   - Task control block
*  Returns         : priority changed to, or ERR_TASK_ID if invalid task ID
*  Author          : Richard Shen
* -----------------------------------------------------------------------
*  Date     By      Description
* -----------------------------------------------------------------------
*  16Aug95  RCS     Created.
************************************************************************/
uchar RtmkGetPriority(PROCESS process)
{
   return(process->priority);
} /* RtmkGetPriority() */

/************************************************************************
*  Function name   : RtmkCurrent
*  Description     : Get current running process control block
*                  :
*  Parameters      : -
*  Returns         : curProcess
*  Author          : Richard Shen
* -----------------------------------------------------------------------
*  Date     By      Description
* -----------------------------------------------------------------------
*  22Aug95  RCS     Created.
************************************************************************/
PROCESS RtmkCurrent(void)
{
   return(curProcess);
} /* RtmkCurrent() */

/************************************************************************
*  Function name   : EnableInterrupt
*  Description     : Enables interrupts
*                  :
*  Parameters      : -
*  Returns         : -
*  Author          : Richard Shen
* ----------------------------------------------------------------------
*  Date     By      Description
* ----------------------------------------------------------------------
*  09Oct95  RCS     Created.
************************************************************************/
void EnableInterrupt(void)
{
   if (servingInt == 0)
      enable();
} /* EnableInterrupt() */

/************************************************************************
*  Function name   : DisableInterrupt
*  Description     : Disables interrupts
*                  :
*  Parameters      : -
*  Returns         : -
*  Author          : Richard Shen
* ----------------------------------------------------------------------
*  Date     By      Description
* ----------------------------------------------------------------------
*  09Oct95  RCS     Created.
************************************************************************/
void DisableInterrupt(void)
{
   if (servingInt == 0)
      disable();
} /* DisableInterrupt() */

⌨️ 快捷键说明

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