delay() fix, Vx5.0 compile option, code clean-up, task delete fix, removed task variables.

This commit is contained in:
kozubal
1992-01-29 13:46:37 +00:00
parent 113e6aa884
commit 3d72da5c20
6 changed files with 848 additions and 643 deletions

View File

@@ -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.
###

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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