diff --git a/src/sequencer/Version b/src/sequencer/Version index 38af70180..bf65d5728 100755 --- a/src/sequencer/Version +++ b/src/sequencer/Version @@ -1,2 +1,2 @@ -1.7.10 +1.8_Test diff --git a/src/sequencer/gen_ss_code.c b/src/sequencer/gen_ss_code.c index 25d56d191..9c66438e3 100644 --- a/src/sequencer/gen_ss_code.c +++ b/src/sequencer/gen_ss_code.c @@ -8,6 +8,7 @@ ENVIRONMENT: UNIX HISTORY: 19nov91,ajk Changed find_var() to findVar(). +28apr92,ajk Implemented efClear() & efTestAndClear(). ***************************************************************************/ #include #include "parse.h" @@ -207,7 +208,7 @@ int level; /* indentation level */ { Expr *epf; int nparams; - extern int reent_flag; + extern int reent_opt; if (ep == 0) return; @@ -269,7 +270,7 @@ int level; /* indentation level */ eval_expr(stmt_type, ep->left, sp, level+1); break; case E_VAR: - if(reent_flag) + if(reent_opt) { /* Make variables point to allocated structure */ Var *vp; vp = (Var *)ep->left; @@ -352,12 +353,14 @@ int level; printf("\t"); } /* func_name_to_code - convert function name to a code */ -enum fcode { F_DELAY, F_EFSET, F_EFTEST, F_PVGET, F_PVPUT, +enum fcode { F_DELAY, F_EFSET, F_EFTEST, F_EFCLEAR, F_EFTESTANDCLEAR, + F_PVGET, F_PVPUT, F_PVMONITOR, F_PVSTOPMONITOR, F_PVCOUNT, F_PVINDEX, F_PVSTATUS, F_PVSEVERITY, F_PVFLUSH, F_PVERROR, F_PVGETCOMPLETE, F_PVCONNECTED, F_PVCHANNELCOUNT, F_PVCONNECTCOUNT, F_NONE }; -char *fcode_str[] = { "delay", "efSet", "efTest", "pvGet", "pvPut", +char *fcode_str[] = { "delay", "efSet", "efTest", "efClear", "efTestAndClear", + "pvGet", "pvPut", "pvMonitor", "pvStopMonitor", "pvCount", "pvIndex", "pvStatus", "pvSeverity", "pvFlush", "pvError", "pvGetComplete", "pvConnected", "pvChannelCount", "pvConnectCount", NULL }; @@ -377,10 +380,10 @@ char *fname; } /* Process special function (returns TRUE if this is a special function) - Checks for special functions: - efSet(ef) and efGet(ef) -> set corresponding bit in ef_mask. - pvPut() & pvGet -> replace variable with ptr to db struct. - delay() - replaces delay time with delay index. + Checks for one of the following special functions: + - event flag functions + - process variable functions + - delay() */ special_func(stmt_type, ep, sp) int stmt_type; /* ACTION_STMT or EVENT_STMT */ @@ -415,6 +418,8 @@ Expr *sp; /* current State struct */ { case F_EFSET: case F_EFTEST: + case F_EFCLEAR: + case F_EFTESTANDCLEAR: if (vp->type != V_EVFLAG) { fprintf(stderr, "Line %d: ", ep->line_num); diff --git a/src/sequencer/gen_tables.c b/src/sequencer/gen_tables.c index 331dd56de..6fa78e93f 100644 --- a/src/sequencer/gen_tables.c +++ b/src/sequencer/gen_tables.c @@ -7,6 +7,8 @@ DESCRIPTION: Generate tables for run-time sequencer. See also: phase2.c & gen_ss_code.c ENVIRONMENT: UNIX + HISTORY: +28apr92,ajk Implemented new event flag mode. ***************************************************************************/ #include @@ -84,7 +86,7 @@ int index; Var *vp; char *get_type_string, *put_type_string, *postfix; extern char *prog_name; - extern int reent_flag; + extern int reent_opt; int size, ev_flag, count; vp = cp->var; @@ -138,7 +140,7 @@ int index; postfix = "[0]"; else postfix = ""; - if (reent_flag) + if (reent_opt) printf("OFFSET(struct UserVar, %s%s), ", vp->name, postfix); else printf("&%s%s, ", vp->name, postfix); /* variable ptr */ @@ -168,7 +170,7 @@ int index; printf("0, "); /* event id supplied by CA */ - printf("0, "); /* getSemId */ + printf("0, "); /* semaphore id for async. pvGet() */ printf("&%s", prog_name); /* ptr to state program structure */ @@ -236,9 +238,10 @@ char *ss_name; gen_state_prog_table() { extern char *prog_name, *prog_param; - extern int async_flag, debug_flag, reent_flag, conn_flag; + extern int async_opt, debug_opt, reent_opt, conn_opt, newef_opt; extern int nstates; extern Expr exit_code_list; + int i; printf("\n/* Program parameter list */\n"); @@ -276,7 +279,7 @@ gen_state_prog_table() printf("\tNULL,\t/* ptr to user area (not used) */\n"); - if (reent_flag) + if (reent_opt) printf("\tsizeof(struct UserVar),\t/* user area size */\n"); else printf("\t0,\t/* user area size (not used) */\n"); @@ -291,8 +294,13 @@ gen_state_prog_table() printf("\tprog_param,\t/* *params */\n"); - printf("\t%d, %d, %d, %d,\t/* async, debug, & reent flags */\n", - async_flag, debug_flag, reent_flag, conn_flag); + printf("\t"); + for (i = 0; i < NWRDS; i++) + printf("0, "); + printf("\t/* Event flags (bit encoded) */\n"); + + printf("\t0x%x,\t/* encoded async, debug, conn, newef & reent options */\n", + encode_options() ); printf("\texit_handler,\t/* exit handler */\n"); @@ -302,6 +310,24 @@ gen_state_prog_table() return; } + +encode_options() +{ + int options; + + options = 0; + if (async_opt) + options |= OPT_ASYNC; + if (conn_opt) + options |= OPT_CONN; + if (debug_opt) + options |= OPT_DEBUG; + if (reent_opt) + options |= OPT_REENT; + if (newef_opt) + options |= OPT_NEWEF; + return options; +} /* Generate an array of state set control blocks (SSCB), one entry for each state set */ gen_sscb_array() @@ -337,11 +363,6 @@ gen_sscb_array() printf("\t0, FALSE,\t/* trans_number, action_complete */\n"); - printf("\t/* outstanding events */\n\t"); - for (n = 0; n < NWRDS; n++) - printf("0, "); - printf("\n"); - printf("\t0,\t/* pMask - ptr to current event mask */\n"); printf("\t0,\t/* number of delays in use */\n"); diff --git a/src/sequencer/parse.c b/src/sequencer/parse.c index 62fbeb841..6566b92bc 100644 --- a/src/sequencer/parse.c +++ b/src/sequencer/parse.c @@ -14,6 +14,7 @@ 19nov91,ajk Replaced lstLib calls with built-in links. 20nov91,ajk Removed snc_init() - no longer did anything useful. 20nov91,ajk Added option_stmt() routine. +28apr92,ajk Implemented new event flag mode. ***************************************************************************/ /*====================== Includes, globals, & defines ====================*/ @@ -28,7 +29,7 @@ #define FALSE 0 #endif TRUE -int debug_print_flag = 0; /* Debug level (set by source file) */ +int debug_print_opt = 0; /* Debug level (set by source file) */ char *prog_name; /* ptr to program name (string) */ @@ -122,28 +123,32 @@ option_stmt(option, value) char *option; /* "a", "r", ... */ int value; /* TRUE means +, FALSE means - */ { - extern int async_flag, conn_flag, debug_flag, - line_flag, reent_flag, warn_flag; + extern int async_opt, conn_opt, debug_opt, + line_opt, reent_opt, warn_opt, newef_opt; switch(*option) { case 'a': - async_flag = value; + async_opt = value; break; case 'c': - conn_flag = value; + conn_opt = value; break; case 'd': - debug_flag = value; + debug_opt = value; break; case 'l': - line_flag = value; + line_opt = value; break; case 'r': - reent_flag = value; + reent_opt = value; break; case 'w': - warn_flag = value; + warn_opt = value; + + case 'e': + newef_opt = value; + break; } return; @@ -347,11 +352,11 @@ char *name; /* variable name */ return 0; } -/* Set debug print flag */ -set_debug_print(flag) -char *flag; +/* Set debug print opt */ +set_debug_print(opt) +char *opt; { - debug_print_flag = atoi(flag); + debug_print_opt = atoi(opt); } /* Parsing "program" statement */ diff --git a/src/sequencer/phase2.c b/src/sequencer/phase2.c index 22bf23f56..96bf587b9 100644 --- a/src/sequencer/phase2.c +++ b/src/sequencer/phase2.c @@ -80,7 +80,7 @@ phase2() gen_preamble() { extern char *prog_name; - extern int async_flag, conn_flag, debug_flag, reent_flag; + extern int async_opt, conn_opt, debug_opt, reent_opt; /* Program name (comment) */ printf("/* Program \"%s\" */\n", prog_name); @@ -92,11 +92,11 @@ gen_preamble() printf("\n#define NUM_SS %d\n", num_ss); printf("#define NUM_CHANNELS %d\n", num_channels); - /* #define's for compiler flags */ - gen_flag_defn(async_flag, "ASYNC_FLAG"); - gen_flag_defn(conn_flag, "CONN_FLAG" ); - gen_flag_defn(debug_flag, "DEBUG_FLAG"); - gen_flag_defn(reent_flag, "REENT_FLAG"); + /* #define's for compiler options */ + gen_opt_defn(async_opt, "ASYNC_OPT"); + gen_opt_defn(conn_opt, "CONN_OPT" ); + gen_opt_defn(debug_opt, "DEBUG_OPT"); + gen_opt_defn(reent_opt, "REENT_OPT"); printf("\n"); /* Forward references of tables: */ @@ -106,11 +106,11 @@ gen_preamble() return; } -gen_flag_defn(flag, defn_name) -int flag; +gen_opt_defn(opt, defn_name) +int opt; char *defn_name; { - if (flag) + if (opt) printf("#define %s TRUE\n", defn_name); else printf("#define %s FALSE\n", defn_name); @@ -148,12 +148,12 @@ Expr *ep; { Var *vp; extern char *stype[]; - extern int warn_flag; + extern int warn_opt; vp = (Var *)findVar(ep->value); if (vp == 0) { /* variable not declared; add it to the variable list */ - if (warn_flag) + if (warn_opt) fprintf(stderr, "Warning: variable \"%s\" is used but not declared.\n", ep->value); @@ -218,12 +218,12 @@ gen_var_decl() Var *vp; char *vstr; int nv; - extern int reent_flag; + extern int reent_opt; printf("\n/* Variable declarations */\n"); /* Convert internal type to `C' type */ - if (reent_flag) + if (reent_opt) printf("struct UserVar {\n"); for (nv=0, vp = var_list; vp != NULL; nv++, vp = vp->next) { @@ -259,7 +259,7 @@ gen_var_decl() if (vstr != NULL) { - if (reent_flag) + if (reent_opt) printf("\t"); else printf("static "); @@ -271,7 +271,7 @@ gen_var_decl() printf(";\n"); } } - if (reent_flag) + if (reent_opt) printf("};\n"); return; } diff --git a/src/sequencer/seq_ca.c b/src/sequencer/seq_ca.c index c3e02cbb6..0c4a05265 100644 --- a/src/sequencer/seq_ca.c +++ b/src/sequencer/seq_ca.c @@ -27,9 +27,12 @@ * * Modification Log: * ----------------- - * .01 07-03-91 ajk . - * .02 12-11-91 ajk Cosmetic changes (comments & names) - * .03 02-13-92 ajk All seqLog() calls compile only if DEBUG is defined. + * 03jul91,ajk . + * 11dec91,ajk Cosmetic changes (comments & names) + * 13feb92,ajk All seqLog() calls compile only if DEBUG is defined. + * 28apr92,ajk Implemented new event flag mode. + * 21may92,ajk Will periodically announce number of connected channels + * if waiting form some to connect. */ #include "seq.h" @@ -105,10 +108,20 @@ SPROG *pSP; } ca_flush_io(); - if (pSP->conn_flag) - { /* Wait for all connections to complete */ - while (pSP->conn_count < pSP->nchan) - taskDelay(30); + if (pSP->options & OPT_CONN) + { /* Wait for all connections to complete ("+c" option) */ + for (i = 1; pSP->conn_count < pSP->nchan; i++) + { + if (i <= 2) + taskDelay(6); /* 1-st 2 times we delay 0.1 sec */ + else + taskDelay(30); /* thereafter we delay 0.5 sec */ + /* Log a message after about 5 sec + * or about every 50 sec thereafter */ + if (i == 12 || (i % 100) == 0) + logMsg("%d of %d channels connected\n", + pSP->conn_count, pSP->nchan); + } } return 0; @@ -197,8 +210,8 @@ struct connection_handler_args args; } /* - * seq_efSet() - Set an event flag. The result is to wake up each state - * set that is waiting for event processing. + * seq_efSet() - Set an event flag, then wake up each state + * set that might be waiting on that event flag. */ VOID seq_efSet(pSP, dummy, ev_flag) SPROG *pSP; @@ -208,34 +221,49 @@ int ev_flag; /* event flag */ SSCB *pSS; int nss; - pSS = pSP->sscb; - /* For all state sets: */ - for (nss = 0; nss < pSP->nss; nss++, pSS++) - { - /* Apply resource lock */ - semTake(pSP->caSemId, WAIT_FOREVER); + /* Set this bit (apply resource lock) */ + semTake(pSP->caSemId, WAIT_FOREVER); + bitSet(pSP->events, ev_flag); + /* Check flag against mask for all state sets: */ + for (nss = 0, pSS = pSP->sscb; nss < pSP->nss; nss++, pSS++) + { /* Test for possible event trig based on bit mask for this state */ if ( (ev_flag == 0) || bitTest(pSS->pMask, ev_flag) ) { - bitSet(pSS->events, ev_flag); semGive(pSS->syncSemId); /* wake up the ss task */ } - /* Unlock resource */ - semGive(pSP->caSemId); } + + /* Unlock resource */ + semGive(pSP->caSemId); } /* * seq_efTest() - Test event flag against outstanding events. */ -seq_efTest(pSP, pSS, ev_flag) +int seq_efTest(pSP, pSS, ev_flag) SPROG *pSP; SSCB *pSS; int ev_flag; /* event flag */ { - return bitTest(pSS->events, ev_flag); + return bitTest(pSP->events, ev_flag); +} + +/* + * seq_efClear() - Test event flag against outstanding events, then clear it. + */ +int seq_efClear(pSP, pSS, ev_flag) +SPROG *pSP; +SSCB *pSS; +int ev_flag; /* event flag */ +{ + int isSet; + + isSet = bitTest(pSP->events, ev_flag); + bitClear(pSP->events, ev_flag); + return isSet; } /* * seq_pvGet() - Get DB value (uses channel access). @@ -256,7 +284,7 @@ CHAN *pDB; /* ptr to channel struct */ pDB->get_complete = FALSE; /* If synchronous pvGet then clear the pvGet pend semaphore */ - if (!pSP->async_flag) + if ( !(pSP->options & OPT_ASYNC) ) { pDB->getSemId = pSS->getSemId; semTake(pSS->getSemId, NO_WAIT); @@ -270,7 +298,7 @@ CHAN *pDB; /* ptr to channel struct */ seq_callback_handler, /* callback handler */ pDB); /* user arg */ - if (pSP->async_flag || (status != ECA_NORMAL) ) + if ( (pSP->options & OPT_ASYNC) || (status != ECA_NORMAL) ) return status; /* Synchronous pvGet() */ @@ -320,13 +348,13 @@ struct event_handler_args args; seq_efSet(pSP, 0, pDB->index + 1); /* If syncronous pvGet then notify pending state set */ - if (!pSP->async_flag) + if ( !(pSP->options & OPT_ASYNC) ) semGive(pDB->getSemId); return; } -/* Flush requests */ +/* Flush outstanding CA requests */ VOID seq_pvFlush() { ca_flush_io(); diff --git a/src/sequencer/seq_main.c b/src/sequencer/seq_main.c index b55958269..1c684fb02 100644 --- a/src/sequencer/seq_main.c +++ b/src/sequencer/seq_main.c @@ -25,6 +25,10 @@ 11dec91,ajk Cleaned up comments. 05feb92,ajk Decreased minimum allowable stack size to SPAWN_STACK_SIZE/2. 24feb92,ajk Print error code for log file failure. +28apr92,ajk Implemented new event flag mode. +29apr92,ajk Now alocates private program structures, even when reentry option + is not specified. This avoids problems with seqAddTask(). +29apr92,ajk Implemented mutual exclusion lock in seq_log(). ***************************************************************************/ /*#define DEBUG 1*/ @@ -76,10 +80,12 @@ int stack_size; /* optional stack size (bytes) */ SPROG *pSP, *alloc_task_area(); char *seqMacValGet(), *pname, *pvalue, *ptask_name; - /* If no parameters specified, print version info. */ + /* Print version & date of sequencer */ + printf("%s\n", seqVersion); + + /* Exit if no parameters specified */ if (pSP_orig == 0) { - printf("%s\n", seqVersion); return 0; } @@ -107,8 +113,7 @@ int stack_size; /* optional stack size (bytes) */ pSP = alloc_task_area(pSP_orig); /* Make a private copy of original structures (but change pointers!) */ - if (pSP_orig->reent_flag) - copy_sprog(pSP_orig, pSP); + copy_sprog(pSP_orig, pSP); /* Initialize state program block */ init_sprog(pSP); @@ -156,13 +161,13 @@ int stack_size; /* optional stack size (bytes) */ pSP->name, ptask_name); seq_log(pSP, " Task id = %d = 0x%x\n", tid, tid); + /* Return task id to calling program */ return tid; } /* * 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. + * Allocate a single block for all dynamic structures * The pointer to the allocated area is saved for task delete hook routine. */ LOCAL SPROG *alloc_task_area(pSP_orig) @@ -187,17 +192,10 @@ SPROG *pSP_orig; /* original state program structure */ scr_size = SCRATCH_SIZE; /* Total # bytes to allocate */ - if (pSP_orig->reent_flag) - { - size = prog_size + ss_size + state_size + - chan_size + user_size + mac_size + scr_size; - } - else - { - size = mac_size + scr_size; - } + size = prog_size + ss_size + state_size + + chan_size + user_size + mac_size + scr_size; - /* Alloc the task area */ + /* Alloc the dynamic task area */ dyn_ptr = dyn_ptr_start = (char *)calloc(size, 1); #ifdef DEBUG @@ -212,35 +210,34 @@ SPROG *pSP_orig; /* original state program structure */ #endif DEBUG /* Set ptrs in the PROG structure */ - if (pSP_orig->reent_flag) - { /* Reentry flag set: create a new structures */ - pSP_new = (SPROG *)dyn_ptr; + pSP_new = (SPROG *)dyn_ptr; - /* Copy the SPROG struct contents */ - *pSP_new = *pSP_orig; + /* Copy the SPROG struct contents */ + *pSP_new = *pSP_orig; - /* Allocate space for the other structures */ - dyn_ptr += prog_size; - pSP_new->sscb = (SSCB *)dyn_ptr; - dyn_ptr += ss_size; - pSP_new->states = (STATE *)dyn_ptr; - dyn_ptr += state_size; - pSP_new->channels = (CHAN *)dyn_ptr; - dyn_ptr += chan_size; + /* Allocate space for copies of the original structures */ + dyn_ptr += prog_size; + pSP_new->sscb = (SSCB *)dyn_ptr; + dyn_ptr += ss_size; + pSP_new->states = (STATE *)dyn_ptr; + dyn_ptr += state_size; + pSP_new->channels = (CHAN *)dyn_ptr; + dyn_ptr += chan_size; + if (user_size != 0) + { pSP_new->user_area = (char *)dyn_ptr; dyn_ptr += user_size; } else - { /* Reentry flag not set: keep original structures */ - pSP_new = pSP_orig; - } - /* Create dynamic structures for macros and scratch area */ + pSP_new->user_area = NULL; + + /* Create additional dynamic structures for macros and scratch area */ pSP_new->mac_ptr = (MACRO *)dyn_ptr; dyn_ptr += mac_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 */ + /* Save ptr to start of allocated area so we can free it at task delete */ pSP_new->dyn_ptr = dyn_ptr_start; return pSP_new; @@ -267,8 +264,7 @@ SPROG *pSP; /* new ptr */ pSS = pSP->sscb; /* Copy structures for each state set */ - pST = pSP->states; - for (nss = 0; nss < pSP->nss; nss++) + for (nss = 0, pST = pSP->states; nss < pSP->nss; nss++) { *pSS = *pSS_orig; /* copy SSCB */ pSS->states = pST; /* new ptr to 1-st STATE */ @@ -294,8 +290,11 @@ SPROG *pSP; /* new ptr */ /* Reset ptr to SPROG structure */ pDB->sprog = pSP; - /* Convert offset to address of the user variable */ - pDB->var += (int)var_ptr; + /* +r: Convert offset to address of the user variable. + * -r: var_ptr is an absolute address. + */ + if (pSP->options & OPT_REENT) + pDB->var += (int)var_ptr; pDB++; pDB_orig++; @@ -334,8 +333,7 @@ SPROG *pSP; SSCB *pSS; int nss, i; - pSS = pSP->sscb; - for (nss = 0; nss < pSP->nss; nss++, pSS++) + for (nss = 0, pSS = pSP->sscb; nss < pSP->nss; nss++, pSS++) { pSS->task_id = 0; /* Create a binary semaphore for synchronizing events in a SS */ @@ -347,7 +345,7 @@ SPROG *pSP; } /* Create a binary semaphore for pvGet() synconizing */ - if (!pSP->async_flag) + if (!pSP->options & OPT_ASYNC) { pSS->getSemId = semBCreate(SEM_Q_FIFO, SEM_FULL); @@ -362,8 +360,6 @@ SPROG *pSP; pSS->current_state = 0; /* initial state */ pSS->next_state = 0; pSS->action_complete = TRUE; - for (i = 0; i < NWRDS; i++) - pSS->events[i] = 0; /* clear events */ } return; } @@ -392,7 +388,8 @@ int nChar; return NULL; } /* - * Initialize logging + * seq_logInit() - Initialize logging. + * If "logfile" is not specified, then we log to standard output. */ LOCAL VOID seq_logInit(pSP) SPROG *pSP; @@ -422,7 +419,7 @@ SPROG *pSP; } } /* - * seqLog + * seq_log * 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: ". */ @@ -461,6 +458,7 @@ int arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8; /* arguments */ pBfr += count - 1; /* Write the msg */ + semTake(pSP->logSemId, WAIT_FOREVER); /* lock it */ fd = pSP->logFd; count = pBfr - logBfr + 1; status = write(fd, logBfr, count); @@ -476,7 +474,7 @@ int arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8; /* arguments */ { ioctl(fd, FIOSYNC); } - + semGive(pSP->logSemId); return; } @@ -498,19 +496,20 @@ int arg1,arg2, arg3, arg4, arg5, arg6, arg7, arg8; /* arguments */ return OK; } /* - * seq_flagGet: return the value of an option flag. + * seq_optGet: return the value of an option. * FALSE means "-" and TRUE means "+". */ -BOOL seq_flagGet(pSP, flag) +BOOL seq_optGet(pSP, opt) SPROG *pSP; -char *flag; /* one of the snc flags as a strign (e.g. "a") */ +char *opt; /* one of the snc options as a strign (e.g. "a") */ { - switch (flag[0]) + switch (opt[0]) { - case 'a': return pSP->async_flag; - case 'c': return pSP->conn_flag; - case 'd': return pSP->debug_flag; - case 'r': return pSP->reent_flag; + case 'a': return ( (pSP->options & OPT_ASYNC) != 0); + case 'c': return ( (pSP->options & OPT_CONN) != 0); + case 'd': return ( (pSP->options & OPT_DEBUG) != 0); + case 'r': return ( (pSP->options & OPT_REENT) != 0); + case 'e': return ( (pSP->options & OPT_NEWEF) != 0); default: return FALSE; } } @@ -547,17 +546,17 @@ SPROG *pSP; 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); + printf(" options: + printf(" async=%d, debug=%d, conn=%d, reent=%d, newef=%d\n", + seq_optGet(pSP, 'a'), seq_optGet(pSP, 'd'), seq_optGet(pSP, 'c'), + seq_optGet(pSP, 'r'), seq_optGet(pSP, 'e')); - pSS = pSP->sscb; - for (nss = 0; nss < pSP->nss; nss++, pSS++) + for (nss = 0, pSS = pSP->sscb; 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++) + for (nstates = 0, pST = pSS->states; nstates < pSS->num_states; nstates++) { printf(" \"%s\"\n", pST->name); pST++; diff --git a/src/sequencer/seq_prog.c b/src/sequencer/seq_prog.c index 265c71f16..51fe76af7 100644 --- a/src/sequencer/seq_prog.c +++ b/src/sequencer/seq_prog.c @@ -11,8 +11,10 @@ ENVIRONMENT: VxWorks HISTORY: -09dec91,ajk original ***************************************************************************/ - +09dec91,ajk original +29apr92,ajk Added mutual exclusion locks +***************************************************************************/ +#define DEBUG #include "seq.h" LOCAL SEM_ID seqProgListSemId; @@ -43,19 +45,28 @@ int task_id; if (!seqProgListInited || task_id == 0) return NULL; + semTake(seqProgListSemId, WAIT_FOREVER); + for (pNode = seqListFirst(&seqProgList); pNode != NULL; pNode = seqListNext(pNode) ) { pSP = pNode->pSP; if (pSP->task_id == task_id) + { + semGive(seqProgListSemId); return pSP; + } pSS = pSP->sscb; for (n = 0; n < pSP->nss; n++, pSS++) { if (pSS->task_id == task_id) + { + semGive(seqProgListSemId); return pSP; + } } } + semGive(seqProgListSemId); return NULL; /* not in list */ } @@ -75,6 +86,7 @@ VOID *param; /* any parameter */ if (!seqProgListInited) return ERROR; + semTake(seqProgListSemId, WAIT_FOREVER); for (pNode = seqListFirst(&seqProgList); pNode != NULL; pNode = seqListNext(pNode) ) { @@ -82,6 +94,7 @@ VOID *param; /* any parameter */ pFunc(pSP, param); } + semGive(seqProgListSemId); return OK; } @@ -97,21 +110,35 @@ SPROG *pSP; if (!seqProgListInited) seqProgListInit(); /* Initialize list */ + semTake(seqProgListSemId, WAIT_FOREVER); for (pNode = seqListFirst(&seqProgList); pNode != NULL; pNode = seqListNext(pNode) ) { if (pSP == pNode->pSP) + { + semGive(seqProgListSemId); +#ifdef DEBUG + printf("Task %d already in list\n", pSP->task_id); +#endif return ERROR; /* already in list */ + } } /* Insert at head of list */ pNode = (PROG_NODE *)malloc(sizeof(PROG_NODE) ); if (pNode == NULL) + { + semGive(seqProgListSemId); return ERROR; + } pNode->pSP = pSP; lstAdd(&seqProgList, pNode); + semGive(seqProgListSemId); +#ifdef DEBUG + printf("Added task %d to list.\n", pSP->task_id); +#endif return OK; } @@ -128,16 +155,23 @@ SPROG *pSP; if (!seqProgListInited) return ERROR; + semTake(seqProgListSemId, WAIT_FOREVER); for (pNode = seqListFirst(&seqProgList); pNode != NULL; pNode = seqListNext(pNode) ) { if (pNode->pSP == pSP) { lstDelete(&seqProgList, pNode); + semGive(seqProgListSemId); + +#ifdef DEBUG + printf("Deleted task %d from list.\n", pSP->task_id); +#endif return OK; } } + semGive(seqProgListSemId); return ERROR; /* not in list */ } @@ -151,6 +185,7 @@ LOCAL seqProgListInit() /* Create a semaphore for mutual exclusion */ seqProgListSemId = semBCreate(0); + semGive(seqProgListSemId); seqProgListInited = TRUE; diff --git a/src/sequencer/seq_qry.c b/src/sequencer/seq_qry.c index 6582f4763..3b5282e82 100644 --- a/src/sequencer/seq_qry.c +++ b/src/sequencer/seq_qry.c @@ -18,6 +18,8 @@ 19dec91,ajk Allow task name as well as task id. 25feb92,ajk V5.0 accepts 0 as a valid task id: fixed it. 26feb92,ajk Fixed formatting of task/program listing. +29apr92,ajk Modified to interpret encoded options. +21may92,ajk Modified format for listing programs & tasks. ***************************************************************************/ /* #define DEBUG 1 */ @@ -79,19 +81,19 @@ int tid; 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", - pSP->async_flag, pSP->debug_flag, pSP->reent_flag, - pSP->conn_flag); + printf(" options: async=%d, debug=%d, reent=%d, conn=%d, newef=%d\n", + ((pSP->options & OPT_ASYNC) != 0), ((pSP->options & OPT_DEBUG) != 0), + ((pSP->options & OPT_REENT) != 0), ((pSP->options & OPT_CONN) != 0), + ((pSP->options & OPT_NEWEF) != 0) ); 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"); - pSS = pSP->sscb; /* Print state set info */ - for (nss = 0; nss < pSP->nss; nss++, pSS++) + for (nss = 0, pSS = pSP->sscb; nss < pSP->nss; nss++, pSS++) { wait_rtn(); @@ -333,12 +335,24 @@ LOCAL seqShowSP(pSP) SPROG *pSP; { SSCB *pSS; + int nss; + char *progName, *ptaskName;; - pSS = pSP->sscb; if (seqProgCount++ == 0) - printf("TID Program Name Task Name\n"); + printf("Program Name Task ID Task Name SS Name\n\n"); - printf("%-10d %-18s %-18s\n", pSP->task_id,pSP->name, taskName(pSS->task_id) ); + progName = pSP->name; + for (nss = 0, pSS = pSP->sscb; nss < pSP->nss; nss++, pSS++) + { + if (pSS->task_id == 0) + ptaskName = "(no task)"; + else + ptaskName = taskName(pSS->task_id); + printf("%-16s %-10d %-16s %-16s\n", + progName, pSS->task_id, ptaskName, pSS->name ); + progName = ""; + } + printf("\n"); } /* Print a brief summary of all state programs */ diff --git a/src/sequencer/seq_task.c b/src/sequencer/seq_task.c index f2f12eb77..d4b31c712 100644 --- a/src/sequencer/seq_task.c +++ b/src/sequencer/seq_task.c @@ -1,7 +1,8 @@ /************************************************************************** GTA PROJECT AT division - Copyright, 1990, The Regents of the University of California. - Los Alamos National Laboratory + Copyright, 1990, 1991, 1992 + The Regents of the University of California + Los Alamos National Laboratory $Id$ DESCRIPTION: Seq_tasks.c: Task creation and control for sequencer @@ -12,7 +13,11 @@ 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(). +19dec91,ajk Changed algoritm in seq_getTimeout(). +29apr92,ajk Implemented new event flag mode. +30apr92,ajk Periodically call ca_pend_event() to detect connection failures. +21may92,ajk In sprog_delete() wait for loggin semaphore before suspending tasks. + Some minor changes in the way semaphores are deleted. ***************************************************************************/ #include "seq.h" @@ -20,15 +25,15 @@ /* Function declarations */ #ifdef ANSI LOCAL VOID ss_task_init(SPROG *, SSCB *); -LOCAL long get_timeout(SSCB *); +long seq_getTimeout(SSCB *); #else LOCAL VOID ss_task_init(); -LOCAL long get_timeout(); +long seq_getTimeout(); #endif ANSI #define TASK_NAME_SIZE 10 -#define MAX_TIMEOUT (1<<30) /* like 2 years */ +#define MAX_DELAY (60*10) /* max delay time pending for events */ /* * sequencer() - Sequencer main task entry point. @@ -40,11 +45,17 @@ char *ptask_name; /* Parent task name */ { SSCB *pSS; STATE *pST; - int nss, task_id; + int nss, task_id, i; char task_name[TASK_NAME_SIZE+10]; extern VOID ss_entry(); pSP->task_id = taskIdSelf(); /* my task id */ + pSS = pSP->sscb; + pSS->task_id = pSP->task_id; + + /* Clear all event flags */ + for (i = 0; i < NWRDS; i++) + pSP->events[i] = 0; /* Add the program to the state program list */ seqAddProg(pSP); @@ -61,8 +72,7 @@ char *ptask_name; /* Parent task name */ ptask_name[TASK_NAME_SIZE] = 0; /* Create each additional state set task */ - pSS = pSP->sscb + 1; - for (nss = 1; nss < pSP->nss; nss++, pSS++) + for (nss = 1, pSS = pSP->sscb + 1; nss < pSP->nss; nss++, pSS++) { /* Form task name from program name + state set number */ sprintf(task_name, "%s_%d", ptask_name, nss); @@ -93,7 +103,6 @@ SSCB *pSS; BOOL ev_trig; STATE *pST, *pStNext; long delay; - int i; char *pVar; pSS->task_id = taskIdSelf(); @@ -117,12 +126,6 @@ SSCB *pSS; */ while (1) { - /* Clear event bits */ - semTake(pSP->caSemId, WAIT_FOREVER); /* Lock CA event update */ - for (i = 0; i < NWRDS; i++) - pSS->events[i] = 0; - semGive(pSP->caSemId); /* Unlock CA event update */ - pSS->time = tickGet(); /* record time we entered this state */ /* Call delay function to set up delays */ @@ -135,25 +138,34 @@ SSCB *pSS; semGive(pSS->syncSemId); /* - * Loop until an event is triggered, i.e. when() - * returns TRUE. + * Loop until an event is triggered, i.e. when() returns TRUE + * or at least every MAX_DELAY ticks. + * */ do { + /* Allow CA to check for connect/disconnect on channels */ + if (pSP->task_id == pSS->task_id) + ca_pend_event(0.001); /* returns immediately */ + /* Wake up on CA event, event flag, or expired time delay */ - delay = get_timeout(pSS); + delay = seq_getTimeout(pSS); if (delay > 0) semTake(pSS->syncSemId, delay); - /* Apply resource lock: any new events coming in will - be deferred until next state is entered */ + /* Call the event function to check for an event trigger. + * The statement inside the when() statement is executed. + * Note, we lock out CA events while doing this. + */ semTake(pSP->caSemId, WAIT_FOREVER); - /* 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); + ev_trig = pST->event_func(pSP, pSS, pVar); /* check events */ - /* Unlock CA resource */ + if ( ev_trig && (pSP->options & OPT_NEWEF) == 0 ) + { /* Clear all event flags (old mode only) */ + register int i; + for (i = 0; i < NWRDS; i++) + pSP->events[i] = pSP->events[i] & !pSS->pMask[i]; + } semGive(pSP->caSemId); } while (!ev_trig); @@ -190,39 +202,41 @@ SSCB *pSS; return; } - /* Return time-out for delay() */ -LOCAL long get_timeout(pSS) + /* + * seq_getTimeout() - return time-out for pending on events. + * Returns number of tics to next expected timeout of a delay() call. + * Returns MAX_DELAY if no delays pending */ +long seq_getTimeout(pSS) SSCB *pSS; { int ndelay; - long timeout, timeoutMin; /* expiration clock time */ - long delay; /* min. delay (tics) */ + long timeout; /* expiration clock time (tics) */ + long delay, delayMin; /* remaining & min. delay (tics) */ if (pSS->ndelay == 0) - return MAX_TIMEOUT; + return MAX_DELAY; - timeoutMin = MAX_TIMEOUT; /* start with largest timeout */ + delayMin = MAX_DELAY; /* start with largest possible delay */ - /* Find the minimum abs. timeout (0 means already expired) */ + /* Find the minimum delay among all non-expired timeouts */ for (ndelay = 0; ndelay < pSS->ndelay; ndelay++) { timeout = pSS->timeout[ndelay]; if (timeout == 0) continue; /* already expired */ - if (pSS->time >= timeout) + delay = timeout - tickGet(); /* convert timeout to remaining delay */ + if (delay <= 0) { /* just expired */ - timeoutMin = pSS->time; + delayMin = 0; pSS->timeout[ndelay] = 0; /* mark as expired */ } - else if (timeout < timeoutMin) + else if (delay < delayMin) { - timeoutMin = timeout; + delayMin = delay; /* this is the min. delay so far */ } } - /* Convert minimum timeout to delay */ - delay = timeoutMin - tickGet(); - return delay; + return delayMin; } /* Set-up for delay() on entering a state. This routine is called by the state program for each delay in the "when" statement */ @@ -306,6 +320,9 @@ TCBX *pTcbX; /* ptr to TCB of task to be deleted */ return -1; } + /* Wait for log semaphore (in case a task is doing a write) */ + semTake(pSP->logSemId, 600); + /* Suspend all state set tasks except self */ pSS = pSP->sscb; #ifdef DEBUG @@ -314,7 +331,7 @@ TCBX *pTcbX; /* ptr to TCB of task to be deleted */ for (nss = 0; nss < pSP->nss; nss++, pSS++) { tid_ss = pSS->task_id; - if ( (tid_ss > 0) && (tid != tid_ss) ) + if ( (tid_ss != 0) && (tid != tid_ss) ) { #ifdef DEBUG logMsg(" suspend task: tid=%d\n", tid_ss); @@ -323,8 +340,11 @@ TCBX *pTcbX; /* ptr to TCB of task to be deleted */ } } + /* Give back log semaphore */ + semGive(pSP->logSemId); + /* Call user exit routine (only if task has run) */ - if (pSP->sscb->task_id > 0) + if (pSP->sscb->task_id != 0) { #ifdef DEBUG logMsg(" Call exit function\n"); @@ -350,23 +370,24 @@ TCBX *pTcbX; /* ptr to TCB of task to be deleted */ for (nss = 0; nss < pSP->nss; nss++, pSS++) { tid_ss = pSS->task_id; - if ( tid_ss > 0) + if ( (tid != tid_ss) && (tid_ss != 0) ) { - if ( (tid != tid_ss) && (tid_ss > 0) ) - { #ifdef DEBUG - logMsg(" delete ss task: tid=%d\n", tid_ss); + logMsg(" delete ss task: tid=%d\n", tid_ss); #endif DEBUG - taskDelete(tid_ss); - } - semDelete(pSS->syncSemId); - if (!pSP->async_flag) - semDelete(pSS->getSemId); + taskDelete(tid_ss); } + + if (pSS->syncSemId != 0) + semDelete(pSS->syncSemId); + + if (pSS->getSemId != 0) + semDelete(pSS->getSemId); } /* Delete program-wide semaphores */ semDelete(pSP->caSemId); + semDelete(pSP->logSemId); /* Free the memory that was allocated for the task area */ #ifdef DEBUG diff --git a/src/sequencer/snc_main.c b/src/sequencer/snc_main.c index 3806d1871..94244c380 100644 --- a/src/sequencer/snc_main.c +++ b/src/sequencer/snc_main.c @@ -11,6 +11,7 @@ HISTORY: 20nov91,ajk Removed call to init_snc(). 20nov91,ajk Removed some debug stuff. +28apr92,ajk Implemented new event flag mode. ***************************************************************************/ extern char *sncVersion; /* snc version and date created */ @@ -27,13 +28,14 @@ char out_file[200]; /* output file name */ char *src_file; /* ptr to (effective) source file name */ int line_num; /* current src file line number */ int c_line_num; /* line number for beginning of C code */ -/* Flags: */ -int async_flag = FALSE; /* do pvGet() asynchronously */ -int conn_flag = TRUE; /* wait for all connections to complete */ -int debug_flag = FALSE; /* run-time debug */ -int line_flag = TRUE; /* line numbering */ -int reent_flag = FALSE; /* reentrant at run-time */ -int warn_flag = TRUE; /* compiler warnings */ +/* Compile & run-time options: */ +int async_opt = FALSE; /* do pvGet() asynchronously */ +int conn_opt = TRUE; /* wait for all connections to complete */ +int debug_opt = FALSE; /* run-time debug */ +int newef_opt = TRUE; /* use new event flag mode */ +int line_opt = TRUE; /* line numbering */ +int reent_opt = FALSE; /* reentrant at run-time */ +int warn_opt = TRUE; /* compiler warnings */ /*+************************************************************************ * NAME: main @@ -125,6 +127,7 @@ char *argv[]; fprintf(stderr, " -l - supress line numbering\n"); fprintf(stderr, " +r - make reentrant at run-time\n"); fprintf(stderr, " -w - supress compiler warnings\n"); + fprintf(stderr, " -e - don't use new event flag mode\n"); fprintf(stderr, "example:\n snc +a -c vacuum.st\n"); exit(1); } @@ -133,51 +136,55 @@ char *argv[]; { s = *argv; if (*s == '+' || *s == '-') - get_flag(s); + get_options(s); else get_in_file(s); } } -get_flag(s) +get_options(s) char *s; { - int flag_val; - extern int debug_flag, line_flag, reent_flag, warn_flag; + int opt_val; + extern int debug_opt, line_opt, reent_opt, warn_opt, async_opt, newef_opt; if (*s == '+') - flag_val = TRUE; + opt_val = TRUE; else - flag_val = FALSE; + opt_val = FALSE; switch (s[1]) { case 'a': - async_flag = flag_val; + async_opt = opt_val; break; case 'c': - conn_flag = flag_val; + conn_opt = opt_val; break; case 'd': - debug_flag = flag_val; + debug_opt = opt_val; break; case 'l': - line_flag = flag_val; + line_opt = opt_val; break; case 'r': - reent_flag = flag_val; + reent_opt = opt_val; break; case 'w': - warn_flag = flag_val; + warn_opt = opt_val; + break; + + case 'e': + newef_opt = opt_val; break; default: - fprintf(stderr, "Unknown flag: \"%s\"\n", s); + fprintf(stderr, "Unknown option: \"%s\"\n", s); break; } } @@ -275,9 +282,9 @@ print_line_num(line_num, src_file) int line_num; char *src_file; { - extern int line_flag; + extern int line_opt; - if (line_flag) + if (line_opt) printf("# line %d \"%s\"\n", line_num, src_file); return; }