home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / CTASK22.ZIP / TSKINST.C < prev    next >
C/C++ Source or Header  |  1990-10-12  |  11KB  |  392 lines

  1. /*
  2.    --- Version 2.2 90-10-12 15:49 ---
  3.  
  4.    TSKINST.C - CTask - Install/Remove main tasker.
  5.  
  6.    CTask - a Multitasking Kernel for C
  7.  
  8.    Public Domain Software written by
  9.       Thomas Wagner
  10.       Ferrari electronic Gmbh
  11.       Beusselstrasse 27
  12.       D-1000 Berlin 21
  13.       Germany
  14.  
  15.    No rights reserved.
  16.  
  17.    Version 2.1 separates the functions previously collected in tskmain.c into
  18.          tskmain.c - Front ends for installation/removal
  19.          tskinst.c - Install/Remove main kernel
  20.          tskgrp.c  - Create/remove groups
  21.          tsktask.c - Task creation and deletion
  22.          tsktutl.c - Task utilities (get/set priority etc.)
  23.          tskutil.c - General utilities (preemption, t_delay)
  24.  
  25.    Added in version 2.1: Debug support and NDP checking.
  26. */
  27.  
  28. #include "tsk.h"
  29. #include "tsklocal.h"
  30.  
  31. #define STACKSIZE 512
  32.  
  33. /*
  34.    The tcb's of the standard tasks.
  35.  
  36.       timer_tcb   is the tcb for the timer task.
  37.                   This task waits for the tsk_timer_counter, which is
  38.                   increased on every timer tick. It processes the entries
  39.                   in the timeout queue.
  40.  
  41.       int8_tcb    is the tcb for the int8 chain task.
  42.                   This task waits for the tsk_int8_counter, which is
  43.                   increased on every system timer tick. It then chains to
  44.                   the previous timer interrupt entry. If the IFL_INT8_EARLY
  45.                   installation flag is set, this task will only be awakened
  46.                   if the timer interrupt occurs during scheduler execution.
  47.                   If the INT8_EARLY configuration flag is TRUE, this tcb
  48.                   is not created.
  49.  
  50.       main_tcb    is the "main" task which called "install_tasker". This
  51.                   task has no separate stack, rather the stack on entry
  52.                   to the scheduler is used. Since main_tcb is not used
  53.                   if this is a secondary invocation of CTask, "main_ptr"
  54.                   points to the main_tcb for a primary invocation, and
  55.                   to the underlying task for a secondary invocation.
  56.  
  57.       kill_tcb    is the tcb for the "kill" task. This task is only
  58.                   used when dynamic allocation is enabled. Its only
  59.                   purpose is to dispose of a dynamically allocated TCB,
  60.                   and/or a dynamically allocated task stack. This task
  61.                   was added in version 2.1 to fix a problem with killing
  62.                   the current task when there were dynamically allocated
  63.                   elements in it.
  64. */
  65.  
  66. /* 
  67.    The following variables are never directly accessed from shared code,
  68.    so they can be defined locally.
  69. */
  70.  
  71. local tcb timer_tcb;
  72. local tcb main_tcb;
  73.  
  74. #if (TSK_DYNAMIC)
  75. local tcb kill_tcb;
  76. local char kill_stack [STACKSIZE];
  77. #endif
  78.  
  79. local char timer_stack [STACKSIZE];
  80.  
  81. #if (IBM && !INT8_EARLY)
  82. local tcb int8_tcb;
  83. local char int8_stack [STACKSIZE];
  84. #endif
  85.  
  86. #if (CODE_SHARING)
  87. extern byte tsk_jmptab [];
  88. #endif
  89.  
  90. /* 
  91.    The following variables are local to the primary invocation.
  92.    They are referenced from the timer task.
  93. */
  94.  
  95. counter Neardata tsk_timer_counter;
  96.  
  97. #if (IBM && !INT8_EARLY)
  98. counter Neardata tsk_int8_counter;
  99. #endif
  100.  
  101. /* --------------------------------------------------------------------- */
  102.  
  103. #if (TSK_DYNAMIC)
  104.  
  105. /*
  106.    tsk_kill is awakened directly by the internal task kill routines
  107.    if the current task is to be killed, and it has dynamically 
  108.    allocated elements in it. Since the freeing of the dynamic elements
  109.    may cause the task to be made waiting, this can't be done immediately 
  110.    in certain situations. So the task is only marked as killed, and its
  111.    queue head pointer is set to the kill_queue entry in the global variable
  112.    block. The tsk_kill task is then marked as runable. The scheduler will
  113.    enter the TCB into the kill_queue, and eventually activate tsk_kill.
  114. */
  115.  
  116. local void Taskfunc tsk_kill (void)
  117. {
  118.    tcbptr task;
  119.    CRITICAL;
  120.  
  121.    while (1)
  122.       {
  123.       C_ENTER;
  124.       task = (tcbptr)tsk_glob_rec.kill_queue.first;
  125.       while (!(task->cqueue.kind & Q_HEAD))
  126.          {
  127.          tsk_dequeue (&task->cqueue);
  128.          C_LEAVE;
  129.          if (task->flags & F_STTEMP)
  130.             tsk_pfree (task->stkbot);   /* Bug fixed in 2.1, was 'task->stack' */
  131.          if (task->flags & F_TEMP)
  132.             tsk_pfree (task);
  133.          C_ENTER;
  134.          task = (tcbptr)tsk_glob_rec.kill_queue.first;
  135.          }
  136.       kill_tcb.state = ST_STOPPED;
  137.       kill_tcb.qhead = LNULL;
  138.       schedule ();
  139.       C_LEAVE;
  140.       }
  141. }
  142.  
  143. #endif
  144.  
  145. /* --------------------------------------------------------------------- */
  146.  
  147. /*
  148.    tsk_install_main
  149.       Installs the Ctask system. The internal tasks are created,
  150.       the queues are initialised, and the interrupt handler installation
  151.       routines are called. Task preemption is initially off.
  152.  
  153.       Handling of the speedup parameter is system dependent.
  154. */
  155.  
  156. int Localfunc tsk_install_main (byte varpri, int speedup, word flags
  157.                                 TN(byteptr name))
  158. {
  159.    word divisor, sys_ticks;
  160.  
  161.  
  162.    tsk_instflags = flags;
  163.  
  164.    tsk_glob_rec.current_task = &main_tcb;
  165. #if (GROUPS)
  166.    tsk_glob_rec.group.main_ptr = &main_tcb;
  167. #else
  168.    tsk_glob_rec.main_ptr = &main_tcb;
  169. #endif
  170.  
  171. #if (!SINGLE_DATA)
  172.    tsk_global = &tsk_glob_rec;
  173. #endif
  174. #if (GROUPS)
  175.    main_tcb.group = &tsk_glob_rec.group;
  176. #endif
  177.  
  178. #if (CODE_SHARING)
  179.    tsk_glob_rec.stub_table = tsk_jmptab;
  180. #else
  181.    tsk_glob_rec.stub_table = LNULL;
  182. #endif
  183.  
  184.    tsk_init_qhead (&tsk_glob_rec.eligible_queue, 0);
  185.    tsk_init_qhead (&tsk_glob_rec.timer_queue, 0);
  186.    tsk_init_qhead (&tsk_glob_rec.watch_queue, 0);
  187.  
  188.    tsk_glob_rec.preempt = 1;
  189.    tsk_glob_rec.pretick = 0;
  190.    tsk_glob_rec.var_prior = varpri;
  191.    tsk_glob_rec.in_sched = 0;
  192.    tsk_glob_rec.ticker_chain = LNULL;
  193. #if (NDP)
  194.    tsk_glob_rec.ndp_present = 0;  /* Init to 0 for creation of system tasks */
  195. #endif
  196.  
  197. #if (GROUPS)
  198.    tsk_glob_rec.group.branch = LNULL;
  199.    tsk_create_group (&tsk_glob_rec.group, name);
  200.    tsk_glob_rec.group.branch = LNULL;
  201.    tsk_glob_rec.group.home = LNULL;
  202.  
  203. #if (DOS)
  204.    tsk_glob_rec.group.save_psp = 0;
  205.    tsk_glob_rec.emergency_exit = tsk_emergency_exit;
  206.  
  207.    tsk_install_dos ();
  208. #endif
  209. #else
  210.    tsk_glob_rec.remove = LNULL;
  211. #if (TSK_NAMED)
  212.    tsk_init_qhead (&tsk_glob_rec.name_list.list, 0);
  213.    tsk_glob_rec.name_list.name [0] = 0;
  214. #endif
  215. #endif
  216. #if (EMS)
  217.    tsk_install_ems ();
  218. #endif
  219.  
  220.    /* 
  221.       Call create_task to initialise the main task's TCB.
  222.       Note that the function pointer and stack parameters are
  223.       insignificant, but must be valid pointers (the stack is
  224.       initialised, but not used).
  225.    */
  226.  
  227.    create_task (&main_tcb, tsk_timer, timer_stack, STACKSIZE, 
  228.                 PRI_TIMER - 1, LNULL TN("-MAIN-"));
  229.  
  230.    main_tcb.qhead = &tsk_glob_rec.eligible_queue;
  231.    main_tcb.state = ST_RUNNING;
  232.    main_tcb.flags |= F_PERM;
  233.  
  234. #if (TSK_DYNAMIC && TSK_DYNLOAD)
  235.    create_resource (&alloc_resource TN("ALLOCRSC"));
  236. #endif
  237.  
  238. #if (TSK_DYNAMIC)
  239.    tsk_init_qhead (&tsk_glob_rec.kill_queue, 0);
  240.    create_task (&kill_tcb, tsk_kill, kill_stack, STACKSIZE, 
  241.                 PRI_STD, LNULL TN("-KILLER-"));
  242.    kill_tcb.flags |= F_PERM;
  243.    tsk_glob_rec.kill_task = &kill_tcb;
  244. #endif
  245.  
  246.    create_task (&timer_tcb, tsk_timer, timer_stack, STACKSIZE, 
  247.                 PRI_TIMER, LNULL TN("-TIMER-"));
  248.    timer_tcb.flags |= F_PERM;
  249.  
  250.    create_counter (&tsk_timer_counter TN("TIMCOUNT"));
  251.  
  252.    start_task (&timer_tcb);
  253.  
  254. #if (IBM && !INT8_EARLY)
  255.  
  256.    /* Note: to allow delayed timer ticks even with the INT8_DIR
  257.       installation flag active, we must create the int8 task and
  258.       counter without checking for the flag. Delayed ticks are 
  259.       possible under the new interrupt handler scheme in version 2.1.
  260.    */
  261.  
  262.    create_task (&int8_tcb, tsk_int8, int8_stack, STACKSIZE, PRI_INT8, LNULL
  263.                   TN("-INT8-"));
  264.    int8_tcb.flags |= F_PERM;
  265.  
  266.    create_counter (&tsk_int8_counter TN("INT8CNT"));
  267.    start_task (&int8_tcb);
  268.  
  269. #endif
  270.  
  271.    /* NOTE: divisor/sys_ticks calculations are machine dependent. */
  272.  
  273.    if (speedup <= 0 || speedup > 8)
  274.       {
  275.       divisor = 0;
  276.       sys_ticks = 1;
  277.       tsk_glob_rec.ticks_per_sec = 0x0012;
  278.       tsk_glob_rec.tick_factor = 0x36ED;
  279.       }
  280.    else
  281.       {
  282.       divisor = 1 << (16 - speedup);
  283.       sys_ticks = 1 << speedup;
  284.       tsk_glob_rec.ticks_per_sec =
  285.          (0x1235 + (0x0080 >> speedup)) >> (8 - speedup);
  286.       tsk_glob_rec.tick_factor =
  287.          (0x36ED + (0x0080 >> (8 - speedup))) >> speedup;
  288.       }
  289.  
  290.    tsk_install_timer (divisor, sys_ticks);
  291.  
  292. #if (HOTKEYS)
  293.    tsk_init_qhead (&tsk_glob_rec.hotkey_scan, 0);
  294.    tsk_init_qhead (&tsk_glob_rec.hotkey_noscan, 0);
  295. #endif
  296.  
  297. #if (IBM)
  298.    tsk_install_kbd ();
  299.  
  300.    if (flags & IFL_PRINTER)
  301.       tsk_install_int17 ();
  302. #endif
  303.  
  304. #if (AT_BIOS)
  305.    if (flags & IFL_INT15)
  306.       tsk_install_bios ();
  307. #endif
  308.  
  309. #if (NDP)
  310.    tsk_glob_rec.ndp_present = tsk_use_ndp = tsk_check_ndp ();
  311. #endif
  312.  
  313.    return 0;
  314. }
  315.  
  316.  
  317. /* --------------------------------------------------------------------- */
  318.  
  319. /*
  320.    tsk_remove_chain
  321.       Calls the chained remove routines.
  322. */
  323.  
  324. void Localfunc tsk_remove_chain (callchainptr chain)
  325. {
  326.    callchainptr curr;
  327.    funcptr_ccp fn;
  328.  
  329.    while (chain != LNULL)
  330.       {
  331.       curr = chain;
  332.       chain = chain->next;
  333.       if ((fn = curr->func) != LNULL)
  334.          {
  335.          curr->func = LNULL;
  336.          tsk_callfunc ((farptr)fn, curr);
  337.          }
  338. #if (TSK_DYNAMIC)
  339.       if (curr->flags & F_TEMP)
  340.          tsk_pfree (curr);
  341. #endif
  342.       }
  343. }
  344.  
  345.  
  346. /*
  347.    tsk_remove_tasker
  348.       Calls the interrupt handler un-install routines.
  349. */
  350.  
  351. void Localfunc tsk_remove_tasker (void)
  352. {
  353. #if (!GROUPS)
  354.    tsk_remove_chain (tsk_glob_rec.remove);
  355. #endif
  356.  
  357.    tsk_glob_rec.preempt = 0;
  358.  
  359. #if (AT_BIOS)
  360.    if (tsk_instflags & IFL_INT15)
  361.       tsk_remove_bios ();
  362. #endif
  363.  
  364. #if (IBM && !INT8_EARLY)
  365.  
  366.    /* Allow all stored clock ticks to be processed */
  367.  
  368.    if (!(tsk_instflags & IFL_INT8_DIR))
  369.       {
  370.       set_priority (&int8_tcb, 0xffff);
  371.       while (check_counter (&tsk_int8_counter))
  372.          schedule();
  373.       }
  374. #endif
  375.  
  376. #if (IBM)
  377.    if (tsk_instflags & IFL_PRINTER)
  378.       tsk_remove_int17 ();
  379.  
  380.    tsk_remove_kbd ();
  381. #endif
  382.  
  383.    tsk_remove_timer ();
  384.  
  385. #if (DOS)
  386.    tsk_remove_dos ();
  387. #endif
  388.  
  389.    ctask_active = 0;
  390. }
  391.  
  392.