home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / c / ct22d / tsktask.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-04  |  6.9 KB  |  302 lines

  1. /*
  2.    --- Version 2.2 93-03-04 15:27 ---
  3.  
  4.    TSKTASK.C - CTask - Task creation and deletion.
  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.    This file is new with version 2.1.
  18.    Version 2.1 separates the functions previously collected in tskmain.c into
  19.          tskmain.c - Front ends for installation/removal
  20.          tskinst.c - Install/Remove main kernel
  21.          tskgrp.c  - Create/remove groups
  22.          tsktask.c - Task creation and deletion
  23.          tsktutl.c - Task utilities (get/set priority etc.)
  24.          tskutil.c - General utilities (preemption, t_delay)
  25. */
  26.  
  27. #include "tsk.h"
  28. #include "tsklocal.h"
  29.  
  30. #if (DOS)
  31. extern void Localfunc tsk_get_dosswap (tcbptr task);
  32. #endif
  33.  
  34. /*
  35.    tsk_use_ndp is initialized by install_tasker, and may be changed
  36.    to 0 by the user to enable or disable ndp handling for tasks
  37.    being created.
  38.  
  39.    Note that setting tsk_use_ndp to 1 will have no effect if 
  40.    install_tasker has determined that there is no NDP present, or
  41.    if the NDP configuration flag is FALSE.
  42. */
  43.  
  44. int tsk_use_ndp = 0;
  45.  
  46.  
  47. #pragma check_stack(off)
  48.  
  49. /*
  50.    tsk_kill
  51.       mark task as killed.
  52.  
  53.       CAUTION: Critical section assumed entered.
  54. */
  55.  
  56. local void Staticfunc tsk_kill (tcbptr task, int currtask)
  57. {
  58.    /*
  59.       Note: The following test shouldn't be necessary. However,
  60.       if ever an interrupt handler should cause the current task to
  61.       be killed while the scheduler is active, this would cause
  62.       catastrophic effects (also see the notes in tskasm.asm).
  63.       Well, no interrupt handler should ever do such a nasty thing, but...
  64.       So if the in_sched flag is set, and the task is the current
  65.       task, we have to stop everything.
  66.       The test is ommitted when we're not running under DOS.
  67.    */
  68.  
  69. #if (DOS)
  70.    if (currtask && GLOBDATA in_sched)
  71.       tsk_fatal ("Kill while in Scheduler");
  72. #endif
  73.  
  74.    task->state = ST_KILLED;
  75.    task->qhead = LNULL;
  76.    tsk_deqtimer (&task->timerq.link);
  77.  
  78. #if (TSK_NAMED)
  79.    tsk_dequeue ((queptr)&task->name.list);
  80. #endif
  81.  
  82. #if (TSK_DYNAMIC)
  83.    if (!currtask)
  84.       {
  85.       if (task->flags & F_STTEMP)
  86.          tsk_pfree (task->stkbot);   /* Bug fixed in 2.1, was 'task->stack' */
  87.       if (task->flags & F_TEMP)
  88.          tsk_pfree (task);
  89.       }
  90.    else if (task->flags & (F_STTEMP | F_TEMP))
  91.       {
  92.       task->qhead = &GLOBDATA kill_queue;
  93.       if (GLOBDATA kill_task->state == ST_STOPPED)
  94.          tsk_runable (GLOBDATA kill_task);
  95.       }
  96. #endif
  97.  
  98.    if (currtask)
  99.       schedule ();
  100. }
  101.  
  102. /*
  103.    Killretn kills the current active task. It is used internally, but
  104.    can also be called from outside. (However, *never* call it from an 
  105.    interrupt handler!)
  106. */
  107.  
  108. void Taskfunc killretn (void)
  109. {
  110.    tsk_cli ();
  111.    tsk_kill (GLOBDATA current_task, 1);
  112. }
  113.  
  114.  
  115. /*
  116.    tsk_kill_queue
  117.       Removes all tasks from a queue, and marks queue invalid. 
  118.       For internal use only.
  119.  
  120.       CAUTION: Critical section assumed entered.
  121. */
  122.  
  123. void Localfunc tsk_kill_queue (queheadptr que)
  124. {
  125.    queptr curr, next;
  126.  
  127.    CHECK_QHEAD (que, "Task Kill Queue");
  128.  
  129.    for (curr = que->first; !(curr->kind & Q_HEAD); )
  130.       {
  131.       next = curr->next;
  132.       tsk_kill ((tcbptr)curr, 0);
  133.       curr = next;
  134.       }
  135.    tsk_init_qhead (que, 0xff);
  136. }
  137.  
  138.  
  139. /* ---------------------------------------------------------------------- */
  140.  
  141. /*
  142.    create_task
  143.       Initialises a tcb. The task is in stopped state initially.
  144. */
  145.  
  146. tcbptr Globalfunc create_task (tcbptr task,
  147.                                funcptr func,
  148.                                byteptr stack,
  149.                                word stksz,
  150.                                word prior,
  151.                                farptr arg
  152.                                TN(byteptr name)
  153.                                )
  154.  
  155. {
  156.    struct task_stack far *stk;
  157. #if (CHECKING)
  158.    word i;
  159. #endif
  160.  
  161. #if (TSK_DYNAMIC)
  162.    if (task == LNULL)
  163.       {
  164.       if ((task = (tcbptr) tsk_palloc (sizeof(tcb))) == LNULL)
  165.          return LNULL;
  166.       task->flags = F_TEMP;
  167.       }
  168.    else
  169.       task->flags = 0;
  170.  
  171.    if (stack == LNULL)
  172.       {
  173.       if ((stack = (byteptr) tsk_palloc (stksz)) == LNULL)
  174.          {
  175.          if (task->flags & F_TEMP)
  176.             tsk_pfree (task);
  177.          return LNULL;
  178.          }
  179.       task->flags |= F_STTEMP;
  180.       }
  181. #else
  182.    task->flags = 0;
  183. #endif
  184.  
  185.    stk = (struct task_stack far *)(stack + stksz - sizeof (struct task_stack));
  186.    stk->r_ds = task->t_es = tsk_dseg ();
  187.    stk->r_flags = tsk_flags ();
  188.    stk->retn = func;
  189.    stk->dummyret = killretn;
  190.    stk->arg = arg;
  191.    task->t_bp = 0;
  192.  
  193.    task->stkbot = stack;
  194. #if (CHECKING)
  195.    for (i = 0; i < stksz - sizeof (struct task_stack); i++)
  196.       *stack++ = (byte)i;
  197. #endif
  198.    task->stack = (byteptr) stk;
  199.    task->cqueue.kind = TYP_TCB;
  200.    task->cqueue.next = LNULL;
  201.    task->qhead = LNULL;
  202.    task->state = ST_STOPPED;
  203.    task->cqueue.el.pri.prior = task->cqueue.el.pri.ini_prior = prior;
  204.    task->timerq.link.el.ticks = task->timerq.elem.time.reload = 0L;
  205.    task->timerq.link.kind = TYP_TIMER;
  206.    task->timerq.link.next = LNULL;
  207.    task->timerq.strucp = (farptr) task;
  208.    task->timerq.struckind = TKIND_WAKE;
  209.    task->timerq.flags = 0;
  210.    task->save_func = task->rest_func = LNULL;
  211. #if (DOS)
  212.    task->sched_ent_func = LNULL;
  213. #endif
  214.    task->user_ptr = LNULL;
  215.  
  216. #if (GROUPS)
  217.    task->group = task->homegroup = GLOBDATA current_task->group;
  218. #endif
  219. #if (DOS)
  220.    task->indos = 0;
  221.    task->t_new = 1;
  222.    task->base_psp = task->group->create_psp;
  223.    tsk_get_dosswap (task);
  224. #endif
  225.  
  226. #if (TSK_NAMED)
  227.    tsk_add_name (&task->name, name, TYP_TCB, task);
  228. #endif
  229.  
  230. #if (EMS)
  231.    if (GLOBDATA ems_savetsk != LNULL)
  232.       GLOBDATA ems_savetsk (task);
  233. #endif
  234.  
  235. #if (NDP)
  236.    if (tsk_use_ndp && GLOBDATA ndp_present)
  237.       task->flags |= F_USES_NDP;
  238. #endif
  239.  
  240.    return task;
  241. }
  242.  
  243.  
  244. /*
  245.    kill_task
  246.       Removes a task from the system.
  247. */
  248.  
  249. void Globalfunc kill_task (tcbptr task)
  250. {
  251.    CRITICAL;
  252.  
  253.    CHECK_TCBPTR (task, "Kill Task");
  254.  
  255.    C_ENTER;
  256.    if (task != GLOBDATA current_task)
  257.       {
  258.       if (task->state == ST_KILLED)
  259.          return;
  260.       else
  261.          tsk_dequeue (&task->cqueue);
  262.  
  263.       tsk_kill (task, 0);
  264.       }
  265.    else
  266.       tsk_kill (task, 1);
  267.  
  268.    C_LEAVE;
  269. }
  270.  
  271.  
  272. /*
  273.    start_task
  274.       Starts a stopped task. Returns -1 if the task was not stopped.
  275. */
  276.  
  277. int Globalfunc start_task (tcbptr task)
  278. {
  279.    CRITICAL;
  280.  
  281.    if (task == LNULL)
  282. #if (GROUPS)
  283.       task = GLOBDATA current_task->group->main_ptr;
  284. #else
  285.       task = GLOBDATA main_ptr;
  286. #endif
  287.  
  288.    CHECK_TCBPTR (task, "Start Task");
  289.  
  290.    if (task->state == ST_STOPPED)
  291.       {
  292.       task->state = ST_ELIGIBLE;
  293.       C_ENTER;
  294.       tsk_runable (task);
  295.       C_LEAVE;
  296.       return 0;
  297.       }
  298.    return -1;
  299. }
  300.  
  301.  
  302.