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

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