/********************************************************************20**
Name: System Services -- Task Management
Type: C source file
Desc: Source code for System Services functions for task mgmt.
File: ss_task.c
Sid: ss_task.c 1.3 - 10/14/98 14:22:22
Prg: kp
*********************************************************************21*/
/* header include files (.h) */
#include "envopt.h" /* environment options */
#include "envdep.h" /* environment dependent */
#include "envind.h" /* environment independent */
#include "gen.h" /* general layer */
#include "ssi.h" /* system services */
#include "ss_err.h" /* errors */
#include "ss_dep.h" /* implementation-specific */
#include "ss_queue.h" /* queues */
#include "ss_task.h" /* tasking */
#include "ss_msg.h" /* messaging */
#include "ss_mem.h" /* memory management interface */
#include "ss_gen.h" /* general */
/* header/extern include files (.x) */
#include "gen.x" /* general layer */
#include "ssi.x" /* system services */
#include "ss_dep.x" /* implementation-specific */
#include "ss_queue.x" /* queues */
#include "ss_task.x" /* tasking */
#include "ss_timer.x" /* timers */
#include "ss_strm.x" /* STREAMS */
#include "ss_msg.x" /* messaging */
#include "ss_mem.x" /* memory management interface */
#include "ss_drvr.x" /* driver tasks */
#include "ss_gen.x" /* general */
/*
*
* Fun: SRegInit
*
* Desc: This function is used to register an initialization function
* for the layer. The system services will invoke the function
* passed to it one time. The initialization function will be
* used by the layer to initilize the layer.
*
* Ret: ROK - ok
* RFAILED - failed, general (optional)
*
* Notes:
*
* File: ss_task.c
*
*/
#ifdef ANSI
PUBLIC S16 SRegInit
(
Ent ent, /* entity */
Inst inst, /* instance */
PAIFS16 initFnct /* initialization function */
)
#else
PUBLIC S16 SRegInit(ent, inst, initFnct)
Ent ent; /* entity */
Inst inst; /* instance */
PAIFS16 initFnct; /* initialization function */
#endif
{
TRC1(SRegInit);
#if (ERRCLASS & ERRCLS_INT_PAR)
/* check entity and instance ranges */
if (ent >= SS_MAX_ENT || inst >= SS_MAX_INST)
{
SSLOGERROR(ERRCLS_INT_PAR, ESS449, ERRZERO, "Invalid entity/instance");
RETVALUE(RFAILED);
}
/* check initialization function */
if (initFnct == NULLP)
{
SSLOGERROR(ERRCLS_INT_PAR, ESS450, ERRZERO, "Null pointer");
RETVALUE(RFAILED);
}
#endif
/* Activate initialization function. This uses hard-coded
* parameters.
*/
(Void)(*initFnct)(ent, inst, DFLT_REGION, PWR_UP);
RETVALUE(ROK);
} /* SRegInit */
/*
*
* Fun: SRegActvTsk
*
* Desc: This function is used to register an activation function
* for the layer. The system services will invoke the
* function passed to it whenever a task buffer is received.
* The activation function will be used by the layer to receive
* messages from other entities. It allows a priority to be
* associated with the task so that it can be preempted if
* necessary.
*
* Ret: ROK - ok
* RFAILED - failed, general (optional)
* ROUTRES - failed, out of resources (optional)
*
* Notes: We pass NULLP for the initialization function, because
* it is assumed that whoever is using this call will also
* be calling SRegInit().
*
* File: ss_task.c
*
*/
#ifdef ANSI
PUBLIC S16 SRegActvTsk
(
Ent ent, /* entity */
Inst inst, /* instance */
Ttype ttype, /* task type */
Prior prior, /* task priority */
ActvTsk actvTsk /* activate task function */
)
#else
PUBLIC S16 SRegActvTsk(ent, inst, ttype, prior, actvTsk)
Ent ent; /* entity */
Inst inst; /* instance */
Ttype ttype; /* task type */
Prior prior; /* task priority */
ActvTsk actvTsk; /* activate task function */
#endif
{
S16 ret;
SSTskId sTskId;
Prior spri;
TRC1(SRegActvTsk);
#if (ERRCLASS & ERRCLS_INT_PAR)
/* check entity and instance ranges */
if (ent >= SS_MAX_ENT || inst >= SS_MAX_INST)
{
SSLOGERROR(ERRCLS_INT_PAR, ESS451, ERRZERO, "Invalid entity/instance");
RETVALUE(RFAILED);
}
/* check activation function */
if (actvTsk == NULLP)
{
SSLOGERROR(ERRCLS_INT_PAR, ESS452, ERRZERO, "Null pointer");
RETVALUE(RFAILED);
}
/* check task type */
if (ttype != TTNORM && ttype != TTPERM)
{
SSLOGERROR(ERRCLS_INT_PAR, ESS453, ERRZERO, "Invalid task type");
}
/* check task priority */
if (prior > PRIOR3)
{
SSLOGERROR(ERRCLS_INT_PAR, ESS454, ERRZERO, "Invalid task priority");
RETVALUE(RFAILED);
}
#endif
#if (ERRCLASS & ERRCLS_DEBUG)
/* lock system task table */
ret = SLock(&osCp.sTskTblLock);
if (ret != ROK)
{
SSLOGERROR(ERRCLS_DEBUG, ESS455, ERRZERO,
"Could not lock system task table");
RETVALUE(RFAILED);
}
/* lock TAPA task table */
SS_ACQUIRE_ALL_SEMA(&osCp.tTskTblSem, ret);
if (ret != ROK)
{
SUnlock(&osCp.sTskTblLock);
SSLOGERROR(ERRCLS_DEBUG, ESS456, ERRZERO,
"Could not lock TAPA task table");
RETVALUE(RFAILED);
}
/* check count of tasks */
if (osCp.numTTsks == SS_MAX_TTSKS || osCp.numSTsks == SS_MAX_STSKS)
{
SS_RELEASE_ALL_SEMA(&osCp.tTskTblSem);
SUnlock(&osCp.sTskTblLock);
SSLOGERROR(ERRCLS_DEBUG, ESS457, ERRZERO, "Too many tasks");
RETVALUE(ROUTRES);
}
/* check if entity and instance already registered */
if (osCp.tTskIds[ent][inst] != SS_TSKNC)
{
SS_RELEASE_ALL_SEMA(&osCp.tTskTblSem);
SUnlock(&osCp.sTskTblLock);
SSLOGERROR(ERRCLS_DEBUG, ESS458, ERRZERO,
"Entity and instance already registered");
RETVALUE(RFAILED);
}
/* unlock tables */
SS_RELEASE_ALL_SEMA(&osCp.tTskTblSem);
SUnlock(&osCp.sTskTblLock);
#endif
/* check and bump the priority if it is a permanent task */
if (ttype == TTPERM)
{
prior = PRIOR3;
}
/* Register this task as a TAPA task. We pass NULLP for the
* initialization function, because whoever is using this
* call (SRegActvTsk()) will also be calling SRegInit().
*/
ret = SRegTTsk(ent, inst, ttype, prior, NULLP, actvTsk);
if (ret != ROK)
{
#if (ERRCLASS & ERRCLS_DEBUG)
SSLOGERROR(ERRCLS_DEBUG, ESS459, (ErrVal) ret,
"Could not register task");
#endif
RETVALUE(ret);
}
/* Now we create a system task--one per TAPA task is the
* semantics of SRegActvTsk().
*/
if (ttype == TTNORM)
spri = SS_NORM_TSK_PRI;
else
spri = SS_PERM_TSK_PRI;
ret = SCreateSTsk(spri, &sTskId);
if (ret != ROK)
{
#if (ERRCLASS & ERRCLS_DEBUG)
SSLOGERROR(ERRCLS_DEBUG, ESS460, (ErrVal) ret,
"Could not create system task");
#endif
SDeregTTsk(ent, inst);
RETVALUE(ret);
}
/* Attach the TAPA task we just registered, to the system
* task we just created.
*/
ret = SAttachTTsk(ent, inst, sTskId);
if (ret != ROK)
{
#if (ERRCLASS & ERRCLS_DEBUG)
SSLOGERROR(ERRCLS_DEBUG, ESS461, (ErrVal) ret,
"Could not attach TAPA task to system task");
#endif
SDestroySTsk(sTskId);
SDeregTTsk(ent, inst);
}
RETVALUE(ret);
} /* SRegActvTsk */
/*
*
* Fun: Deregister Initialize, task buffer and timer
*
* Desc: This function is used to deregister the initialization,
* activation and timer functions for a task.
*
* Ret: ROK - ok
*
* Notes: None.
*
* File: ss_task.c
*
*/
#ifdef ANSI
PUBLIC S16 SDeregInitTskTmr
(
Ent ent, /* entity */
Inst inst /* instance */
)
#else
PUBLIC S16 SDeregInitTskTmr(ent, inst)
Ent ent; /* entity */
Inst inst; /* instance */
#endif
{
SsTTskEntry *tTsk;
SsSTskEntry *sTsk;
S16 ret;
/* add by shang to avoid warning */
SSTskId sTskId = 0;
/* add by shang to avoid warning over*/
SsIdx idx;
Bool destroySTsk;
TRC1(SDeregInitTskTmr);
#if (ERRCLASS & ERRCLS_INT_PAR)
/* check entity and instance ranges */
if (ent >= SS_MAX_ENT || inst >= SS_MAX_INST)
{
SSLOGERROR(ERRCLS_INT_PAR, ESS462, ERRZERO, "Invalid entity/instance");
RETVALUE(RFAILED);
}
#endif
/* lock the TAPA task table */
SS_ACQUIRE_ALL_SEMA(&osCp.tTskTblSem, ret);
if (ret != ROK)
{
#if (ERRCLASS & ERRCLS_DEBUG)
SSLOGERROR(ERRCLS_DEBUG, ESS463, ERRZERO,
"Could not lock TAPA task table");
#endif
RETVALUE(RFAILED);
}
#if (ERRCLASS & ERRCLS_INT_PAR)
/* check whether this entity is registered */
if (osCp.tTskIds[ent][inst] == SS_TSKNC)
{
SS_RELEASE_ALL_SEMA(&osCp.tTskTblSem);
SSLOGERROR(ERRCLS_INT_PAR, ESS464, ERRZERO, "Unknown task");
RETVALUE(RFAILED);
}
#endif
/* get out the TAPA task entry */
tTsk = &osCp.tTskTbl[osCp.tTskIds[ent][inst]];
/* get out the system task that's running this TAPA task */
sTsk = tTsk->sTsk;
/* get out the ID of this system task */
if (sTsk != NULLP)
{
sTskId = sTsk->tskId;
}
/* unlock the TAPA task table */
SS_RELEASE_ALL_SEMA(&osCp.tTskTblSem);
/* deregister the TAPA task */
if (SDeregTTsk(ent, inst) != ROK)
{
RETVALUE(RFAILED);
}
/* Now, if the TAPA task was attached, and nobody else is using that
* system task, we should destroy it.
*/
if (sTsk != NULLP)
{
destroySTsk = FALSE;
/* lock the system task table */
ret = SLock(&osCp.sTskTblLock);
if (ret != ROK)
{
#if (ERRCLASS & ERRCLS_DEBUG)
SSLOGERROR(ERRCLS_DEBUG, ESS465, (ErrVal) ret,
"Could not lock system task table");
#endif
RETVALUE(RFAILED);
}
idx = (SsIdx) sTskId;
sTsk = &osCp.sTskTbl[idx];
/* check if the system task is still around */
if (sTsk->used != TRUE)
{
SUnlock(&osCp.sTskTblLock);
RETVALUE(ROK);
}
/* check if the system task is dying already */
if (sTsk->termPend)
{
SUnlock(&osCp.sTskTblLock);
RETVALUE(ROK);
}
/* If this system task entry has no more TAPA tasks attached,
* we destroy it, otherwise we do nothing.
*/
if (sTsk->numTTsks == 0)
{
sTsk->termPend = TRUE;
destroySTsk = TRUE;
}
/* unlock */
SUnlock(&osCp.sTskTblLock);
/* If we're destroying the system task, ask the implementation
* to do it.
*/
if (destroySTsk)
{
ret = ssdDestroySTsk(sTsk);
if (ret != ROK)
{
/* oops? */
#if (ERRCLASS & ERRCLS_DEBUG)
SSLOGERROR(ERRCLS_DEBUG, ESS466, (ErrVal) ret,
"Could not destroy system task");
#endif
RETVALUE(RFAILED);
}
}
}
RETVALUE(ROK);
} /* SDeregInitTskTmr */
/*
*
* Fun: Register a TAPA task
*
* Desc: This function is used to register a TAPA task,
* and its initialization and activation functions.
*
* Ret: ROK - ok
* RFAILED - failed, general (optional)
* ROUTRES - failed, out of resources (optional)
*
* Notes:
*
* File: ss_task.c
*
*/
#ifdef ANSI
PUBLIC S16 SRegTTsk
(
Ent ent, /* entity */
Inst inst, /* instance */
Ttype type, /* task type */
Prior prior, /* task priority */
PAIFS16 initTsk, /* initialization function */
ActvTsk actvTsk /* activation function */
)
#else
PUBLIC S16 SRegTTsk(ent, inst, type, prior, initTsk, actvTsk)