home *** CD-ROM | disk | FTP | other *** search
- /*
- CPPTask - A Multitasking Kernel For C++
-
- Version 1.0 08-12-91
-
- Ported by Rich Smith from:
-
- Public Domain Software written by
- Thomas Wagner
- Patschkauer Weg 31
- D-1000 Berlin 33
- West Germany
-
- TSKTASK.CPP - task class member functions
-
- Subroutines:
- task::task
- task::~task
- task::operator new
- task::start_task
- task::wake_task
- task::tsk_enqueue
- task::tsk_unqueue
- task::tsk_enqtimer
- task::tsk_unqtimer
- task::tsk_runable
- task::set_priority
- task::get_priority
- task::set_state
- task::get_state
- task::set_user_flags
- task::set_system_flags
- task::get_flags
- task::set_retptr
- task::get_retptr
- task::set_retsize
- task::get_retsize
- task::get_next
-
- */
-
- #include "task.hpp"
- #include "tsklocal.hpp"
-
- /*
- create_task
- Initialises a tcb. The task is in stopped state initially.
- */
-
- task::task (funcptr func,
- byteptr stackptr,
- word stksz,
- word priority,
- farptr arg)
- {
- struct task_stack far *stk;
-
- if (func == NULL)
- {
- stkbot = NULL;
- stack = NULL;
- queue = &tsk_eligible;
- state = ST_RUNNING;
- flags = flags | F_CRIT;
- }
- else
- {
- stk = (struct task_stack far *)
- (stackptr + stksz - sizeof (struct task_stack));
- stk->r_ds = stk->r_es = tsk_dseg ();
- stk->r_bp = 0;
- stk->r_flags = tsk_flags ();
- stk->retn = func;
- stk->dummyret = killretn;
- stk->arg = arg;
-
- stkbot = stackptr;
- stack = (byteptr) stk;
- queue = NULL;
- state = ST_STOPPED;
- }
- next = NULL;
- prior = initprior = priority;
- timerq = new timer(0, NULL, TKIND_TASK, 0);
- timerq->strucp = (farptr) this;
- }
-
-
- /*
- ~task
- Removes a task from the system.
- CAUTION: The task control block may *not* be immediately re-used
- if it was enqueued in the timer queue. Check for
- task->timerq->tstate == TSTAT_IDLE before modifying
- the tcb.
- */
-
- task::~task (void)
- {
- byte st;
- CRITICAL;
-
- C_ENTER;
-
-
- if (this != &main_tcb)
- {
- if ((st = state) != ST_RUNNING)
- tsk_unqueue ();
-
- queue = NULL;
- tsk_kill ();
- if (st == ST_RUNNING)
- {
- tsk_current = NULL;
- tasker.schedule ();
- }
- C_LEAVE;
- }
- }
-
-
- void* task::operator new(size_t size)
- {
- void *ptr;
-
- ptr = tsk_alloc(size); // call protected memory allocation procedure
-
- if (ptr)
- ((tcbptr) ptr)->flags = F_TEMP;
-
- return ptr;
- }
-
-
- /*
- tsk_kill - mark task as killed.
- */
-
- void far task::tsk_kill (void)
- {
- state = ST_KILLED;
-
- // delete timerq element only if it is IDLE, otherwise mark it for
- // deletion by the timer_main function
-
- if (timerq->tstate != TSTAT_IDLE)
- {
- timerq->tstate = (byte) TSTAT_REMOVE;
- if (flags & F_TEMP)
- timerq->tkind |= TKIND_TEMP;
- }
- else
- delete timerq;
-
- if (flags & F_STTEMP)
- delete stack;
-
- }
-
-
- /*
- start_task
- Starts a stopped task. Returns -1 if the task was not stopped.
- */
-
- int far task::start_task (void)
- {
- CRITICAL;
-
- if (state == ST_STOPPED)
- {
- state = ST_ELIGIBLE;
- C_ENTER;
- tsk_enqueue (&tsk_eligible);
- C_LEAVE;
- return 0;
- }
- return -1;
- }
-
-
- /*
- wake_task
- Restarts a task waiting for an event or timeout.
- Returns -1 if the task was not waiting or stopped.
- */
-
- int far task::wake_task (void)
- {
- CRITICAL;
-
- C_ENTER;
- if (state >= ST_ELIGIBLE)
- {
- C_LEAVE;
- return -1;
- }
-
- retptr = TWAKE;
- tsk_wakeup ();
- C_LEAVE;
- return 0;
- }
-
-
-
- /*
- get_priority
- Returns the priority of a task.
- */
-
- word far task::get_priority (void)
- {
- return prior;
- }
-
-
- /*
- set_priority
- Changes the priority of a task. If the task is enqueued in a
- queue, its position in the queue is affected.
- */
-
- void far task::set_priority (word newprior)
- {
- tqueptr que;
- CRITICAL;
-
- C_ENTER;
- prior = initprior = newprior;
-
- if ((state != ST_RUNNING) && ((que = queue) != NULL))
- {
- tsk_unqueue ();
- tsk_enqueue (que);
- }
- C_LEAVE;
- }
-
- /*
- set_user_flags
- Changes the user modifiable flags of the task.
- */
-
- void far task::set_user_flags (byte newflags)
- {
- CRITICAL;
-
- C_ENTER;
- flags = (flags & FL_SYSM) | (newflags & FL_USRM);
- C_LEAVE;
- }
-
-
- /*
- set_system_flags
- Changes the system modifiable flags of the task.
- */
-
- void far task::set_system_flags (byte newflags)
- {
- CRITICAL;
-
- C_ENTER;
- flags = (newflags & FL_SYSM) | (flags & FL_USRM);
- C_LEAVE;
- }
-
-
- /*
- tsk_enqueue inserts a task into a queue based on priority.
- */
-
- void far task::tsk_enqueue (tqueptr que)
- {
- tcbptr last, curr;
-
- last = NULL;
- curr = *que;
-
- while (curr != NULL && curr->prior >= prior)
- {
- last = curr;
- curr = curr->next;
- }
- next = curr;
- if (last == NULL)
- *que = this;
- else
- last->next = this;
- queue = que;
- }
-
-
- /*
- tsk_unqueue
- Removes a task from somewhere in the middle of a queue. It is only
- used when stopping or prematurely waking a task, since in all other
- circumstances a task is only removed from the head of a queue.
- */
-
- void far task::tsk_unqueue (void)
- {
- tcbptr last, curr;
-
- if (state == ST_RUNNING || queue == NULL)
- return;
-
- last = NULL;
- curr = *queue;
-
- while (curr != this)
- {
- if (curr == NULL)
- return;
- last = curr;
- curr = curr->next;
- }
-
- if (last == NULL)
- *queue = curr->next;
- else
- last->next = curr->next;
- queue = NULL;
- }
-
-
- /*
- tsk_enqtimer inserts a task into the timer queue.
- */
-
- void far task::tsk_enqtimer (dword tout)
- {
- tlinkptr curr;
-
- if (tout == 0)
- return;
-
- /*
- Tasks are not sorted in the timer queue, so the task is inserted
- at the queue head. The timer task has to step through all tasks
- in the queue to cont down the timeout, so sorting would not bring
- any advantages.
- */
-
- curr = timerq;
- curr->timeout = tsk_timeout(tout);
- if (curr->tstate == TSTAT_IDLE)
- {
- curr->next = tsk_timer;
- tsk_timer = curr;
- }
- curr->tstate = TSTAT_COUNTDOWN;
- }
-
-
- /*
- tsk_unqtimer marks task for removal from the timer queue.
- */
-
- void task::tsk_unqtimer(void)
- {
- if (timerq->tstate != TSTAT_IDLE)
- timerq->tstate = (byte) TSTAT_REMOVE;
- }
-
-
- /*
- tsk_runable
- make a task eligible for running. The task is removed from the
- timer queue and enqueued in the eligible queue. The old "next"
- pointer of the tcb is returned. This assumes that the task
- is removed from the head of a queue.
- */
-
- tcbptr far task::tsk_runable (void)
- {
- tcbptr nxt;
-
- nxt = next;
- state = ST_ELIGIBLE;
- tsk_unqtimer ();
- tsk_enqueue (&tsk_eligible);
- return nxt;
- }
-
-
- /*
- tsk_wakeup
- make a task eligible for running. The task is removed from the
- timer queue and enqueued in the eligible queue.
- This routine assumes that the task is removed from the middle of
- a queue.
- */
-
- void far task::tsk_wakeup (void)
- {
- state = ST_ELIGIBLE;
- tsk_unqueue ();
- tsk_unqtimer ();
- tsk_enqueue (&tsk_eligible);
- }
-
-
- /*
- 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.
- */
-
- void far tsk_wait (tqueptr que, dword timeout)
- {
- tsk_current->state = ST_WAITING;
- tsk_current->queue = que;
- tsk_current->tsk_enqtimer (timeout);
- tasker.schedule ();
- }
-
-
-