home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frostbyte's 1980s DOS Shareware Collection
/
floppyshareware.zip
/
floppyshareware
/
DOOG
/
CTASK.ZIP
/
TSKSUB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-20
|
7KB
|
299 lines
/*
--- Version 2.0 89-12-17 21:19 ---
CTask Subroutines
Public Domain Software written by
Thomas Wagner
Patschkauer Weg 31
D-1000 Berlin 33
West Germany
*/
#include <stdio.h>
#include "tsk.h"
#include "tsklocal.h"
/*
tsk_runable
Make a task eligible for running. The task is removed from the
timer queue and enqueued in the eligible queue.
CAUTION: Critical section assumed entered.
*/
void near tsk_runable (tcbptr task)
{
task->state = ST_ELIGIBLE;
tsk_deqtimer (&task->timerq.link);
tsk_dequeue (&task->cqueue);
tsk_enqueue (task->qhead = &GLOBDATA eligible_queue, &task->cqueue);
}
/*
tsk_runable_all
Make all tasks in a queue eligible for running.
CAUTION: Critical section assumed entered.
*/
void near tsk_runable_all (queheadptr que)
{
queptr curr;
tcbptr task;
for (curr = que->first; curr->kind; )
{
task = (tcbptr)curr;
curr = curr->next;
task->state = ST_ELIGIBLE;
tsk_deqtimer (&task->timerq.link);
tsk_enqueue (task->qhead = &GLOBDATA eligible_queue, &task->cqueue);
}
tsk_init_qhead (que);
}
/*
tsk_wait
put current running task in wait state.
Note that the task is NOT enqueued in the respective queue
here, this is done by the scheduler based on the queue head
pointer. Only the timeout queue is affected directly.
CAUTION: Critical section assumed entered.
*/
void near tsk_wait (queheadptr que, dword timeout)
{
tcbptr curr;
curr = GLOBDATA current_task;
/*
Note: The following test shouldn't be necessary. However,
there is a time when the current task is *not* running, and
that's while the scheduler is waiting for a task to become
eligible. If an interrupt handler causes the current task to
be made waiting during this time, we have to take care not to
kill the eligible queue. Well, no interrupt handler should ever
do such a nasty thing, but...
*/
if (curr->state != ST_RUNNING)
{
tsk_dequeue (&curr->cqueue);
tsk_deqtimer (&curr->timerq.link);
tsk_enqueue (que, &curr->cqueue);
}
curr->qhead = que;
curr->state = ST_WAITING;
if (timeout)
{
tsk_enqtimer (&curr->timerq.link, timeout);
curr->timerq.tstate = TSTAT_COUNTDOWN;
}
schedule ();
}
/*
tsk_kill
mark task as killed.
CAUTION: Critical section assumed entered.
*/
void near tsk_kill (tcbptr task)
{
task->state = ST_KILLED;
task->qhead = NULL;
tsk_deqtimer (&task->timerq.link);
#if (TSK_NAMED)
tsk_dequeue ((queptr)&task->name.list);
#endif
#if (TSK_DYNAMIC)
if (task->flags & F_STTEMP)
tsk_free (task->stack);
if (task->flags & F_TEMP)
tsk_free (task);
#endif
}
/*
tsk_kill_queue
Removes all tasks from a queue. For internal use only.
CAUTION: Critical section assumed entered.
*/
void near tsk_kill_queue (queheadptr que)
{
queptr curr, next;
for (curr = que->first; curr->kind; )
{
next = curr->next;
tsk_kill ((tcbptr)curr);
curr = next;
}
tsk_init_qhead (que);
}
#if (CLOCK_MSEC)
dword near tsk_timeout (dword tout)
{
dword t;
t = (dword) (((double)tout / tick_factor) + 0.5);
return (t) ? t : 1;
}
#endif
#if (TSK_NAMED)
/*
tsk_copy_name
A replacement for strcpy, used for copying names. The C-runtime
strcpy is not used here to keep the kernel model independent.
*/
void near tsk_copy_name (nameptr elem, byteptr name)
{
byteptr n;
int i;
n = elem->name;
if (name != NULL)
for (i = 0; i < 8; i++)
if ((*n++ = *name++) == 0)
break;
*n = 0;
}
/*
tsk_add_name
Initialise name-list element and insert it into the name list.
NOTE: no check is made for duplicate names; names are not sorted.
*/
void near tsk_add_name (nameptr elem, byteptr name, byte kind, farptr strucp)
{
CRITICAL;
elem->list.kind = kind;
elem->strucp = strucp;
tsk_copy_name (elem, name);
C_ENTER;
#if (GROUPS)
tsk_putqueue (&GLOBDATA current_task->group->namelist.list, (queptr)&elem->list);
#else
tsk_putqueue (&GLOBDATA name_list.list, &elem.list);
#endif
C_LEAVE;
}
/*
tsk_del_name
delete name-element from the name-list.
*/
void near tsk_del_name (nameptr elem)
{
CRITICAL;
C_ENTER;
tsk_dequeue ((queptr)&elem->list);
C_LEAVE;
}
/*
find_name
find structure, given name and type.
If type is zero, the first name-element matching the name is returned.
If type is nonzero, the first structure matching the name and type is
returned.
*/
local int near tsk_streq (byteptr n1, byteptr n2)
{
while (*n1 && *n1 == *n2)
{
n1++;
n2++;
}
return *n1 == *n2;
}
#if (GROUPS)
farptr far find_group_name (gcbptr group, byteptr name, int kind)
{
queptr curr;
if (kind == TYP_GROUP && tsk_streq (name, group->namelist.name))
return group;
for (curr = group->namelist.list.first; curr->kind; curr = curr->next)
if (kind < 0 || (int)curr->kind == kind)
if (tsk_streq (name, ((nameptr)curr)->name))
return (kind >= 0) ? ((nameptr)curr)->strucp : curr;
return NULL;
}
#endif
farptr far find_name (byteptr name, int kind)
{
#if (GROUPS)
farptr curr;
gcbptr group;
if (tsk_global == NULL)
if (!ctask_resident ())
return NULL;
for (group = GLOBDATA current_task->group;
group != NULL; group = group->home)
if ((curr = find_group_name (group, name, kind)) != NULL)
return curr;
#else
queueptr curr;
if (kind == TYP_GROUP && tsk_streq (name, GLOBDATA name_list.name))
return group;
for (curr = GLOBDATA name_list.list.first; curr->kind;
curr = curr->next)
if (kind < 0 || (int)curr->kind == kind)
if (tsk_streq (name, ((nameptr)curr)->name))
return (kind >= 0) ? ((nameptr)curr)->strucp : curr;
#endif
return NULL;
}
#endif
/*
tsk_init_qhead
Initializes the head of a queue.
*/
void near tsk_init_qhead (queheadptr head)
{
head->kind = 0;
head->first = head->last = (queptr)head;
}