delay() fix, Vx5.0 compile option, code clean-up, task delete fix, removed task variables.
This commit is contained in:
@@ -2,3 +2,5 @@
|
||||
### 3 Apr. 1991 (MDA) moved seq.c to seq_main.c for consistency with
|
||||
### snc, and for ease of use in Imakefiles...
|
||||
###
|
||||
### 03jan92,ajk s_*.c files are VxWorks version 5 compatable.
|
||||
###
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 07-03-91 ajk .
|
||||
* .02 12-11-91 ajk Cosmetic changes (comments & names)
|
||||
*/
|
||||
|
||||
#include "seq.h"
|
||||
@@ -43,41 +44,46 @@ LOCAL void *getPtrToValue();
|
||||
|
||||
#define MACRO_STR_LEN (MAX_STRING_SIZE+1)
|
||||
|
||||
/* Connect to the database channels through channel access */
|
||||
seq_connect(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
/*
|
||||
* seq_connect() - Connect to all database channels through channel access.
|
||||
*/
|
||||
seq_connect(pSP)
|
||||
SPROG *pSP;
|
||||
{
|
||||
CHAN *db_ptr;
|
||||
CHAN *pDB;
|
||||
int status, i;
|
||||
MACRO *macro_tbl;
|
||||
extern seq_conn_handler();
|
||||
extern VOID seq_conn_handler();
|
||||
|
||||
/* Initialize CA task */
|
||||
ca_task_initialize();
|
||||
|
||||
sp_ptr->conn_count = 0;
|
||||
macro_tbl = sp_ptr->mac_ptr;
|
||||
pSP->conn_count = 0;
|
||||
macro_tbl = pSP->mac_ptr;
|
||||
|
||||
/* Search for all channels */
|
||||
db_ptr = sp_ptr->channels;
|
||||
for (i = 0; i < sp_ptr->nchan; i++)
|
||||
/*
|
||||
* For each channel: substitute macros, connect to db,
|
||||
* & isssue monitor (if monitor request flaf is TRUE).
|
||||
*/
|
||||
pDB = pSP->channels;
|
||||
for (i = 0; i < pSP->nchan; i++)
|
||||
{
|
||||
/* Do macro substitution on channel name */
|
||||
db_ptr->db_name = seqAlloc(sp_ptr, MACRO_STR_LEN);
|
||||
seqMacEval(db_ptr->db_uname, db_ptr->db_name, MACRO_STR_LEN,
|
||||
pDB->db_name = seqAlloc(pSP, MACRO_STR_LEN);
|
||||
seqMacEval(pDB->db_uname, pDB->db_name, MACRO_STR_LEN,
|
||||
macro_tbl);
|
||||
#ifdef DEBUG
|
||||
printf("connect to \"%s\"\n", db_ptr->db_name);
|
||||
printf("connect to \"%s\"\n", pDB->db_name);
|
||||
#endif DEBUG
|
||||
/* Connect to it */
|
||||
status = ca_build_and_connect(
|
||||
db_ptr->db_name, /* DB channel name */
|
||||
pDB->db_name, /* DB channel name */
|
||||
TYPENOTCONN, /* Don't get initial value */
|
||||
0, /* get count (n/a) */
|
||||
&(db_ptr->chid), /* ptr to chid */
|
||||
&(pDB->chid), /* ptr to chid */
|
||||
0, /* ptr to value (n/a) */
|
||||
seq_conn_handler, /* connection handler routine */
|
||||
db_ptr); /* user ptr is CHAN structure */
|
||||
pDB); /* user ptr is CHAN structure */
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
SEVCHK(status, "ca_search");
|
||||
@@ -85,166 +91,179 @@ SPROG *sp_ptr;
|
||||
return -1;
|
||||
}
|
||||
/* Clear monitor indicator */
|
||||
db_ptr->monitored = FALSE;
|
||||
pDB->monitored = FALSE;
|
||||
|
||||
/* Issue monitor requests */
|
||||
if (db_ptr->mon_flag)
|
||||
/*
|
||||
* Issue monitor request
|
||||
*/
|
||||
if (pDB->mon_flag)
|
||||
{
|
||||
seq_pvMonitor(sp_ptr, 0, db_ptr);
|
||||
seq_pvMonitor(pSP, 0, pDB);
|
||||
}
|
||||
db_ptr++;
|
||||
pDB++;
|
||||
}
|
||||
ca_flush_io();
|
||||
|
||||
if (sp_ptr->conn_flag)
|
||||
if (pSP->conn_flag)
|
||||
{ /* Wait for all connections to complete */
|
||||
while (sp_ptr->conn_count < sp_ptr->nchan)
|
||||
while (pSP->conn_count < pSP->nchan)
|
||||
taskDelay(30);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Channel access events (monitors) come here */
|
||||
/*
|
||||
* seq_event_handler() - Channel access events (monitors) come here.
|
||||
* args points to CA event handler argument structure. args.usr contains
|
||||
* a pointer to the channel structure (CHAN *).
|
||||
*/
|
||||
VOID seq_event_handler(args)
|
||||
struct event_handler_args args;
|
||||
{
|
||||
SPROG *sp_ptr;
|
||||
CHAN *db_ptr;
|
||||
SPROG *pSP;
|
||||
CHAN *pDB;
|
||||
struct dbr_sts_char *dbr_sts_ptr;
|
||||
void *value_ptr;
|
||||
void *pVal;
|
||||
int i, nbytes;
|
||||
|
||||
/* User arg is ptr to db channel structure */
|
||||
db_ptr = (CHAN *)args.usr;
|
||||
pDB = (CHAN *)args.usr;
|
||||
|
||||
/* Copy value returned into user variable */
|
||||
value_ptr = getPtrToValue(
|
||||
(union db_access_val *)args.dbr, db_ptr->get_type);
|
||||
nbytes = db_ptr->size * db_ptr->count;
|
||||
bcopy(value_ptr, db_ptr->var, nbytes);
|
||||
pVal = getPtrToValue((union db_access_val *)args.dbr, pDB->get_type);
|
||||
nbytes = pDB->size * pDB->count;
|
||||
bcopy(pVal, pDB->var, nbytes);
|
||||
|
||||
/* Copy status & severity */
|
||||
dbr_sts_ptr = (struct dbr_sts_char *)args.dbr;
|
||||
db_ptr->status = dbr_sts_ptr->status;
|
||||
db_ptr->severity = dbr_sts_ptr->severity;
|
||||
pDB->status = dbr_sts_ptr->status;
|
||||
pDB->severity = dbr_sts_ptr->severity;
|
||||
|
||||
/* Process event handling in each state set */
|
||||
sp_ptr = db_ptr->sprog; /* State program that owns this db entry */
|
||||
pSP = pDB->sprog; /* State program that owns this db entry */
|
||||
|
||||
/* Wake up each state set that is waiting for event processing */
|
||||
seq_efSet(sp_ptr, 0, db_ptr->index + 1);
|
||||
seq_efSet(pSP, 0, pDB->index + 1);
|
||||
|
||||
return;
|
||||
}
|
||||
/* Sequencer connection handler:
|
||||
Called each time a connection is established or broken */
|
||||
/*
|
||||
* seq_conn_handler() - Sequencer connection handler.
|
||||
* Called each time a connection is established or broken.
|
||||
*/
|
||||
VOID seq_conn_handler(args)
|
||||
struct connection_handler_args args;
|
||||
{
|
||||
CHAN *db_ptr;
|
||||
SPROG *sp_ptr;
|
||||
CHAN *pDB;
|
||||
SPROG *pSP;
|
||||
|
||||
|
||||
/* user argument (from ca_search() */
|
||||
db_ptr = (CHAN *)ca_puser(args.chid);
|
||||
/* User argument is db ptr (specified at ca_search() ) */
|
||||
pDB = (CHAN *)ca_puser(args.chid);
|
||||
|
||||
/* State program that owns this db entry */
|
||||
sp_ptr = db_ptr->sprog;
|
||||
pSP = pDB->sprog;
|
||||
|
||||
/* Check for connected */
|
||||
if (ca_field_type(args.chid) == TYPENOTCONN)
|
||||
{
|
||||
db_ptr->connected = FALSE;
|
||||
sp_ptr->conn_count--;
|
||||
seq_log(sp_ptr, "Channel \"%s\" disconnected\n", db_ptr->db_name);
|
||||
pDB->connected = FALSE;
|
||||
pSP->conn_count--;
|
||||
seq_log(pSP, "Channel \"%s\" disconnected\n", pDB->db_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
db_ptr->connected = TRUE;
|
||||
sp_ptr->conn_count++;
|
||||
seq_log(sp_ptr, "Channel \"%s\" connected\n", db_ptr->db_name);
|
||||
if (db_ptr->count > ca_element_count(args.chid))
|
||||
pDB->connected = TRUE;
|
||||
pSP->conn_count++;
|
||||
seq_log(pSP, "Channel \"%s\" connected\n", pDB->db_name);
|
||||
if (pDB->count > ca_element_count(args.chid))
|
||||
{
|
||||
db_ptr->count = ca_element_count(args.chid);
|
||||
seq_log(sp_ptr, "\"%s\": reset count to %d\n",
|
||||
db_ptr->db_name, db_ptr->count);
|
||||
pDB->count = ca_element_count(args.chid);
|
||||
seq_log(pSP, "\"%s\": reset count to %d\n",
|
||||
pDB->db_name, pDB->count);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wake up each state set that is waiting for event processing */
|
||||
seq_efSet(sp_ptr, 0, 0);
|
||||
seq_efSet(pSP, 0, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wake up each state set that is waiting for event processing */
|
||||
VOID seq_efSet(sp_ptr, dummy, ev_flag)
|
||||
SPROG *sp_ptr;
|
||||
/*
|
||||
* seq_efSet() - Set an event flag. The result is to wake up each state
|
||||
* set that is waiting for event processing.
|
||||
*/
|
||||
VOID seq_efSet(pSP, dummy, ev_flag)
|
||||
SPROG *pSP;
|
||||
int dummy;
|
||||
int ev_flag; /* event flag */
|
||||
{
|
||||
SSCB *ss_ptr;
|
||||
SSCB *pSS;
|
||||
int nss;
|
||||
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
pSS = pSP->sscb;
|
||||
/* For all state sets: */
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
for (nss = 0; nss < pSP->nss; nss++, pSS++)
|
||||
{
|
||||
/* Apply resource lock */
|
||||
semTake(sp_ptr->caSemId, WAIT_FOREVER);
|
||||
semTake(pSP->caSemId, WAIT_FOREVER);
|
||||
|
||||
/* Test for possible event trig based on bit mask for this state */
|
||||
if ( (ev_flag == 0) || bitTest(ss_ptr->pMask, ev_flag) )
|
||||
if ( (ev_flag == 0) || bitTest(pSS->pMask, ev_flag) )
|
||||
{
|
||||
bitSet(ss_ptr->events, ev_flag);
|
||||
semGive(ss_ptr->syncSemId); /* wake up the ss task */
|
||||
bitSet(pSS->events, ev_flag);
|
||||
semGive(pSS->syncSemId); /* wake up the ss task */
|
||||
}
|
||||
|
||||
/* Unlock resource */
|
||||
semGive(sp_ptr->caSemId);
|
||||
semGive(pSP->caSemId);
|
||||
}
|
||||
}
|
||||
|
||||
/* Test event flag against outstanding events */
|
||||
seq_efTest(sp_ptr, ss_ptr, ev_flag)
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
/*
|
||||
* seq_efTest() - Test event flag against outstanding events.
|
||||
*/
|
||||
seq_efTest(pSP, pSS, ev_flag)
|
||||
SPROG *pSP;
|
||||
SSCB *pSS;
|
||||
int ev_flag; /* event flag */
|
||||
{
|
||||
return bitTest(ss_ptr->events, ev_flag);
|
||||
return bitTest(pSS->events, ev_flag);
|
||||
}
|
||||
/* Get DB value (uses channel access) */
|
||||
seq_pvGet(sp_ptr, ss_ptr, db_ptr)
|
||||
SPROG *sp_ptr; /* ptr to state program */
|
||||
SSCB *ss_ptr; /* ptr to current state set */
|
||||
CHAN *db_ptr; /* ptr to channel struct */
|
||||
/*
|
||||
* seq_pvGet() - Get DB value (uses channel access).
|
||||
*/
|
||||
seq_pvGet(pSP, pSS, pDB)
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
SSCB *pSS; /* ptr to current state set */
|
||||
CHAN *pDB; /* ptr to channel struct */
|
||||
{
|
||||
int status, sem_status;
|
||||
extern seq_callback_handler();
|
||||
extern VOID seq_callback_handler();
|
||||
|
||||
/* Check for channel connected */
|
||||
if (!db_ptr->connected)
|
||||
if (!pDB->connected)
|
||||
return ECA_DISCONN;
|
||||
|
||||
/* Flag this pvGet() as not completed */
|
||||
db_ptr->get_complete = 0;
|
||||
pDB->get_complete = FALSE;
|
||||
|
||||
/* If synchronous pvGet then clear the pvGet pend semaphore */
|
||||
if (!sp_ptr->async_flag)
|
||||
if (!pSP->async_flag)
|
||||
{
|
||||
db_ptr->getSemId = ss_ptr->getSemId;
|
||||
semTake(ss_ptr->getSemId, NO_WAIT);
|
||||
pDB->getSemId = pSS->getSemId;
|
||||
semTake(pSS->getSemId, NO_WAIT);
|
||||
}
|
||||
|
||||
/* Perform the CA get operation with a callback routine specified */
|
||||
status = ca_array_get_callback(
|
||||
db_ptr->get_type, /* db request type */
|
||||
db_ptr->count, /* element count */
|
||||
db_ptr->chid, /* chid */
|
||||
pDB->get_type, /* db request type */
|
||||
pDB->count, /* element count */
|
||||
pDB->chid, /* chid */
|
||||
seq_callback_handler, /* callback handler */
|
||||
db_ptr); /* user arg */
|
||||
pDB); /* user arg */
|
||||
|
||||
if (sp_ptr->async_flag || (status != ECA_NORMAL) )
|
||||
if (pSP->async_flag || (status != ECA_NORMAL) )
|
||||
return status;
|
||||
|
||||
/* Synchronous pvGet() */
|
||||
@@ -252,49 +271,52 @@ CHAN *db_ptr; /* ptr to channel struct */
|
||||
ca_flush_io();
|
||||
|
||||
/* Wait for completion (10s timeout) */
|
||||
sem_status = semTake(ss_ptr->getSemId, 600);
|
||||
sem_status = semTake(pSS->getSemId, 600);
|
||||
if (sem_status == ERROR)
|
||||
status = ECA_TIMEOUT;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Sequencer callback handler - called when a "get" completes */
|
||||
seq_callback_handler(args)
|
||||
/*
|
||||
* seq_callback_handler() - Sequencer callback handler.
|
||||
* Called when a "get" completes.
|
||||
* args.usr points to the db structure (CHAN *) for tis channel.
|
||||
*/
|
||||
VOID seq_callback_handler(args)
|
||||
struct event_handler_args args;
|
||||
{
|
||||
SPROG *sp_ptr;
|
||||
CHAN *db_ptr;
|
||||
SPROG *pSP;
|
||||
CHAN *pDB;
|
||||
struct dbr_sts_char *dbr_sts_ptr;
|
||||
int i, nbytes;
|
||||
void *value_ptr;
|
||||
void *pVal;
|
||||
|
||||
/* User arg is ptr to db channel structure */
|
||||
db_ptr = (CHAN *)args.usr;
|
||||
pDB = (CHAN *)args.usr;
|
||||
|
||||
/* Copy value returned into user variable */
|
||||
value_ptr = getPtrToValue(
|
||||
(union db_access_val *)args.dbr, db_ptr->get_type);
|
||||
nbytes = db_ptr->size * db_ptr->count;
|
||||
bcopy(value_ptr, db_ptr->var, nbytes);
|
||||
pVal = getPtrToValue((union db_access_val *)args.dbr, pDB->get_type);
|
||||
nbytes = pDB->size * pDB->count;
|
||||
bcopy(pVal, pDB->var, nbytes);
|
||||
|
||||
/* Copy status & severity */
|
||||
dbr_sts_ptr = (struct dbr_sts_char *)args.dbr;
|
||||
db_ptr->status = dbr_sts_ptr->status;
|
||||
db_ptr->severity = dbr_sts_ptr->severity;
|
||||
pDB->status = dbr_sts_ptr->status;
|
||||
pDB->severity = dbr_sts_ptr->severity;
|
||||
|
||||
/* Set get complete flag */
|
||||
db_ptr->get_complete = TRUE;
|
||||
pDB->get_complete = TRUE;
|
||||
|
||||
/* Wake up each state set that is waiting for event processing) */
|
||||
sp_ptr = db_ptr->sprog; /* State program that owns this db entry */
|
||||
seq_efSet(sp_ptr, 0, db_ptr->index + 1);
|
||||
pSP = pDB->sprog; /* State program that owns this db entry */
|
||||
seq_efSet(pSP, 0, pDB->index + 1);
|
||||
|
||||
/* If syncronous pvGet then notify pending state set */
|
||||
if (!sp_ptr->async_flag)
|
||||
semGive(db_ptr->getSemId);
|
||||
if (!pSP->async_flag)
|
||||
semGive(pDB->getSemId);
|
||||
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Flush requests */
|
||||
@@ -303,92 +325,100 @@ VOID seq_pvFlush()
|
||||
ca_flush_io();
|
||||
}
|
||||
|
||||
/* Put DB value (uses channel access) */
|
||||
seq_pvPut(sp_ptr, ss_ptr, db_ptr)
|
||||
SPROG *sp_ptr; /* ptr to state program */
|
||||
SSCB *ss_ptr; /* ptr to current state set */
|
||||
CHAN *db_ptr; /* ptr to channel struct */
|
||||
/*
|
||||
* seq_pvPut() - Put DB value (uses channel access).
|
||||
*/
|
||||
seq_pvPut(pSP, pSS, pDB)
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
SSCB *pSS; /* ptr to current state set */
|
||||
CHAN *pDB; /* ptr to channel struct */
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!db_ptr->connected)
|
||||
if (!pDB->connected)
|
||||
return ECA_DISCONN;
|
||||
|
||||
status = ca_array_put(db_ptr->put_type, db_ptr->count,
|
||||
db_ptr->chid, db_ptr->var);
|
||||
status = ca_array_put(pDB->put_type, pDB->count,
|
||||
pDB->chid, pDB->var);
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
seq_log(sp_ptr, "pvPut on \"%s\" failed (%d)\n",
|
||||
db_ptr->db_name, status);
|
||||
seq_log(sp_ptr, " put_type=%d\n", db_ptr->put_type);
|
||||
seq_log(sp_ptr, " size=%d, count=%d\n", db_ptr->size, db_ptr->count);
|
||||
seq_log(pSP, "pvPut on \"%s\" failed (%d)\n",
|
||||
pDB->db_name, status);
|
||||
seq_log(pSP, " put_type=%d\n", pDB->put_type);
|
||||
seq_log(pSP, " size=%d, count=%d\n", pDB->size, pDB->count);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
/* Initiate a monitor on a channel */
|
||||
seq_pvMonitor(sp_ptr, ss_ptr, db_ptr)
|
||||
SPROG *sp_ptr; /* ptr to state program */
|
||||
SSCB *ss_ptr; /* ptr to current state set */
|
||||
CHAN *db_ptr; /* ptr to channel struct */
|
||||
/*
|
||||
* seq_pvMonitor() - Initiate a monitor on a channel.
|
||||
*/
|
||||
seq_pvMonitor(pSP, pSS, pDB)
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
SSCB *pSS; /* ptr to current state set */
|
||||
CHAN *pDB; /* ptr to channel struct */
|
||||
{
|
||||
int status;
|
||||
extern seq_event_handler();
|
||||
extern VOID seq_event_handler();
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("monitor \"%s\"\n", db_ptr->db_name);
|
||||
printf("monitor \"%s\"\n", pDB->db_name);
|
||||
#endif DEBUG
|
||||
|
||||
if (db_ptr->monitored)
|
||||
return -1;
|
||||
if (pDB->monitored)
|
||||
return;
|
||||
|
||||
status = ca_add_array_event(
|
||||
db_ptr->get_type, /* requested type */
|
||||
db_ptr->count, /* element count */
|
||||
db_ptr->chid, /* chid */
|
||||
pDB->get_type, /* requested type */
|
||||
pDB->count, /* element count */
|
||||
pDB->chid, /* chid */
|
||||
seq_event_handler, /* function to call */
|
||||
db_ptr, /* user arg (db struct) */
|
||||
db_ptr->delta, /* pos. delta value */
|
||||
db_ptr->delta, /* neg. delta value */
|
||||
db_ptr->timeout, /* timeout */
|
||||
&db_ptr->evid); /* where to put event id */
|
||||
pDB, /* user arg (db struct) */
|
||||
pDB->delta, /* pos. delta value */
|
||||
pDB->delta, /* neg. delta value */
|
||||
pDB->timeout, /* timeout */
|
||||
&pDB->evid); /* where to put event id */
|
||||
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
SEVCHK(status, "ca_add_array_event");
|
||||
ca_task_exit(); /* this is serious */
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
ca_flush_io();
|
||||
|
||||
db_ptr->monitored = TRUE;
|
||||
return 0;
|
||||
pDB->monitored = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Cancel a monitor */
|
||||
seq_pvStopMonitor(sp_ptr, ss_ptr, db_ptr)
|
||||
SPROG *sp_ptr; /* ptr to state program */
|
||||
SSCB *ss_ptr; /* ptr to current state set */
|
||||
CHAN *db_ptr; /* ptr to channel struct */
|
||||
/*
|
||||
* seq_pvStopMonitor() - Cancel a monitor
|
||||
*/
|
||||
seq_pvStopMonitor(pSP, pSS, pDB)
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
SSCB *pSS; /* ptr to current state set */
|
||||
CHAN *pDB; /* ptr to channel struct */
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!db_ptr->monitored)
|
||||
if (!pDB->monitored)
|
||||
return -1;
|
||||
|
||||
status = ca_clear_event(db_ptr->evid);
|
||||
status = ca_clear_event(pDB->evid);
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
SEVCHK(status, "ca_clear_event");
|
||||
return status;
|
||||
}
|
||||
|
||||
db_ptr->monitored = FALSE;
|
||||
pDB->monitored = FALSE;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Given ptr to value structure & type, return ptr to value */
|
||||
/*
|
||||
* getPtr() - Given ptr to value structure & type, return ptr to value.
|
||||
*/
|
||||
LOCAL void *getPtrToValue(pBuf, dbrType)
|
||||
union db_access_val *pBuf;
|
||||
chtype dbrType;
|
||||
|
||||
@@ -5,8 +5,12 @@
|
||||
|
||||
$Id$
|
||||
DESCRIPTION: Macro routines for Sequencer.
|
||||
The macro table contains name & value pairs. These are both pointers
|
||||
to strings.
|
||||
|
||||
ENVIRONMENT: VxWorks
|
||||
|
||||
HISTORY:
|
||||
***************************************************************************/
|
||||
#include "seq.h"
|
||||
|
||||
@@ -27,20 +31,25 @@ LOCAL MACRO *seqMacTblGet();
|
||||
|
||||
/*#define DEBUG*/
|
||||
|
||||
/* seqMacTblInit - initialize macro table */
|
||||
seqMacTblInit(mac_ptr)
|
||||
MACRO *mac_ptr;
|
||||
/*
|
||||
*seqMacTblInit - initialize macro the table.
|
||||
*/
|
||||
seqMacTblInit(pMac)
|
||||
MACRO *pMac;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < MAX_MACROS; i++, mac_ptr++)
|
||||
for (i = 0 ; i < MAX_MACROS; i++, pMac++)
|
||||
{
|
||||
mac_ptr->name = NULL;
|
||||
mac_ptr->value = NULL;
|
||||
pMac->name = NULL;
|
||||
pMac->value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* seqMacEval - substitute macro value into a string */
|
||||
/*
|
||||
*seqMacEval - substitute macro value into a string containing:
|
||||
* ....{mac_name}....
|
||||
*/
|
||||
seqMacEval(pInStr, pOutStr, maxChar, macTbl)
|
||||
char *pInStr;
|
||||
char *pOutStr;
|
||||
@@ -93,8 +102,9 @@ MACRO *macTbl;
|
||||
}
|
||||
*pOutStr == 0;
|
||||
}
|
||||
|
||||
/* seqMacValGet - given macro name, return pointer to its value */
|
||||
/*
|
||||
* seqMacValGet - given macro name, return pointer to its value.
|
||||
*/
|
||||
char *seqMacValGet(macName, macNameLth, macTbl)
|
||||
char *macName;
|
||||
int macNameLth;
|
||||
@@ -116,7 +126,8 @@ MACRO *macTbl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return number of characters in a macro name */
|
||||
/*
|
||||
* macNameLth() - Return number of characters in a macro name */
|
||||
LOCAL int macNameLth(pstr)
|
||||
char *pstr;
|
||||
{
|
||||
@@ -130,14 +141,15 @@ char *pstr;
|
||||
}
|
||||
return nchar;
|
||||
}
|
||||
/* seqMacParse - parse the macro definition string and build
|
||||
the macro table (name/value pairs). Returns number of macros parsed.
|
||||
Assumes the table may already contain entries (values may be changed).
|
||||
String for name and value are allocated dynamically from pool.
|
||||
*/
|
||||
int seqMacParse(pMacStr, sp_ptr)
|
||||
/*
|
||||
* seqMacParse - parse the macro definition string and build
|
||||
* the macro table (name/value pairs). Returns number of macros parsed.
|
||||
* Assumes the table may already contain entries (values may be changed).
|
||||
* String for name and value are allocated dynamically from pool.
|
||||
*/
|
||||
int seqMacParse(pMacStr, pSP)
|
||||
char *pMacStr; /* macro definition string */
|
||||
SPROG *sp_ptr;
|
||||
SPROG *pSP;
|
||||
{
|
||||
int nMac, nChar;
|
||||
char *skipBlanks();
|
||||
@@ -145,7 +157,7 @@ SPROG *sp_ptr;
|
||||
MACRO *pMacTbl; /* macro tbl entry */
|
||||
char *name, *value;
|
||||
|
||||
macTbl = sp_ptr->mac_ptr;
|
||||
macTbl = pSP->mac_ptr;
|
||||
for ( ;; )
|
||||
{
|
||||
/* Skip blanks */
|
||||
@@ -156,7 +168,7 @@ SPROG *sp_ptr;
|
||||
nChar = seqMacParseName(pMacStr);
|
||||
if (nChar == 0)
|
||||
break; /* finished or error */
|
||||
name = seqAlloc(sp_ptr, nChar+1);
|
||||
name = seqAlloc(pSP, nChar+1);
|
||||
if (name == NULL)
|
||||
break;
|
||||
bcopy(pMacStr, name, nChar);
|
||||
@@ -190,7 +202,7 @@ SPROG *sp_ptr;
|
||||
nChar = seqMacParseValue(pMacStr);
|
||||
if (nChar == 0)
|
||||
break;
|
||||
value = seqAlloc(sp_ptr, nChar+1);
|
||||
value = seqAlloc(pSP, nChar+1);
|
||||
if (value == NULL)
|
||||
break;
|
||||
bcopy(pMacStr, value, nChar);
|
||||
@@ -214,7 +226,9 @@ SPROG *sp_ptr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* seqMacParseName() - Parse a macro name from the input string.
|
||||
*/
|
||||
LOCAL int seqMacParseName(pStr)
|
||||
char *pStr;
|
||||
{
|
||||
@@ -235,7 +249,9 @@ char *pStr;
|
||||
return nChar;
|
||||
}
|
||||
|
||||
LOCAL int seqMacParseValue(pStr)
|
||||
/*
|
||||
* seqMacParseValue() - Parse a macro value from the input string.
|
||||
*/LOCAL int seqMacParseValue(pStr)
|
||||
char *pStr;
|
||||
{
|
||||
int nChar;
|
||||
@@ -258,8 +274,10 @@ char *pChar;
|
||||
return pChar;
|
||||
}
|
||||
|
||||
/* seqMacTblGet - find a match for the specified name, otherwise
|
||||
return an empty slot in macro table */
|
||||
/*
|
||||
* seqMacTblGet - find a match for the specified name, otherwise
|
||||
* return an empty slot in macro table.
|
||||
*/
|
||||
LOCAL MACRO *seqMacTblGet(name, macTbl)
|
||||
char *name; /* macro name */
|
||||
MACRO *macTbl;
|
||||
|
||||
@@ -13,13 +13,16 @@
|
||||
HISTORY:
|
||||
23apr91,ajk Fixed problem with state program invoking the sequencer.
|
||||
01jul91,ajk Added ANSI functional prototypes.
|
||||
05jul91,ajk Changed semCreate() in three places to semBCreate() or
|
||||
semMCreate(). Modified semTake() second param. to WAIT_FOREVER.
|
||||
05jul91,ajk Changed semCreate() in three places to semBCreate.
|
||||
Modified semTake() second param. to WAIT_FOREVER.
|
||||
These provide VX5.0 compatability.
|
||||
16aug91,ajk Improved "magic number" error message.
|
||||
25oct91,ajk Code to create semaphores "ss_ptr->getSemId" was left out.
|
||||
25oct91,ajk Code to create semaphores "pSS->getSemId" was left out.
|
||||
Added this code to init_sscb().
|
||||
25nov91,ajk Removed obsolete seqLog() code dealing with global locking.
|
||||
04dec91,ajk Implemented state program linked list, eliminating need for
|
||||
task variables.
|
||||
11dec91,ajk Cleaned up comments.
|
||||
***************************************************************************/
|
||||
/*#define DEBUG 1*/
|
||||
|
||||
@@ -44,39 +47,42 @@ LOCAL VOID seq_logInit();
|
||||
|
||||
#define SCRATCH_SIZE (MAX_MACROS*(MAX_STRING_SIZE+1)*12)
|
||||
|
||||
/*#define DEBUG*/
|
||||
|
||||
/* The following variable points to the area allocated for the
|
||||
parent state program and its corresponding state sets.
|
||||
It is declared a "task variable" and is shared by only these
|
||||
tasks.
|
||||
It is also used as a flag to indicate that the "taskDeleteHookAdd()"
|
||||
/* The following variable is a flag to indicate that the "taskDeleteHookAdd()"
|
||||
routine has been called (we only want to do that once after VxWorks boots).
|
||||
*/
|
||||
SPROG *seq_task_ptr = NULL;
|
||||
int seqDeleteHookAdded = FALSE;
|
||||
|
||||
/* User-callable routine to initiate a state program */
|
||||
int seq(sp_ptr_orig, macro_def, stack_size)
|
||||
SPROG *sp_ptr_orig; /* ptr to original state program table */
|
||||
char *macro_def; /* macro def'n string */
|
||||
int stack_size; /* stack size */
|
||||
/*
|
||||
* seq: User-callable routine to initiate a state program.
|
||||
* Usage: seq(<pSP>, <macros string>, <stack size>)
|
||||
* pSP is the ptr to the state program structure.
|
||||
* Example: seq(&myprog, "logfile=mylog", 0)
|
||||
* When called from the shell, the 2nd & 3rd parameters are optional.
|
||||
*
|
||||
* Creates the initial state program task and returns its task id.
|
||||
* Most initialization is performed here.
|
||||
*/
|
||||
int seq(pSP_orig, macro_def, stack_size)
|
||||
SPROG *pSP_orig; /* ptr to original state program table */
|
||||
char *macro_def; /* optional macro def'n string */
|
||||
int stack_size; /* optional stack size (bytes) */
|
||||
{
|
||||
int status;
|
||||
extern sequencer(), sprog_delete();
|
||||
int tid;
|
||||
extern sequencer(); /* Sequencer task entry point */
|
||||
extern sprog_delete(); /* Task delete routine */
|
||||
extern char *seqVersion;
|
||||
SPROG *sp_ptr, *alloc_task_area();
|
||||
extern SPROG *seq_task_ptr;
|
||||
SPROG *pSP, *alloc_task_area();
|
||||
char *seqMacValGet(), *pname, *pvalue, *ptask_name;
|
||||
|
||||
/* If no parameters specified, print version info. */
|
||||
if (sp_ptr_orig == 0)
|
||||
if (pSP_orig == 0)
|
||||
{
|
||||
printf("%s\n", seqVersion);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for correct state program format */
|
||||
if (sp_ptr_orig->magic != MAGIC)
|
||||
if (pSP_orig->magic != MAGIC)
|
||||
{ /* Oops */
|
||||
logMsg("Illegal magic number in state program.\n");
|
||||
logMsg(" - Possible mismatch between SNC & SEQ versions\n");
|
||||
@@ -85,44 +91,44 @@ int stack_size; /* stack size */
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
print_sp_info(sp_ptr_orig);
|
||||
print_sp_info(pSP_orig);
|
||||
#endif DEBUG
|
||||
|
||||
/* Specify a routine to run at task delete */
|
||||
if (seq_task_ptr == NULL)
|
||||
if (!seqDeleteHookAdded)
|
||||
{
|
||||
taskDeleteHookAdd(sprog_delete);
|
||||
seq_task_ptr = (SPROG *)ERROR;
|
||||
seqDeleteHookAdded = TRUE;
|
||||
}
|
||||
|
||||
/* Allocate a contiguous space for all dynamic structures */
|
||||
sp_ptr = alloc_task_area(sp_ptr_orig);
|
||||
pSP = alloc_task_area(pSP_orig);
|
||||
|
||||
/* Make a private copy of original structures (but change pointers!) */
|
||||
if (sp_ptr_orig->reent_flag)
|
||||
copy_sprog(sp_ptr_orig, sp_ptr);
|
||||
if (pSP_orig->reent_flag)
|
||||
copy_sprog(pSP_orig, pSP);
|
||||
|
||||
/* Initialize state program block */
|
||||
init_sprog(sp_ptr);
|
||||
init_sprog(pSP);
|
||||
|
||||
/* Initialize state set control blocks */
|
||||
init_sscb(sp_ptr);
|
||||
init_sscb(pSP);
|
||||
|
||||
/* Initialize the macro definition table */
|
||||
seqMacTblInit(sp_ptr->mac_ptr); /* Init macro table */
|
||||
seqMacTblInit(pSP->mac_ptr); /* Init macro table */
|
||||
|
||||
/* Parse the macro definitions from the "program" statement */
|
||||
seqMacParse(sp_ptr->params, sp_ptr);
|
||||
seqMacParse(pSP->params, pSP);
|
||||
|
||||
/* Parse the macro definitions from the command line */
|
||||
seqMacParse(macro_def, sp_ptr);
|
||||
seqMacParse(macro_def, pSP);
|
||||
|
||||
/* Initialize sequencer logging */
|
||||
seq_logInit(sp_ptr);
|
||||
seq_logInit(pSP);
|
||||
|
||||
/* Specify stack size */
|
||||
pname = "stack";
|
||||
pvalue = seqMacValGet(pname, strlen(pname), sp_ptr->mac_ptr);
|
||||
pvalue = seqMacValGet(pname, strlen(pname), pSP->mac_ptr);
|
||||
if (pvalue != NULL && strlen(pvalue) > 0)
|
||||
{
|
||||
sscanf(pvalue, "%d", &stack_size);
|
||||
@@ -132,84 +138,52 @@ int stack_size; /* stack size */
|
||||
|
||||
/* Specify task name */
|
||||
pname = "name";
|
||||
pvalue = seqMacValGet(pname, strlen(pname), sp_ptr->mac_ptr);
|
||||
pvalue = seqMacValGet(pname, strlen(pname), pSP->mac_ptr);
|
||||
if (pvalue != NULL && strlen(pvalue) > 0)
|
||||
ptask_name = pvalue;
|
||||
else
|
||||
ptask_name = sp_ptr->name;
|
||||
ptask_name = pSP->name;
|
||||
|
||||
/* Spawn the sequencer main task */
|
||||
seq_log(sp_ptr, "Spawning state program \"%s\", task name = \"%s\"\n",
|
||||
sp_ptr->name, ptask_name);
|
||||
/* Spawn the initial sequencer task */
|
||||
tid = taskSpawn(ptask_name, SPAWN_PRIORITY, SPAWN_OPTIONS,
|
||||
stack_size, sequencer, pSP, stack_size, ptask_name);
|
||||
|
||||
status = taskSpawn(ptask_name, SPAWN_PRIORITY, SPAWN_OPTIONS,
|
||||
stack_size, sequencer, sp_ptr, stack_size, ptask_name);
|
||||
seq_log(sp_ptr, " Task id = %d = 0x%x\n", status, status);
|
||||
seq_log(pSP, "Spawning state program \"%s\", task name = \"%s\"\n",
|
||||
pSP->name, ptask_name);
|
||||
seq_log(pSP, " Task id = %d = 0x%x\n", tid, tid);
|
||||
|
||||
return status;
|
||||
return tid;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
print_sp_info(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
{
|
||||
int nss, nstates;
|
||||
STATE *st_ptr;
|
||||
SSCB *ss_ptr;
|
||||
|
||||
printf("State Program: \"%s\"\n", sp_ptr->name);
|
||||
printf(" sp_ptr=%d=0x%x\n", sp_ptr, sp_ptr);
|
||||
printf(" sp_ptr=%d=0x%x\n", sp_ptr, sp_ptr);
|
||||
printf(" task id=%d=0x%x\n", sp_ptr->task_id, sp_ptr->task_id);
|
||||
printf(" task pri=%d\n", sp_ptr->task_priority);
|
||||
printf(" number of state sets=%d\n", sp_ptr->nss);
|
||||
printf(" number of channels=%d\n", sp_ptr->nchan);
|
||||
printf(" async flag=%d, debug flag=%d, reent flag=%d\n",
|
||||
sp_ptr->async_flag, sp_ptr->debug_flag, sp_ptr->reent_flag);
|
||||
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
{
|
||||
printf(" State Set: \"%s\"\n", ss_ptr->name);
|
||||
printf(" Num states=\"%d\"\n", ss_ptr->num_states);
|
||||
printf(" State names:\n");
|
||||
st_ptr = ss_ptr->states;
|
||||
for (nstates = 0; nstates < ss_ptr->num_states; nstates++)
|
||||
{
|
||||
printf(" \"%s\"\n", st_ptr->name);
|
||||
st_ptr++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif DEBUG
|
||||
/* Allocate a single block for all dynamic structures. The size allocated
|
||||
will depend on whether or not the reentrant flag is set.
|
||||
The pointer to the allocated area is saved for task delete hook routine.
|
||||
*/
|
||||
LOCAL SPROG *alloc_task_area(sp_ptr_orig)
|
||||
SPROG *sp_ptr_orig; /* original state program structure */
|
||||
/*
|
||||
* ALLOC_TASK_AREA
|
||||
* Allocate a single block for all dynamic structures. The size allocated
|
||||
* will depend on whether or not the reentrant flag is set.
|
||||
* The pointer to the allocated area is saved for task delete hook routine.
|
||||
*/
|
||||
LOCAL SPROG *alloc_task_area(pSP_orig)
|
||||
SPROG *pSP_orig; /* original state program structure */
|
||||
{
|
||||
int size, nss, nstates, nchannels, user_size,
|
||||
prog_size, ss_size, state_size, chan_size, mac_size, scr_size;
|
||||
SPROG *sp_ptr_new; /* ptr to new state program struct */
|
||||
SPROG *pSP_new; /* ptr to new state program struct */
|
||||
char *dyn_ptr, *dyn_ptr_start; /* ptr to allocated area */
|
||||
|
||||
nss = sp_ptr_orig->nss;
|
||||
nstates = sp_ptr_orig->nstates;
|
||||
nchannels = sp_ptr_orig->nchan;
|
||||
nss = pSP_orig->nss;
|
||||
nstates = pSP_orig->nstates;
|
||||
nchannels = pSP_orig->nchan;
|
||||
|
||||
/* Calc. # of bytes to allocate for all structures */
|
||||
prog_size = sizeof(SPROG);
|
||||
ss_size = nss*sizeof(SSCB);
|
||||
state_size = nstates*sizeof(STATE);
|
||||
chan_size = nchannels*sizeof(CHAN);
|
||||
user_size = sp_ptr_orig->user_size;
|
||||
user_size = pSP_orig->user_size;
|
||||
mac_size = MAX_MACROS*sizeof(MACRO);
|
||||
scr_size = SCRATCH_SIZE;
|
||||
|
||||
/* Total # bytes to allocate */
|
||||
if (sp_ptr_orig->reent_flag)
|
||||
if (pSP_orig->reent_flag)
|
||||
{
|
||||
size = prog_size + ss_size + state_size +
|
||||
chan_size + user_size + mac_size + scr_size;
|
||||
@@ -234,212 +208,265 @@ SPROG *sp_ptr_orig; /* original state program structure */
|
||||
#endif DEBUG
|
||||
|
||||
/* Set ptrs in the PROG structure */
|
||||
if (sp_ptr_orig->reent_flag)
|
||||
if (pSP_orig->reent_flag)
|
||||
{ /* Reentry flag set: create a new structures */
|
||||
sp_ptr_new = (SPROG *)dyn_ptr;
|
||||
pSP_new = (SPROG *)dyn_ptr;
|
||||
|
||||
/* Copy the SPROG struct contents */
|
||||
*sp_ptr_new = *sp_ptr_orig;
|
||||
*pSP_new = *pSP_orig;
|
||||
|
||||
/* Allocate space for the other structures */
|
||||
dyn_ptr += prog_size;
|
||||
sp_ptr_new->sscb = (SSCB *)dyn_ptr;
|
||||
pSP_new->sscb = (SSCB *)dyn_ptr;
|
||||
dyn_ptr += ss_size;
|
||||
sp_ptr_new->states = (STATE *)dyn_ptr;
|
||||
pSP_new->states = (STATE *)dyn_ptr;
|
||||
dyn_ptr += state_size;
|
||||
sp_ptr_new->channels = (CHAN *)dyn_ptr;
|
||||
pSP_new->channels = (CHAN *)dyn_ptr;
|
||||
dyn_ptr += chan_size;
|
||||
sp_ptr_new->user_area = (char *)dyn_ptr;
|
||||
pSP_new->user_area = (char *)dyn_ptr;
|
||||
dyn_ptr += user_size;
|
||||
}
|
||||
else
|
||||
{ /* Reentry flag not set: keep original structures */
|
||||
sp_ptr_new = sp_ptr_orig;
|
||||
pSP_new = pSP_orig;
|
||||
}
|
||||
/* Create dynamic structures for macros and scratch area */
|
||||
sp_ptr_new->mac_ptr = (MACRO *)dyn_ptr;
|
||||
pSP_new->mac_ptr = (MACRO *)dyn_ptr;
|
||||
dyn_ptr += mac_size;
|
||||
sp_ptr_new->scr_ptr = (char *)dyn_ptr;
|
||||
sp_ptr_new->scr_nleft = scr_size;
|
||||
pSP_new->scr_ptr = (char *)dyn_ptr;
|
||||
pSP_new->scr_nleft = scr_size;
|
||||
|
||||
/* Save ptr to allocated area so we can free it at task delete */
|
||||
sp_ptr_new->dyn_ptr = dyn_ptr_start;
|
||||
pSP_new->dyn_ptr = dyn_ptr_start;
|
||||
|
||||
return sp_ptr_new;
|
||||
return pSP_new;
|
||||
}
|
||||
/* Copy the SSCB, STATE, and CHAN structures into this task.
|
||||
Note: we have to change the pointers in the SPROG struct, user variables,
|
||||
and all SSCB structs */
|
||||
LOCAL VOID copy_sprog(sp_ptr_orig, sp_ptr)
|
||||
SPROG *sp_ptr_orig; /* original ptr to program struct */
|
||||
SPROG *sp_ptr; /* new ptr */
|
||||
/*
|
||||
* Copy the SSCB, STATE, and CHAN structures into this task's dynamic structures.
|
||||
* Note: we have to change some pointers in the SPROG struct, user variables,
|
||||
* and all SSCB structs.
|
||||
*/
|
||||
LOCAL VOID copy_sprog(pSP_orig, pSP)
|
||||
SPROG *pSP_orig; /* original ptr to program struct */
|
||||
SPROG *pSP; /* new ptr */
|
||||
{
|
||||
SSCB *ss_ptr, *ss_ptr_orig;
|
||||
STATE *st_ptr, *st_ptr_orig;
|
||||
CHAN *db_ptr, *db_ptr_orig;
|
||||
SSCB *pSS, *pSS_orig;
|
||||
STATE *pST, *pST_orig;
|
||||
CHAN *pDB, *pDB_orig;
|
||||
int nss, nstates, nchan;
|
||||
char *var_ptr;
|
||||
|
||||
/* Ptr to 1-st SSCB in original SPROG */
|
||||
ss_ptr_orig = sp_ptr_orig->sscb;
|
||||
pSS_orig = pSP_orig->sscb;
|
||||
|
||||
/* Ptr to 1-st SSCB in new SPROG */
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
pSS = pSP->sscb;
|
||||
|
||||
/* Copy structures for each state set */
|
||||
st_ptr = sp_ptr->states;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++)
|
||||
pST = pSP->states;
|
||||
for (nss = 0; nss < pSP->nss; nss++)
|
||||
{
|
||||
*ss_ptr = *ss_ptr_orig; /* copy SSCB */
|
||||
ss_ptr->states = st_ptr; /* new ptr to 1-st STATE */
|
||||
st_ptr_orig = ss_ptr_orig->states;
|
||||
for (nstates = 0; nstates < ss_ptr->num_states; nstates++)
|
||||
*pSS = *pSS_orig; /* copy SSCB */
|
||||
pSS->states = pST; /* new ptr to 1-st STATE */
|
||||
pST_orig = pSS_orig->states;
|
||||
for (nstates = 0; nstates < pSS->num_states; nstates++)
|
||||
{
|
||||
*st_ptr = *st_ptr_orig; /* copy STATE struct */
|
||||
st_ptr++;
|
||||
st_ptr_orig++;
|
||||
*pST = *pST_orig; /* copy STATE struct */
|
||||
pST++;
|
||||
pST_orig++;
|
||||
}
|
||||
ss_ptr++;
|
||||
ss_ptr_orig++;
|
||||
pSS++;
|
||||
pSS_orig++;
|
||||
}
|
||||
|
||||
/* Copy database channel structures */
|
||||
db_ptr = sp_ptr->channels;
|
||||
db_ptr_orig = sp_ptr_orig->channels;
|
||||
var_ptr = sp_ptr->user_area;
|
||||
for (nchan = 0; nchan < sp_ptr->nchan; nchan++)
|
||||
pDB = pSP->channels;
|
||||
pDB_orig = pSP_orig->channels;
|
||||
var_ptr = pSP->user_area;
|
||||
for (nchan = 0; nchan < pSP->nchan; nchan++)
|
||||
{
|
||||
*db_ptr = *db_ptr_orig;
|
||||
*pDB = *pDB_orig;
|
||||
|
||||
/* Reset ptr to SPROG structure */
|
||||
db_ptr->sprog = sp_ptr;
|
||||
pDB->sprog = pSP;
|
||||
|
||||
/* Convert offset to address of the user variable */
|
||||
db_ptr->var += (int)var_ptr;
|
||||
pDB->var += (int)var_ptr;
|
||||
|
||||
db_ptr++;
|
||||
db_ptr_orig++;
|
||||
pDB++;
|
||||
pDB_orig++;
|
||||
}
|
||||
|
||||
/* Note: user area is not copied; it should be all zeros */
|
||||
|
||||
return;
|
||||
}
|
||||
/* Initialize state program block */
|
||||
LOCAL VOID init_sprog(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
/*
|
||||
* Initialize the state program block
|
||||
*/
|
||||
LOCAL VOID init_sprog(pSP)
|
||||
SPROG *pSP;
|
||||
{
|
||||
/* Semaphore for resource locking on CA events */
|
||||
sp_ptr->caSemId = semMCreate(SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
|
||||
pSP->caSemId = semBCreate(SEM_Q_FIFO, SEM_FULL);
|
||||
if (pSP->caSemId == NULL)
|
||||
{
|
||||
logMsg("can't create caSemId\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sp_ptr->task_is_deleted = FALSE;
|
||||
sp_ptr->logFd = 0;
|
||||
pSP->task_is_deleted = FALSE;
|
||||
pSP->logFd = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize state set control blocks */
|
||||
LOCAL VOID init_sscb(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
/*
|
||||
* Initialize the state set control blocks
|
||||
*/
|
||||
LOCAL VOID init_sscb(pSP)
|
||||
SPROG *pSP;
|
||||
{
|
||||
SSCB *ss_ptr;
|
||||
SSCB *pSS;
|
||||
int nss, i;
|
||||
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
pSS = pSP->sscb;
|
||||
for (nss = 0; nss < pSP->nss; nss++, pSS++)
|
||||
{
|
||||
ss_ptr->task_id = 0;
|
||||
pSS->task_id = 0;
|
||||
/* Create a binary semaphore for synchronizing events in a SS */
|
||||
ss_ptr->syncSemId = semBCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE);
|
||||
pSS->syncSemId = semBCreate(SEM_Q_FIFO, SEM_FULL);
|
||||
if (pSS->syncSemId == NULL)
|
||||
{
|
||||
logMsg("can't create syncSemId\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a binary semaphore for pvGet() synconizing */
|
||||
if (!sp_ptr->async_flag)
|
||||
ss_ptr->getSemId =
|
||||
semBCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE);
|
||||
if (!pSP->async_flag)
|
||||
{
|
||||
pSS->getSemId =
|
||||
semBCreate(SEM_Q_FIFO, SEM_FULL);
|
||||
if (pSS->getSemId == NULL)
|
||||
{
|
||||
logMsg("can't create getSemId\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ss_ptr->current_state = 0; /* initial state */
|
||||
ss_ptr->next_state = 0;
|
||||
ss_ptr->action_complete = TRUE;
|
||||
}
|
||||
|
||||
pSS->current_state = 0; /* initial state */
|
||||
pSS->next_state = 0;
|
||||
pSS->action_complete = TRUE;
|
||||
for (i = 0; i < NWRDS; i++)
|
||||
ss_ptr->events[i] = 0; /* clear events */
|
||||
pSS->events[i] = 0; /* clear events */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate memory from scratch area (always round up to even no. bytes) */
|
||||
char *seqAlloc(sp_ptr, nChar)
|
||||
SPROG *sp_ptr;
|
||||
/*
|
||||
* seqAlloc: Allocate memory from the program scratch area.
|
||||
* Always round up to even no. bytes.
|
||||
*/
|
||||
char *seqAlloc(pSP, nChar)
|
||||
SPROG *pSP;
|
||||
int nChar;
|
||||
{
|
||||
char *pStr;
|
||||
|
||||
pStr = sp_ptr->scr_ptr;
|
||||
pStr = pSP->scr_ptr;
|
||||
/* round to even no. bytes */
|
||||
if ((nChar & 1) != 0)
|
||||
nChar++;
|
||||
if (sp_ptr->scr_nleft >= nChar)
|
||||
if (pSP->scr_nleft >= nChar)
|
||||
{
|
||||
sp_ptr->scr_ptr += nChar;
|
||||
sp_ptr->scr_nleft -= nChar;
|
||||
pSP->scr_ptr += nChar;
|
||||
pSP->scr_nleft -= nChar;
|
||||
return pStr;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
/* Initialize logging */
|
||||
LOCAL VOID seq_logInit(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
/*
|
||||
* Initialize logging
|
||||
*/
|
||||
LOCAL VOID seq_logInit(pSP)
|
||||
SPROG *pSP;
|
||||
{
|
||||
char *pname, *pvalue, *seqMacValGet();
|
||||
int fd;
|
||||
|
||||
/* Create a logging resource locking semaphore */
|
||||
sp_ptr->logSemId = semMCreate(SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
|
||||
sp_ptr->logFd = ioGlobalStdGet(1); /* default fd is std out */
|
||||
pSP->logSemId = semBCreate(SEM_Q_FIFO, SEM_FULL);
|
||||
if (pSP->logSemId == NULL)
|
||||
{
|
||||
logMsg("can't create logSemId\n");
|
||||
return;
|
||||
}
|
||||
pSP->logFd = ioGlobalStdGet(1); /* default fd is std out */
|
||||
|
||||
/* Check for logfile spec. */
|
||||
pname = "logfile";
|
||||
pvalue = seqMacValGet(pname, strlen(pname), sp_ptr->mac_ptr);
|
||||
pvalue = seqMacValGet(pname, strlen(pname), pSP->mac_ptr);
|
||||
if (pvalue != NULL && strlen(pvalue) > 0)
|
||||
{ /* Create & open file for write only */
|
||||
delete(pvalue);
|
||||
fd = open(pvalue, O_CREAT | O_WRONLY, 0664);
|
||||
if (fd != ERROR)
|
||||
sp_ptr->logFd = fd;
|
||||
pSP->logFd = fd;
|
||||
printf("logfile=%s, fd=%d\n", pvalue, fd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Log a message to the console or a file with time of day and task id */
|
||||
/*
|
||||
* seqLog
|
||||
* Log a message to the console or a file with time of day and task id.
|
||||
* The format looks like "mytask 12/13/91 10:07:43: <user's message>".
|
||||
*/
|
||||
#include "tsDefs.h"
|
||||
VOID seq_log(sp_ptr, fmt, arg1, arg2, arg3, arg4, arg5, arg6)
|
||||
SPROG *sp_ptr;
|
||||
#define LOG_BFR_SIZE 200
|
||||
|
||||
VOID seq_log(pSP, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
|
||||
SPROG *pSP;
|
||||
char *fmt; /* format string */
|
||||
int arg1, arg2, arg3, arg4, arg5, arg6; /* arguments */
|
||||
int arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8; /* arguments */
|
||||
{
|
||||
int fd;
|
||||
int fd, count, status;
|
||||
TS_STAMP timeStamp;
|
||||
char timeBfr[28];
|
||||
char logBfr[LOG_BFR_SIZE], *pBfr;
|
||||
|
||||
pBfr = logBfr;
|
||||
|
||||
/* Enter taskname */
|
||||
count = sprintf(pBfr, "%s ", taskName(taskIdSelf()) );
|
||||
pBfr += count - 1;
|
||||
|
||||
/* Get time of day */
|
||||
tsLocalTime(&timeStamp); /* time stamp format */
|
||||
|
||||
/* Convert to mm/dd/yy hh:mm:ss.nano-sec */
|
||||
tsStampToText(&timeStamp, TS_TEXT_MMDDYY, timeBfr);
|
||||
/* Truncate the .nano-secs part */
|
||||
timeBfr[17] = 0;
|
||||
/* Convert to text format: "mm/dd/yy hh:mm:ss.nano-sec" */
|
||||
tsStampToText(&timeStamp, TS_TEXT_MMDDYY, pBfr);
|
||||
/* We're going to truncate the ".nano-sec" part */
|
||||
pBfr += 17;
|
||||
|
||||
/* Lock seq_log resource */
|
||||
semTake(sp_ptr->logSemId, WAIT_FOREVER);
|
||||
/* Insert ": " */
|
||||
*pBfr++ = ':';
|
||||
*pBfr++ = ' ';
|
||||
|
||||
/* Print the message: e.g. "10:23:28 T13: ...." */
|
||||
fd = sp_ptr->logFd;
|
||||
fdprintf(fd, "%s %s: ", taskName(taskIdSelf()), &timeBfr[9]);
|
||||
fdprintf(fd, fmt, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
/* Append the user's msg to the buffer */
|
||||
count = sprintf(pBfr, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
||||
pBfr += count - 1;
|
||||
|
||||
/* Unlock the resource */
|
||||
semGive(sp_ptr->logSemId);
|
||||
/* Write the msg */
|
||||
fd = pSP->logFd;
|
||||
count = pBfr - logBfr + 1;
|
||||
status = write(fd, logBfr, count);
|
||||
if (status != count)
|
||||
{
|
||||
logMsg("Log file error: fd=%d, status=%d\n", fd, status);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If NSF file then flush the buffer */
|
||||
/* If this is an NSF file flush the buffer */
|
||||
if (fd != ioGlobalStdGet(1) )
|
||||
{
|
||||
ioctl(fd, FIOSYNC);
|
||||
@@ -448,36 +475,46 @@ int arg1, arg2, arg3, arg4, arg5, arg6; /* arguments */
|
||||
return;
|
||||
}
|
||||
|
||||
/* seqLog() - State program interface to seq_log() */
|
||||
VOID seqLog(fmt, arg1, arg2, arg3, arg4, arg5, arg6)
|
||||
/*
|
||||
* seqLog() - State program interface to seq_log().
|
||||
* Does not require ptr to state program block.
|
||||
*/
|
||||
STATUS seqLog(fmt, arg1,arg2, arg3, arg4, arg5, arg6, arg7, arg8)
|
||||
char *fmt; /* format string */
|
||||
int arg1, arg2, arg3, arg4, arg5, arg6; /* arguments */
|
||||
int arg1,arg2, arg3, arg4, arg5, arg6, arg7, arg8; /* arguments */
|
||||
{
|
||||
extern SPROG *seq_task_ptr;
|
||||
SPROG *pSP, *seqFindProg();
|
||||
|
||||
if (seq_task_ptr == (SPROG *)ERROR)
|
||||
return;
|
||||
seq_log(seq_task_ptr, fmt, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
pSP = seqFindProg(taskIdSelf());
|
||||
if (pSP == NULL)
|
||||
return ERROR;
|
||||
|
||||
seq_log(pSP, fmt, arg1,arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* seq_flagGet: get the value of a flag ("-" -> FALSE; "+" -> TRUE) */
|
||||
BOOL seq_flagGet(sp_ptr, flag)
|
||||
SPROG *sp_ptr;
|
||||
/*
|
||||
* seq_flagGet: return the value of an option flag.
|
||||
* FALSE means "-" and TRUE means "+".
|
||||
*/
|
||||
BOOL seq_flagGet(pSP, flag)
|
||||
SPROG *pSP;
|
||||
char *flag; /* one of the snc flags as a strign (e.g. "a") */
|
||||
{
|
||||
switch (flag[0])
|
||||
{
|
||||
case 'a': return sp_ptr->async_flag;
|
||||
case 'c': return sp_ptr->conn_flag;
|
||||
case 'd': return sp_ptr->debug_flag;
|
||||
case 'r': return sp_ptr->reent_flag;
|
||||
case 'a': return pSP->async_flag;
|
||||
case 'c': return pSP->conn_flag;
|
||||
case 'd': return pSP->debug_flag;
|
||||
case 'r': return pSP->reent_flag;
|
||||
default: return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VX4
|
||||
/* Fake Vx5.0 semaphore creation */
|
||||
SEM_ID semMCreate(flags)
|
||||
#ifndef V5_vxWorks
|
||||
/*
|
||||
* Fake Vx5.0 binary semaphore creation.
|
||||
*/
|
||||
SEM_ID semBCreate(flags)
|
||||
int flags;
|
||||
{
|
||||
SEM_ID semId;
|
||||
@@ -487,13 +524,40 @@ int flags;
|
||||
semGive(semId);
|
||||
return(semId);
|
||||
}
|
||||
SEM_ID semBCreate(flags)
|
||||
int flags;
|
||||
#endif V5_vxWorks
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Debug only: print state program info. */
|
||||
print_sp_info(pSP)
|
||||
SPROG *pSP;
|
||||
{
|
||||
SEM_ID semId;
|
||||
int nss, nstates;
|
||||
STATE *pST;
|
||||
SSCB *pSS;
|
||||
|
||||
semId = semCreate();
|
||||
semInit(semId);
|
||||
return(semId);
|
||||
printf("State Program: \"%s\"\n", pSP->name);
|
||||
printf(" pSP=%d=0x%x\n", pSP, pSP);
|
||||
printf(" pSP=%d=0x%x\n", pSP, pSP);
|
||||
printf(" task id=%d=0x%x\n", pSP->task_id, pSP->task_id);
|
||||
printf(" task pri=%d\n", pSP->task_priority);
|
||||
printf(" number of state sets=%d\n", pSP->nss);
|
||||
printf(" number of channels=%d\n", pSP->nchan);
|
||||
printf(" async flag=%d, debug flag=%d, reent flag=%d\n",
|
||||
pSP->async_flag, pSP->debug_flag, pSP->reent_flag);
|
||||
|
||||
pSS = pSP->sscb;
|
||||
for (nss = 0; nss < pSP->nss; nss++, pSS++)
|
||||
{
|
||||
printf(" State Set: \"%s\"\n", pSS->name);
|
||||
printf(" Num states=\"%d\"\n", pSS->num_states);
|
||||
printf(" State names:\n");
|
||||
pST = pSS->states;
|
||||
for (nstates = 0; nstates < pSS->num_states; nstates++)
|
||||
{
|
||||
printf(" \"%s\"\n", pST->name);
|
||||
pST++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif VX4
|
||||
#endif DEBUG
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
25nov91,ajk Display task names(s) with id(s).
|
||||
Display logfile name and file descriptor.
|
||||
Moved wait_rtn() to top of loop.
|
||||
09dec91,ajk Modified to used state program linked list.
|
||||
Added option to display all programs when tid=0.
|
||||
19dec91,ajk Allow task name as well as task id.
|
||||
***************************************************************************/
|
||||
|
||||
/* #define DEBUG 1 */
|
||||
@@ -23,170 +26,164 @@
|
||||
int seqShow(int);
|
||||
int seqChanShow(int);
|
||||
LOCAL VOID wait_rtn();
|
||||
static void printValue(void *, int, int, int);
|
||||
static void printType(int);
|
||||
LOCAL VOID printValue(void *, int, int, int);
|
||||
LOCAL VOID printType(int);
|
||||
#else
|
||||
int seqShow();
|
||||
int seqChanShow();
|
||||
LOCAL VOID wait_rtn();
|
||||
static void printValue();
|
||||
static void printType();
|
||||
LOCAL VOID printValue();
|
||||
LOCAL VOID printType();
|
||||
#endif
|
||||
|
||||
/* Querry the sequencer for state information */
|
||||
/*
|
||||
* seqShow() - Querry the sequencer for state information.
|
||||
* If a non-zero task id is specified then print the information about
|
||||
* the state program, otherwise print a brief summary of all state programs
|
||||
*/
|
||||
int seqShow(tid)
|
||||
int tid;
|
||||
{
|
||||
extern SPROG *seq_task_ptr;
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
STATE *st_ptr;
|
||||
CHAN *db_ptr;
|
||||
int nss, nst, nch, status;
|
||||
SPROG *pSP;
|
||||
SSCB *pSS;
|
||||
STATE *pST;
|
||||
CHAN *pDB;
|
||||
int nss, nst, nch, status, n;
|
||||
float time;
|
||||
char file_name[100];
|
||||
extern SPROG *seqQryFind();
|
||||
|
||||
/* Info? */
|
||||
if (tid == 0)
|
||||
{
|
||||
printf("Usage: seqShow <task id>\n");
|
||||
tid = taskIdFigure(tid); /* convert (possible) name to id */
|
||||
pSP = seqQryFind(tid);
|
||||
if (pSP == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the seq_task_ptr (it's task variable) */
|
||||
sp_ptr = (SPROG *)taskVarGet(tid, &seq_task_ptr);
|
||||
|
||||
if (sp_ptr->magic != MAGIC)
|
||||
{
|
||||
printf("seqShow: wrong magic number\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Print info about state program */
|
||||
printf("State Program: \"%s\"\n", sp_ptr->name);
|
||||
printf("State Program: \"%s\"\n", pSP->name);
|
||||
printf(" Memory layout:\n");
|
||||
printf("\tsp_ptr=%d=0x%x\n", sp_ptr, sp_ptr);
|
||||
printf("\tdyn_ptr=%d=0x%x\n", sp_ptr->dyn_ptr, sp_ptr->dyn_ptr);
|
||||
printf("\tsscb=%d=0x%x\n", sp_ptr->sscb, sp_ptr->sscb);
|
||||
printf("\tstates=%d=0x%x\n", sp_ptr->states, sp_ptr->states);
|
||||
printf("\tuser_area=%d=0x%x\n", sp_ptr->user_area, sp_ptr->user_area);
|
||||
printf("\tuser_size=%d=0x%x\n", sp_ptr->user_size, sp_ptr->user_size);
|
||||
printf("\tmac_ptr=%d=0x%x\n", sp_ptr->mac_ptr, sp_ptr->mac_ptr);
|
||||
printf("\tscr_ptr=%d=0x%x\n", sp_ptr->scr_ptr, sp_ptr->scr_ptr);
|
||||
printf("\tscr_nleft=%d=0x%x\n\n", sp_ptr->scr_nleft, sp_ptr->scr_nleft);
|
||||
printf(" initial task id=%d=0x%x\n", sp_ptr->task_id, sp_ptr->task_id);
|
||||
printf(" task priority=%d\n", sp_ptr->task_priority);
|
||||
printf(" number of state sets=%d\n", sp_ptr->nss);
|
||||
printf(" number of channels=%d\n", sp_ptr->nchan);
|
||||
printf(" number of channels connected=%d\n", sp_ptr->conn_count);
|
||||
printf("\tpSP=%d=0x%x\n", pSP, pSP);
|
||||
printf("\tdyn_ptr=%d=0x%x\n", pSP->dyn_ptr, pSP->dyn_ptr);
|
||||
printf("\tsscb=%d=0x%x\n", pSP->sscb, pSP->sscb);
|
||||
printf("\tstates=%d=0x%x\n", pSP->states, pSP->states);
|
||||
printf("\tuser_area=%d=0x%x\n", pSP->user_area, pSP->user_area);
|
||||
printf("\tuser_size=%d=0x%x\n", pSP->user_size, pSP->user_size);
|
||||
printf("\tmac_ptr=%d=0x%x\n", pSP->mac_ptr, pSP->mac_ptr);
|
||||
printf("\tscr_ptr=%d=0x%x\n", pSP->scr_ptr, pSP->scr_ptr);
|
||||
printf("\tscr_nleft=%d=0x%x\n\n", pSP->scr_nleft, pSP->scr_nleft);
|
||||
printf(" initial task id=%d=0x%x\n", pSP->task_id, pSP->task_id);
|
||||
printf(" task priority=%d\n", pSP->task_priority);
|
||||
printf(" number of state sets=%d\n", pSP->nss);
|
||||
printf(" number of channels=%d\n", pSP->nchan);
|
||||
printf(" number of channels connected=%d\n", pSP->conn_count);
|
||||
printf(" async flag=%d, debug flag=%d, reent flag=%d, conn flag=%d\n",
|
||||
sp_ptr->async_flag, sp_ptr->debug_flag, sp_ptr->reent_flag,
|
||||
sp_ptr->conn_flag);
|
||||
printf(" log file fd=%d\n", sp_ptr->logFd);
|
||||
status = ioctl(sp_ptr->logFd, FIOGETNAME, file_name);
|
||||
pSP->async_flag, pSP->debug_flag, pSP->reent_flag,
|
||||
pSP->conn_flag);
|
||||
printf(" log file fd=%d\n", pSP->logFd);
|
||||
status = ioctl(pSP->logFd, FIOGETNAME, file_name);
|
||||
if (status != ERROR)
|
||||
printf(" log file name=\"%s\"\n", file_name);
|
||||
|
||||
printf("\n");
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
pSS = pSP->sscb;
|
||||
|
||||
/* Print state set info */
|
||||
for (nss = 0; nss < pSP->nss; nss++, pSS++)
|
||||
{
|
||||
wait_rtn();
|
||||
|
||||
printf(" State Set: \"%s\"\n", ss_ptr->name);
|
||||
printf(" State Set: \"%s\"\n", pSS->name);
|
||||
|
||||
printf(" task name=%s; ", taskName(ss_ptr->task_id));
|
||||
printf(" task name=%s; ", taskName(pSS->task_id));
|
||||
|
||||
printf(" id=%d=0x%x\n", ss_ptr->task_id, ss_ptr->task_id);
|
||||
printf(" id=%d=0x%x\n", pSS->task_id, pSS->task_id);
|
||||
|
||||
st_ptr = ss_ptr->states;
|
||||
printf(" First state = \"%s\"\n", ss_ptr->states->name);
|
||||
pST = pSS->states;
|
||||
printf(" First state = \"%s\"\n", pSS->states->name);
|
||||
|
||||
st_ptr = ss_ptr->states + ss_ptr->current_state;
|
||||
printf(" Current state = \"%s\"\n", st_ptr->name);
|
||||
pST = pSS->states + pSS->current_state;
|
||||
printf(" Current state = \"%s\"\n", pST->name);
|
||||
|
||||
st_ptr = ss_ptr->states + ss_ptr->prev_state;
|
||||
printf(" Previous state = \"%s\"\n", st_ptr->name);
|
||||
pST = pSS->states + pSS->prev_state;
|
||||
printf(" Previous state = \"%s\"\n", pST->name);
|
||||
|
||||
time = (tickGet() - ss_ptr->time)/60.0;
|
||||
printf("\tTime since state was entered = %.1f seconds)\n", time);
|
||||
time = pSS->time/60.0;
|
||||
printf("\tTime state was entered = %.1f seconds)\n", time);
|
||||
time = (tickGet() - pSS->time)/60.0;
|
||||
printf("\tElapsed time since state was entered = %.1f seconds)\n",
|
||||
time);
|
||||
|
||||
printf("\tNumber delays queued=%d\n", ss_ptr->ndelay);
|
||||
printf("\tNumber delays queued=%d\n", pSS->ndelay);
|
||||
for (n = 0; n < pSS->ndelay; n++)
|
||||
{
|
||||
time = pSS->timeout[n]/60.0;
|
||||
printf("\t\ttimeout[%d] = %.1f seconds\n", n, time);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Querry the sequencer for channel information */
|
||||
/*
|
||||
* seqChanQry() - Querry the sequencer for channel information.
|
||||
*/
|
||||
int seqChanShow(tid)
|
||||
int tid;
|
||||
{
|
||||
extern SPROG *seq_task_ptr;
|
||||
SPROG *sp_ptr;
|
||||
CHAN *db_ptr;
|
||||
SPROG *pSP;
|
||||
extern SPROG *seqQryFind();
|
||||
CHAN *pDB;
|
||||
int nch;
|
||||
float time;
|
||||
|
||||
/* Info? */
|
||||
if (tid == 0)
|
||||
{
|
||||
printf("Usage: seqChanShow <task id>\n");
|
||||
tid = taskIdFigure(tid); /* convert (possible) name to id */
|
||||
pSP = seqQryFind(tid);
|
||||
if (tid == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* seq_task_ptr is a task variable */
|
||||
sp_ptr = (SPROG *)taskVarGet(tid, &seq_task_ptr);
|
||||
pDB = pSP->channels;
|
||||
printf("State Program: \"%s\"\n", pSP->name);
|
||||
printf("Number of channels=%d\n", pSP->nchan);
|
||||
|
||||
if (sp_ptr->magic != MAGIC)
|
||||
for (nch = 0; nch < pSP->nchan; nch++, pDB++)
|
||||
{
|
||||
printf("seqChanQry: wrong magic number\n");
|
||||
return -1;
|
||||
}
|
||||
printf("\nChannel name: \"%s\"\n", pDB->db_name);
|
||||
printf(" Unexpanded name: \"%s\"\n", pDB->db_uname);
|
||||
printf(" Variable=%d=0x%x\n", pDB->var, pDB->var);
|
||||
printf(" Size=%d bytes\n", pDB->size);
|
||||
printf(" Count=%d\n", pDB->count);
|
||||
printType(pDB->put_type);
|
||||
printValue((void *)pDB->var, pDB->size, pDB->count,
|
||||
pDB->put_type);
|
||||
printf(" DB get request type=%d\n", pDB->get_type);
|
||||
printf(" DB put request type=%d\n", pDB->put_type);
|
||||
printf(" monitor flag=%d\n", pDB->mon_flag);
|
||||
|
||||
db_ptr = sp_ptr->channels;
|
||||
printf("State Program: \"%s\"\n", sp_ptr->name);
|
||||
printf("Number of channels=%d\n", sp_ptr->nchan);
|
||||
|
||||
for (nch = 0; nch < sp_ptr->nchan; nch++, db_ptr++)
|
||||
{
|
||||
printf("\nChannel name: \"%s\"\n", db_ptr->db_name);
|
||||
printf(" Unexpanded name: \"%s\"\n", db_ptr->db_uname);
|
||||
printf(" Variable=%d=0x%x\n", db_ptr->var, db_ptr->var);
|
||||
printf(" Size=%d bytes\n", db_ptr->size);
|
||||
printf(" Count=%d\n", db_ptr->count);
|
||||
printType(db_ptr->put_type);
|
||||
printValue((void *)db_ptr->var, db_ptr->size, db_ptr->count,
|
||||
db_ptr->put_type);
|
||||
printf(" DB get request type=%d\n", db_ptr->get_type);
|
||||
printf(" DB put request type=%d\n", db_ptr->put_type);
|
||||
printf(" monitor flag=%d\n", db_ptr->mon_flag);
|
||||
|
||||
if (db_ptr->monitored)
|
||||
if (pDB->monitored)
|
||||
printf(" Monitored\n");
|
||||
else
|
||||
printf(" Not monitored\n");
|
||||
|
||||
if(db_ptr->connected)
|
||||
if(pDB->connected)
|
||||
printf(" Connected\n");
|
||||
else
|
||||
printf(" Not connected\n");
|
||||
|
||||
if(db_ptr->get_complete)
|
||||
if(pDB->get_complete)
|
||||
printf(" Last get completed\n");
|
||||
else
|
||||
printf(" Get not completed or no get issued\n");
|
||||
|
||||
printf(" Status=%d\n", db_ptr->status);
|
||||
printf(" Severity=%d\n", db_ptr->severity);
|
||||
printf(" Status=%d\n", pDB->status);
|
||||
printf(" Severity=%d\n", pDB->severity);
|
||||
|
||||
printf(" Delta=%g\n", db_ptr->delta);
|
||||
printf(" Timeout=%g\n", db_ptr->timeout);
|
||||
printf(" Delta=%g\n", pDB->delta);
|
||||
printf(" Timeout=%g\n", pDB->timeout);
|
||||
wait_rtn();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Read from console until a RETURN is detected */
|
||||
LOCAL VOID wait_rtn()
|
||||
{
|
||||
char bfr;
|
||||
@@ -196,6 +193,7 @@ LOCAL VOID wait_rtn()
|
||||
} while (bfr != '\n');
|
||||
}
|
||||
|
||||
/* Special union to simplify printing values */
|
||||
struct dbr_union {
|
||||
union {
|
||||
char c;
|
||||
@@ -206,7 +204,8 @@ struct dbr_union {
|
||||
} u;
|
||||
};
|
||||
|
||||
static void printValue(pvar, size, count, type)
|
||||
/* Print the current internal value of a database channel */
|
||||
LOCAL VOID printValue(pvar, size, count, type)
|
||||
void *pvar;
|
||||
int size, count, type;
|
||||
{
|
||||
@@ -251,7 +250,8 @@ int size, count, type;
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void printType(type)
|
||||
/* Print the data type of a channel */
|
||||
LOCAL VOID printType(type)
|
||||
int type;
|
||||
{
|
||||
char *type_str;
|
||||
@@ -281,6 +281,66 @@ int type;
|
||||
case DBR_DOUBLE:
|
||||
type_str = "double";
|
||||
break;
|
||||
|
||||
default:
|
||||
type_str = "?";
|
||||
break;
|
||||
}
|
||||
printf(" Type = %s\n", type_str);
|
||||
}
|
||||
|
||||
/* Find a state program associated with a given task id */
|
||||
LOCAL SPROG *seqQryFind(tid)
|
||||
int tid;
|
||||
{
|
||||
SPROG *pSP;
|
||||
extern SPROG *seqFindProg();
|
||||
|
||||
if (tid == 0)
|
||||
{
|
||||
seqShowAll();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find a state program that has this task id */
|
||||
pSP = seqFindProg(tid);
|
||||
if (pSP == NULL)
|
||||
{
|
||||
printf("No state program exists for task id %d\n", tid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check for correct magic number */
|
||||
if (pSP->magic != MAGIC)
|
||||
{
|
||||
printf("Sorry, wrong magic number\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pSP;
|
||||
}
|
||||
|
||||
LOCAL int seqProgCount;
|
||||
|
||||
/* This routine is called by seqTraverseProg() for seqShowAll() */
|
||||
LOCAL seqShowSP(pSP)
|
||||
SPROG *pSP;
|
||||
{
|
||||
SSCB *pSS;
|
||||
|
||||
pSS = pSP->sscb;
|
||||
if (seqProgCount++ == 0)
|
||||
printf("TID Prog Name Task Name\n");
|
||||
|
||||
printf("%-8d %-12s %-12s\n", pSP->task_id,pSP->name, taskName(pSS->task_id) );
|
||||
}
|
||||
|
||||
/* Print a brief summary of all state programs */
|
||||
LOCAL seqShowAll()
|
||||
{
|
||||
SPROG *pSP;
|
||||
|
||||
seqProgCount = 0;
|
||||
seqTraverseProg(seqShowSP, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
state sets.
|
||||
|
||||
ENVIRONMENT: VxWorks
|
||||
|
||||
HISTORY:
|
||||
10dec91,ajk removed "if ( .... );" bug in function sequencer().
|
||||
HISTORY
|
||||
04dec91,ajk Implemented linked list of state programs, eliminating task
|
||||
variables.
|
||||
11dec91,ajk Made cosmetic changes and cleaned up comments.
|
||||
19dec91,ajk Changed algoritm in get_timeout().
|
||||
***************************************************************************/
|
||||
|
||||
#include "seq.h"
|
||||
@@ -28,188 +30,205 @@ LOCAL long get_timeout();
|
||||
|
||||
#define MAX_TIMEOUT (1<<30) /* like 2 years */
|
||||
|
||||
/* Sequencer main task entry point */
|
||||
sequencer(sp_ptr, stack_size, ptask_name)
|
||||
SPROG *sp_ptr; /* ptr to original (global) state program table */
|
||||
/*
|
||||
* sequencer() - Sequencer main task entry point.
|
||||
* */
|
||||
sequencer(pSP, stack_size, ptask_name)
|
||||
SPROG *pSP; /* ptr to original (global) state program table */
|
||||
int stack_size; /* stack size */
|
||||
char *ptask_name; /* Parent task name */
|
||||
{
|
||||
extern SPROG *seq_task_ptr;
|
||||
SSCB *ss_ptr;
|
||||
STATE *st_ptr;
|
||||
SSCB *pSS;
|
||||
STATE *pST;
|
||||
int nss, task_id;
|
||||
char task_name[TASK_NAME_SIZE+10];
|
||||
extern ss_entry();
|
||||
extern VOID ss_entry();
|
||||
|
||||
sp_ptr->task_id = taskIdSelf(); /* my task id */
|
||||
pSP->task_id = taskIdSelf(); /* my task id */
|
||||
|
||||
/* Make "seq_task_ptr" a task variable */
|
||||
if (taskVarAdd(sp_ptr->task_id, &seq_task_ptr) != OK)
|
||||
{
|
||||
seq_log(sp_ptr, "%s: taskVarAdd failed\n", sp_ptr->name);
|
||||
return -1;
|
||||
}
|
||||
seq_task_ptr = sp_ptr;
|
||||
/* Add the program to the state program list */
|
||||
seqAddProg(pSP);
|
||||
|
||||
/* Initilaize state set to first task, and set event mask */
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
{
|
||||
st_ptr = ss_ptr->states;
|
||||
ss_ptr->current_state = 0;
|
||||
ss_ptr->pMask = (st_ptr->eventMask);
|
||||
}
|
||||
/*
|
||||
* Connect to database channels & initiate monitor requests.
|
||||
* Returns here immediately if "connect" option is not set (-c),
|
||||
* otherwise, waits for all channels to connect (+c).
|
||||
*/
|
||||
seq_connect(pSP);
|
||||
|
||||
/* Connect to database channels & initiate monitor requests.
|
||||
Returns here immediately if "connect" switch is not set */
|
||||
seq_connect(sp_ptr);
|
||||
|
||||
/* Create the state set tasks */
|
||||
/* Additional state set task names are derived from the first ss */
|
||||
if (strlen(ptask_name) > TASK_NAME_SIZE)
|
||||
ptask_name[TASK_NAME_SIZE] = 0;
|
||||
|
||||
ss_ptr = sp_ptr->sscb + 1;
|
||||
for (nss = 1; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
/* Create each additional state set task */
|
||||
pSS = pSP->sscb + 1;
|
||||
for (nss = 1; nss < pSP->nss; nss++, pSS++)
|
||||
{
|
||||
/* Form task name from program name + state set number */
|
||||
sprintf(task_name, "%s_%d", ptask_name, nss);
|
||||
|
||||
/* Spawn the task */
|
||||
task_id = taskSpawn(task_name,
|
||||
SPAWN_PRIORITY+ss_ptr->task_priority,
|
||||
SPAWN_OPTIONS, stack_size, ss_entry, sp_ptr, ss_ptr);
|
||||
task_id = taskSpawn(
|
||||
task_name, /* task name */
|
||||
SPAWN_PRIORITY+pSS->task_priority, /* priority */
|
||||
SPAWN_OPTIONS, /* task options */
|
||||
stack_size, /* stack size */
|
||||
ss_entry, /* entry point */
|
||||
pSP, pSS); /* pass 2 parameters */
|
||||
|
||||
seq_log(sp_ptr, "Spawning task %d: \"%s\"\n", task_id, task_name);
|
||||
seq_log(pSP, "Spawning task %d: \"%s\"\n", task_id, task_name);
|
||||
}
|
||||
|
||||
/* Main task handles first state set */
|
||||
ss_entry(sp_ptr, sp_ptr->sscb);
|
||||
/* First state set jumps directly to entry point */
|
||||
ss_entry(pSP, pSP->sscb);
|
||||
}
|
||||
/* Task entry point for state sets */
|
||||
/* Provides main loop for state set processing (common, re-entrant code) */
|
||||
VOID ss_entry(sp_ptr, ss_ptr)
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
/*
|
||||
* ss_entry() - Task entry point for all state sets.
|
||||
* Provides the main loop for state set processing.
|
||||
*/
|
||||
VOID ss_entry(pSP, pSS)
|
||||
SPROG *pSP;
|
||||
SSCB *pSS;
|
||||
{
|
||||
BOOL ev_trig;
|
||||
STATE *st_ptr, *st_pNext;
|
||||
STATE *pST, *pStNext;
|
||||
long delay;
|
||||
int i;
|
||||
char *var_ptr;
|
||||
char *pVar;
|
||||
|
||||
pSS->task_id = taskIdSelf();
|
||||
|
||||
/* Initialize all tasks except the main task */
|
||||
ss_ptr->task_id = taskIdSelf();
|
||||
if (ss_ptr->task_id != sp_ptr->task_id)
|
||||
ss_task_init(sp_ptr, ss_ptr);
|
||||
if (pSS->task_id != pSP->task_id)
|
||||
ss_task_init(pSP, pSS);
|
||||
|
||||
var_ptr = sp_ptr->user_area;
|
||||
st_ptr = ss_ptr->states;
|
||||
/* Initilaize state set to enter the first state */
|
||||
pST = pSS->states;
|
||||
pSS->current_state = 0;
|
||||
|
||||
/* Main loop */
|
||||
/* Use the event mask for this state */
|
||||
pSS->pMask = (pST->eventMask);
|
||||
|
||||
/* Local ptr to user variables (for reentrant code only) */
|
||||
pVar = pSP->user_area;
|
||||
|
||||
/*
|
||||
* ============= Main loop ==============
|
||||
*/
|
||||
while (1)
|
||||
{
|
||||
/* Clear event bits */
|
||||
semTake(sp_ptr->caSemId, WAIT_FOREVER); /* Lock CA event update */
|
||||
semTake(pSP->caSemId, WAIT_FOREVER); /* Lock CA event update */
|
||||
for (i = 0; i < NWRDS; i++)
|
||||
ss_ptr->events[i] = 0;
|
||||
semGive(sp_ptr->caSemId); /* Unlock CA event update */
|
||||
pSS->events[i] = 0;
|
||||
semGive(pSP->caSemId); /* Unlock CA event update */
|
||||
|
||||
ss_ptr->time = tickGet(); /* record time we entered this state */
|
||||
pSS->time = tickGet(); /* record time we entered this state */
|
||||
|
||||
/* Call delay function to set up delays */
|
||||
ss_ptr->ndelay = 0;
|
||||
st_ptr->delay_func(sp_ptr, ss_ptr, var_ptr);
|
||||
pSS->ndelay = 0;
|
||||
pST->delay_func(pSP, pSS, pVar);
|
||||
|
||||
/* On 1-st pass fall thru w/o wake up */
|
||||
semGive(ss_ptr->syncSemId);
|
||||
/* Generate a phoney event.
|
||||
* This guarantees that a when() is always executed at
|
||||
* least once when a state is entered. */
|
||||
semGive(pSS->syncSemId);
|
||||
|
||||
/* Loop until an event is triggered */
|
||||
/*
|
||||
* Loop until an event is triggered, i.e. when()
|
||||
* returns TRUE.
|
||||
*/
|
||||
do {
|
||||
/* Wake up on CA event, event flag, or expired time delay */
|
||||
delay = get_timeout(ss_ptr);
|
||||
semTake(ss_ptr->syncSemId, delay);
|
||||
delay = get_timeout(pSS);
|
||||
if (delay > 0)
|
||||
semTake(pSS->syncSemId, delay);
|
||||
|
||||
/* Apply resource lock: any new events coming in will
|
||||
be deferred until next state is entered */
|
||||
semTake(sp_ptr->caSemId, WAIT_FOREVER);
|
||||
semTake(pSP->caSemId, WAIT_FOREVER);
|
||||
|
||||
/* Call event function to check for event trigger */
|
||||
ev_trig = st_ptr->event_func(sp_ptr, ss_ptr, var_ptr);
|
||||
/* Call the event function to check for an event trigger.
|
||||
* Everything inside the when() statement is executed.
|
||||
*/
|
||||
ev_trig = pST->event_func(pSP, pSS, pVar);
|
||||
|
||||
/* Unlock CA resource */
|
||||
semGive(sp_ptr->caSemId);
|
||||
semGive(pSP->caSemId);
|
||||
|
||||
} while (!ev_trig);
|
||||
/* Event triggered */
|
||||
/*
|
||||
* An event triggered:
|
||||
* execute the action statements and enter the new state.
|
||||
*/
|
||||
|
||||
/* Change event mask ptr for next state */
|
||||
st_pNext = ss_ptr->states + ss_ptr->next_state;
|
||||
ss_ptr->pMask = (st_pNext->eventMask);
|
||||
pStNext = pSS->states + pSS->next_state;
|
||||
pSS->pMask = (pStNext->eventMask);
|
||||
|
||||
/* Execute the action for this event */
|
||||
ss_ptr->action_complete = FALSE;
|
||||
st_ptr->action_func(sp_ptr, ss_ptr, var_ptr);
|
||||
pSS->action_complete = FALSE;
|
||||
pST->action_func(pSP, pSS, pVar);
|
||||
|
||||
/* Flush any outstanding DB requests */
|
||||
ca_flush_io();
|
||||
|
||||
/* Change to next state */
|
||||
ss_ptr->prev_state = ss_ptr->current_state;
|
||||
ss_ptr->current_state = ss_ptr->next_state;
|
||||
st_ptr = ss_ptr->states + ss_ptr->current_state;
|
||||
ss_ptr->action_complete = TRUE;
|
||||
pSS->prev_state = pSS->current_state;
|
||||
pSS->current_state = pSS->next_state;
|
||||
pST = pSS->states + pSS->current_state;
|
||||
pSS->action_complete = TRUE;
|
||||
}
|
||||
}
|
||||
/* Initialize state-set tasks */
|
||||
LOCAL VOID ss_task_init(sp_ptr, ss_ptr)
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
LOCAL VOID ss_task_init(pSP, pSS)
|
||||
SPROG *pSP;
|
||||
SSCB *pSS;
|
||||
{
|
||||
extern SPROG *seq_task_ptr;
|
||||
|
||||
|
||||
/* Import task variable context from main task */
|
||||
taskVarAdd(ss_ptr->task_id, &seq_task_ptr);
|
||||
seq_task_ptr = sp_ptr;
|
||||
|
||||
/* Import Channel Access context from main task */
|
||||
ca_import(sp_ptr->task_id);
|
||||
/* Import Channel Access context from the main task */
|
||||
ca_import(pSP->task_id);
|
||||
|
||||
return;
|
||||
}
|
||||
/* Return time-out for delay() */
|
||||
LOCAL long get_timeout(ss_ptr)
|
||||
SSCB *ss_ptr;
|
||||
LOCAL long get_timeout(pSS)
|
||||
SSCB *pSS;
|
||||
{
|
||||
int ndelay;
|
||||
long timeout; /* min. expiration clock time */
|
||||
long timeout, timeoutMin; /* expiration clock time */
|
||||
long delay; /* min. delay (tics) */
|
||||
|
||||
if (ss_ptr->ndelay == 0)
|
||||
if (pSS->ndelay == 0)
|
||||
return MAX_TIMEOUT;
|
||||
|
||||
timeout = MAX_TIMEOUT; /* start with largest timeout */
|
||||
timeoutMin = MAX_TIMEOUT; /* start with largest timeout */
|
||||
|
||||
/* Find the minimum abs. timeout (0 means already expired) */
|
||||
for (ndelay = 0; ndelay < ss_ptr->ndelay; ndelay++)
|
||||
for (ndelay = 0; ndelay < pSS->ndelay; ndelay++)
|
||||
{
|
||||
if ((ss_ptr->timeout[ndelay] != 0) &&
|
||||
(ss_ptr->timeout[ndelay] < timeout) )
|
||||
timeout = (long)ss_ptr->timeout[ndelay];
|
||||
timeout = pSS->timeout[ndelay];
|
||||
if (timeout == 0)
|
||||
continue; /* already expired */
|
||||
if (pSS->time >= timeout)
|
||||
{ /* just expired */
|
||||
timeoutMin = pSS->time;
|
||||
pSS->timeout[ndelay] = 0; /* mark as expired */
|
||||
}
|
||||
else if (timeout < timeoutMin)
|
||||
{
|
||||
timeoutMin = timeout;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert timeout to delay */
|
||||
delay = timeout - tickGet();
|
||||
if (delay <= 0)
|
||||
return NO_WAIT;
|
||||
else
|
||||
return delay;
|
||||
/* Convert minimum timeout to delay */
|
||||
delay = timeoutMin - tickGet();
|
||||
return delay;
|
||||
}
|
||||
/* Set-up for delay() on entering a state. This routine is called
|
||||
by the state program for each delay in the "when" statement */
|
||||
VOID seq_start_delay(sp_ptr, ss_ptr, delay_id, delay)
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
VOID seq_start_delay(pSP, pSS, delay_id, delay)
|
||||
SPROG *pSP;
|
||||
SSCB *pSS;
|
||||
int delay_id; /* delay id */
|
||||
float delay;
|
||||
{
|
||||
@@ -218,25 +237,25 @@ float delay;
|
||||
/* Note: the following 2 lines could be combined, but doing so produces
|
||||
* the undefined symbol "Mund", which is not in VxWorks library */
|
||||
td_tics = delay*60.0;
|
||||
ss_ptr->timeout[delay_id] = ss_ptr->time + td_tics;
|
||||
pSS->timeout[delay_id] = pSS->time + td_tics;
|
||||
delay_id += 1;
|
||||
if (delay_id > ss_ptr->ndelay)
|
||||
ss_ptr->ndelay = delay_id;
|
||||
if (delay_id > pSS->ndelay)
|
||||
pSS->ndelay = delay_id;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test for time-out expired */
|
||||
BOOL seq_test_delay(sp_ptr, ss_ptr, delay_id)
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
BOOL seq_test_delay(pSP, pSS, delay_id)
|
||||
SPROG *pSP;
|
||||
SSCB *pSS;
|
||||
int delay_id;
|
||||
{
|
||||
if (ss_ptr->timeout[delay_id] == 0)
|
||||
if (pSS->timeout[delay_id] == 0)
|
||||
return TRUE; /* previously expired t-o */
|
||||
|
||||
if (tickGet() >= ss_ptr->timeout[delay_id])
|
||||
if (tickGet() >= pSS->timeout[delay_id])
|
||||
{
|
||||
ss_ptr->timeout[delay_id] = 0; /* mark as expired */
|
||||
pSS->timeout[delay_id] = 0; /* mark as expired */
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
@@ -251,91 +270,103 @@ int delay_id;
|
||||
* 5. Return, causing self to be deleted.
|
||||
*
|
||||
* This task is run whenever ANY task in the system is deleted.
|
||||
* Therefore, we have to check the task variable "seq_task_ptr"
|
||||
* to see if it's one of ours.
|
||||
* Therefore, we have to check the task belongs to a state program.
|
||||
* With VxWorks 5.0 we need to change references to the TCBX to handle
|
||||
* the Wind kernel.
|
||||
*/
|
||||
#ifdef V5_vxWorks
|
||||
sprog_delete(tid)
|
||||
int tid;
|
||||
{
|
||||
int nss, tid_ss;
|
||||
SPROG *pSP, *seqFindProg();
|
||||
SSCB *pSS;
|
||||
|
||||
#else
|
||||
sprog_delete(pTcbX)
|
||||
TCBX *pTcbX; /* ptr to TCB of task to be deleted */
|
||||
{
|
||||
int tid, nss, val, tid_ss;
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
extern SPROG *seq_task_ptr;
|
||||
int tid, nss, tid_ss;
|
||||
SPROG *pSP, *seqFindProg();
|
||||
SSCB *pSS;
|
||||
|
||||
tid = pTcbX->taskId;
|
||||
/* Note: seq_task_ptr is a task variable */
|
||||
val = taskVarGet(tid, &seq_task_ptr);
|
||||
if (val == ERROR)
|
||||
return 0; /* not one of our tasks */
|
||||
#endif
|
||||
pSP = seqFindProg(tid);
|
||||
if (pSP == NULL)
|
||||
return; /* not a state program task */
|
||||
|
||||
sp_ptr = (SPROG *)val;
|
||||
logMsg("Delete %s: sp_ptr=%d=0x%x, tid=%d\n",
|
||||
sp_ptr->name, sp_ptr, sp_ptr, tid);
|
||||
logMsg("Delete %s: pSP=%d=0x%x, tid=%d\n",
|
||||
pSP->name, pSP, pSP, tid);
|
||||
|
||||
/* Is this a real sequencer task? */
|
||||
if (sp_ptr->magic != MAGIC)
|
||||
if (pSP->magic != MAGIC)
|
||||
{
|
||||
logMsg(" Not main state program task\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Suspend all state set tasks except self */
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
pSS = pSP->sscb;
|
||||
logMsg(" Suspending state set tasks:\n");
|
||||
for (nss = 0; nss < pSP->nss; nss++, pSS++)
|
||||
{
|
||||
tid_ss = ss_ptr->task_id;
|
||||
tid_ss = pSS->task_id;
|
||||
if ( (tid_ss > 0) && (tid != tid_ss) )
|
||||
{
|
||||
logMsg(" suspend ss task: tid=%d\n", tid_ss);
|
||||
logMsg(" suspend task: tid=%d\n", tid_ss);
|
||||
taskSuspend(tid_ss);
|
||||
}
|
||||
}
|
||||
|
||||
/* Call user exit routine */
|
||||
sp_ptr->exit_func(sp_ptr, sp_ptr->user_area);
|
||||
|
||||
/* Close the log file */
|
||||
if (sp_ptr->logFd > 0 && sp_ptr->logFd != ioGlobalStdGet(1))
|
||||
/* Call user exit routine (only if task has run) */
|
||||
if (pSP->sscb->task_id > 0)
|
||||
{
|
||||
logMsg("Closing log fd=%d\n", sp_ptr->logFd);
|
||||
close(sp_ptr->logFd);
|
||||
sp_ptr->logFd = ioGlobalStdGet(1);
|
||||
logMsg(" Call exit function\n");
|
||||
pSP->exit_func(pSP, pSP->user_area);
|
||||
}
|
||||
|
||||
/* Delete state set tasks (except self) & delete their semaphores */
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
/* Close the log file */
|
||||
if (pSP->logFd > 0 && pSP->logFd != ioGlobalStdGet(1))
|
||||
{
|
||||
tid_ss = ss_ptr->task_id;
|
||||
logMsg("Closing log fd=%d\n", pSP->logFd);
|
||||
close(pSP->logFd);
|
||||
pSP->logFd = ioGlobalStdGet(1);
|
||||
}
|
||||
|
||||
/* Remove the state program from the state program list */
|
||||
seqDelProg(pSP);
|
||||
|
||||
/* Delete state set tasks (except self) & delete their semaphores */
|
||||
pSS = pSP->sscb;
|
||||
for (nss = 0; nss < pSP->nss; nss++, pSS++)
|
||||
{
|
||||
tid_ss = pSS->task_id;
|
||||
if ( tid_ss > 0)
|
||||
{
|
||||
if (tid != tid_ss)
|
||||
if ( (tid != tid_ss) && (tid_ss > 0) )
|
||||
{
|
||||
logMsg(" delete ss task: tid=%d\n", tid_ss);
|
||||
taskVarSet(tid_ss, &seq_task_ptr, ERROR);
|
||||
taskDelete(tid_ss);
|
||||
}
|
||||
semDelete(ss_ptr->syncSemId);
|
||||
if (!sp_ptr->async_flag)
|
||||
semDelete(ss_ptr->getSemId);
|
||||
semDelete(pSS->syncSemId);
|
||||
if (!pSP->async_flag)
|
||||
semDelete(pSS->getSemId);
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete program-wide semaphores */
|
||||
semDelete(sp_ptr->caSemId);
|
||||
/****semDelete(sp_ptr->logSemId);****/
|
||||
semDelete(pSP->caSemId);
|
||||
|
||||
/* Free the memory that was allocated for the task area */
|
||||
logMsg("free sp_ptr->dyn_ptr=0x%x\n", sp_ptr->dyn_ptr);
|
||||
logMsg("free pSP->dyn_ptr=0x%x\n", pSP->dyn_ptr);
|
||||
taskDelay(5);
|
||||
free(sp_ptr->dyn_ptr);
|
||||
free(pSP->dyn_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* VxWorks Version 4.02 only */
|
||||
#ifdef VX4
|
||||
/* VxWorks Version 4 only */
|
||||
#ifndef V5_vxWorks
|
||||
|
||||
/* seq_semTake - take semaphore:
|
||||
* VxWorks semTake() with timeout added. (emulates VxWorks 5.0)
|
||||
@@ -353,4 +384,4 @@ long timeout; /* timeout in tics */
|
||||
else
|
||||
vrtxPend(&semId->count, timeout, &dummy);
|
||||
}
|
||||
#endif VX4
|
||||
#endif V5_vxWorks
|
||||
|
||||
Reference in New Issue
Block a user