From 3d72da5c20d9df7088d83d297d0d57263a72fc50 Mon Sep 17 00:00:00 2001 From: kozubal Date: Wed, 29 Jan 1992 13:46:37 +0000 Subject: [PATCH] delay() fix, Vx5.0 compile option, code clean-up, task delete fix, removed task variables. --- src/sequencer/README | 2 + src/sequencer/seq_ca.c | 324 ++++++++++++++------------ src/sequencer/seq_mac.c | 66 ++++-- src/sequencer/seq_main.c | 492 ++++++++++++++++++++++----------------- src/sequencer/seq_qry.c | 262 +++++++++++++-------- src/sequencer/seq_task.c | 345 ++++++++++++++------------- 6 files changed, 848 insertions(+), 643 deletions(-) diff --git a/src/sequencer/README b/src/sequencer/README index 2a5e8e276..6eaa4c785 100644 --- a/src/sequencer/README +++ b/src/sequencer/README @@ -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. +### diff --git a/src/sequencer/seq_ca.c b/src/sequencer/seq_ca.c index afa94aca8..8fd2a67c6 100644 --- a/src/sequencer/seq_ca.c +++ b/src/sequencer/seq_ca.c @@ -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; diff --git a/src/sequencer/seq_mac.c b/src/sequencer/seq_mac.c index 85c34987d..3f6eb906d 100644 --- a/src/sequencer/seq_mac.c +++ b/src/sequencer/seq_mac.c @@ -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; diff --git a/src/sequencer/seq_main.c b/src/sequencer/seq_main.c index a3c167de3..70f115449 100644 --- a/src/sequencer/seq_main.c +++ b/src/sequencer/seq_main.c @@ -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 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: ". + */ #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 diff --git a/src/sequencer/seq_qry.c b/src/sequencer/seq_qry.c index dbeaceaf5..0cb1200fe 100644 --- a/src/sequencer/seq_qry.c +++ b/src/sequencer/seq_qry.c @@ -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 \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 \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; +} diff --git a/src/sequencer/seq_task.c b/src/sequencer/seq_task.c index 6050c68f0..298fefe03 100644 --- a/src/sequencer/seq_task.c +++ b/src/sequencer/seq_task.c @@ -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