From 3c16c3c0dab8218cbc5b6d7d416489ea3c1d85fc Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Jun 2012 17:02:23 -0400 Subject: [PATCH 1/6] Cherry-picking d2b0e920 from 3.15 (closes lp:1773373) --- src/db/dbEvent.c | 82 ++++++++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/src/db/dbEvent.c b/src/db/dbEvent.c index ee1673547..6faf82076 100644 --- a/src/db/dbEvent.c +++ b/src/db/dbEvent.c @@ -90,7 +90,8 @@ struct event_user { epicsMutexId lock; epicsEventId ppendsem; /* Wait while empty */ epicsEventId pflush_sem; /* wait for flush */ - + epicsEventId pexitsem; /* wait for event task to join */ + EXTRALABORFUNC *extralabor_sub;/* off load to event task */ void *extralabor_arg;/* parameter to above */ @@ -293,36 +294,45 @@ dbEventCtx epicsShareAPI db_init_events (void) if (!evUser) { return NULL; } - + + /* Flag will be cleared when event task starts */ + evUser->pendexit = TRUE; + evUser->firstque.evUser = evUser; evUser->firstque.writelock = epicsMutexCreate(); - if (!evUser->firstque.writelock) { - return NULL; - } + if (!evUser->firstque.writelock) + goto fail; evUser->ppendsem = epicsEventCreate(epicsEventEmpty); - if (!evUser->ppendsem) { - epicsMutexDestroy (evUser->firstque.writelock); - return NULL; - } + if (!evUser->ppendsem) + goto fail; evUser->pflush_sem = epicsEventCreate(epicsEventEmpty); - if (!evUser->pflush_sem) { - epicsMutexDestroy (evUser->firstque.writelock); - epicsEventDestroy (evUser->ppendsem); - return NULL; - } + if (!evUser->pflush_sem) + goto fail; evUser->lock = epicsMutexCreate(); - if (!evUser->lock) { - epicsMutexDestroy (evUser->firstque.writelock); - epicsEventDestroy (evUser->pflush_sem); - epicsEventDestroy (evUser->ppendsem); - return NULL; - } + if (!evUser->lock) + goto fail; + evUser->pexitsem = epicsEventCreate(epicsEventEmpty); + if (!evUser->pexitsem) + goto fail; evUser->flowCtrlMode = FALSE; evUser->extraLaborBusy = FALSE; evUser->pSuicideEvent = NULL; return (dbEventCtx) evUser; +fail: + if(evUser->lock) + epicsMutexDestroy (evUser->lock); + if(evUser->firstque.writelock) + epicsMutexDestroy (evUser->firstque.writelock); + if(evUser->ppendsem) + epicsEventDestroy (evUser->ppendsem); + if(evUser->pflush_sem) + epicsEventDestroy (evUser->pflush_sem); + if(evUser->pexitsem) + epicsEventDestroy (evUser->pexitsem); + freeListFree(dbevEventUserFreeList,evUser); + return NULL; } /* @@ -346,10 +356,26 @@ void epicsShareAPI db_close_events (dbEventCtx ctx) * hazardous to the system's health. */ epicsMutexMustLock ( evUser->lock ); - evUser->pendexit = TRUE; + if(!evUser->pendexit) { /* event task running */ + evUser->pendexit = TRUE; + epicsMutexUnlock ( evUser->lock ); + + /* notify the waiting task */ + epicsEventSignal(evUser->ppendsem); + /* wait for task to exit */ + epicsEventMustWait(evUser->pexitsem); + + epicsMutexMustLock ( evUser->lock ); + } + epicsMutexUnlock ( evUser->lock ); - /* notify the waiting task */ - epicsEventSignal(evUser->ppendsem); + + epicsEventDestroy(evUser->pexitsem); + epicsEventDestroy(evUser->ppendsem); + epicsEventDestroy(evUser->pflush_sem); + epicsMutexDestroy(evUser->lock); + + freeListFree(dbevEventUserFreeList, evUser); } /* @@ -977,14 +1003,10 @@ static void event_task (void *pParm) } } - epicsEventDestroy(evUser->ppendsem); - epicsEventDestroy(evUser->pflush_sem); - epicsMutexDestroy(evUser->lock); - - freeListFree(dbevEventUserFreeList, evUser); - taskwdRemove(epicsThreadGetIdSelf()); + epicsEventSignal(evUser->pexitsem); + return; } @@ -1008,7 +1030,6 @@ int epicsShareAPI db_start_events ( return DB_EVENT_OK; } - evUser->pendexit = FALSE; evUser->init_func = init_func; evUser->init_func_arg = init_func_arg; if (!taskname) { @@ -1022,6 +1043,7 @@ int epicsShareAPI db_start_events ( epicsMutexUnlock ( evUser->lock ); return DB_EVENT_ERROR; } + evUser->pendexit = FALSE; epicsMutexUnlock ( evUser->lock ); return DB_EVENT_OK; } From b558bd9b16b9a9a299025eb6019dca9a9f0647a3 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Thu, 7 Jun 2018 11:21:04 +0200 Subject: [PATCH 2/6] Cherry-picking e794639e from 3.15 (lp:1730982 lp:1762543) --- src/db/dbEvent.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/db/dbEvent.c b/src/db/dbEvent.c index 6faf82076..9389644fd 100644 --- a/src/db/dbEvent.c +++ b/src/db/dbEvent.c @@ -135,7 +135,9 @@ static char *EVENT_PEND_NAME = "eventTask"; static struct evSubscrip canceledEvent; -static unsigned short ringSpace ( const struct event_que *pevq ) +static epicsMutexId stopSync; + +static unsigned short ringSpace ( const struct event_que *pevq ) { if ( pevq->evque[pevq->putix] == EVENTQEMPTY ) { if ( pevq->getix > pevq->putix ) { @@ -275,7 +277,11 @@ int epicsShareAPI dbel ( const char *pname, unsigned level ) dbEventCtx epicsShareAPI db_init_events (void) { struct event_user * evUser; - + + if (!stopSync) { + stopSync = epicsMutexMustCreate(); + } + if (!dbevEventUserFreeList) { freeListInitPvt(&dbevEventUserFreeList, sizeof(struct event_user),8); @@ -335,6 +341,8 @@ fail: return NULL; } + + /* intentionally leak stopSync to avoid possible shutdown races */ /* * DB_CLOSE_EVENTS() * @@ -370,11 +378,15 @@ void epicsShareAPI db_close_events (dbEventCtx ctx) epicsMutexUnlock ( evUser->lock ); + epicsMutexMustLock (stopSync); + epicsEventDestroy(evUser->pexitsem); epicsEventDestroy(evUser->ppendsem); epicsEventDestroy(evUser->pflush_sem); epicsMutexDestroy(evUser->lock); + epicsMutexUnlock (stopSync); + freeListFree(dbevEventUserFreeList, evUser); } @@ -1005,8 +1017,15 @@ static void event_task (void *pParm) taskwdRemove(epicsThreadGetIdSelf()); + /* use stopSync to ensure pexitsem is not destroy'd + * until epicsEventSignal() has returned. + */ + epicsMutexMustLock (stopSync); + epicsEventSignal(evUser->pexitsem); + epicsMutexUnlock(stopSync); + return; } From e459e8bdd40c6e8fe75ee02a6b3f4292672f82e4 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Thu, 7 Jun 2018 11:32:16 +0200 Subject: [PATCH 3/6] cas: don't spin on zero-length search requests (fix lp:1743321) --- src/cas/generic/casDGClient.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cas/generic/casDGClient.cc b/src/cas/generic/casDGClient.cc index 3bb32c3e2..32a403604 100644 --- a/src/cas/generic/casDGClient.cc +++ b/src/cas/generic/casDGClient.cc @@ -646,6 +646,11 @@ caStatus casDGClient::processDG () if ( status != S_cas_success ) { break; } + + if ( this->in.bytesPresent () > 0 && dgInBytesConsumed == 0 && status == S_cas_success ) { + this->in.removeMsg ( this->in.bytesPresent() ); + } + } return status; } From 8144d2ea01bf95585ad938723ce2b7010755befc Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 26 Jun 2018 14:47:59 -0500 Subject: [PATCH 4/6] Add HOWTO: Converting Wiki Record Reference to POD --- documentation/RELEASE_NOTES.html | 9 ++ src/tools/dbdToHtml.pl | 146 +++++++++++++++++++++++++++++-- 2 files changed, 149 insertions(+), 6 deletions(-) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 710798082..59cd4ce18 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -16,7 +16,16 @@ +

HOWTO: Converting Wiki Record Reference to POD

+ +

Some documentation has been added to the dbdToHtml.pl script +explaining how Perl POD (Plain Old Documentation) markup can be added to +.dbd files to generate HTML documentation for the record types. To see +these instructions, run perl bin/<host>/dbdToHtml.pl -H +or perldoc bin/<host>/dbdToHtml.pl.

+

Fix problem with numeric soft events

+

Changing from numeric to named soft events introduced an incompatibility when a numeric event 1-255 is converted from a DOUBLE, e.g. from a calc record. The post_event() API is not marked deprecated any more. diff --git a/src/tools/dbdToHtml.pl b/src/tools/dbdToHtml.pl index fac850a7e..d30779dcf 100644 --- a/src/tools/dbdToHtml.pl +++ b/src/tools/dbdToHtml.pl @@ -41,19 +41,69 @@ BEGIN { } } -my $tool = 'dbdToHtml'; +use Pod::Usage; -our ($opt_D, @opt_I, $opt_o); -getopts('DI@o:') or - die "Usage: $tool [-D] [-I dir] [-o file.html] file.dbd.pod\n"; +=head1 NAME + +dbdToHtml.pl - Convert DBD file with POD to HTML + +=head1 SYNOPSIS + +B [B<-h>] [B<-D>] [B<-I> dir] [B<-o> file] file.dbd.pod + +=head1 DESCRIPTION + +Generates HTML documentation from a B<.dbd.pod> file. + +=head1 OPTIONS + +B understands the following options: + +=over 4 + +=item B<-h> + +Help, display usage information. + +=item B<-H> + +Conversion help, display information about converting reference documentation +from the EPICS Wiki into a B<.dbd.pod> file for use with this tool. + +=item B<-D> + +Instead of creating the output file as described, read the input file(s) and +print a B dependency rule for the output file(s) to stdout. + +=item B<-o> file + +Name of the output file to be created. + +=back + +If no output filename is set, the file created will be named after the input +file, removing any directory components in the path and replacing any +B<.dbd.pod> file extension with B<.html>. + +=cut + +our ($opt_h, $opt_H, $opt_D, @opt_I, $opt_o); + +my $tool = 'dbdToHtml.pl'; + +getopts('hHDI@o:') or + pod2usage(2); +pod2usage(-verbose => 2) if $opt_H; +pod2usage(1) if $opt_h; +pod2usage("$tool: No input file given.\n") if @ARGV != 1; my $dbd = DBD->new(); my $infile = shift @ARGV; $infile =~ m/\.dbd.pod$/ or - die "$tool: Input file '$infile' must have '.dbd.pod' extension\n"; + pod2usage("$tool: Input file '$infile' must have '.dbd.pod' extension.\n"); -&ParseDBD($dbd, &Readfile($infile, 0, \@opt_I)); +ParseDBD($dbd, Readfile($infile, 0, \@opt_I)); if (!$opt_o) { ($opt_o = $infile) =~ s/\.dbd\.pod$/.html/; @@ -243,3 +293,87 @@ sub DBD::Recfield::writable { return $fld->dbf_type eq "DBF_NOACCESS" ? 'No' : 'Yes'; } +=pod + +=head1 Converting Wiki Record Reference to POD + +If you open the src/std/rec/aiRecord.dbd.pod file in your favourite plain text +editor you'll see what input was required to generate the aiRecord.html file. +The text markup language we're using is a standard called POD (Plain Old +Documentation) which is used by Perl developers, but you don't need to know Perl +at all to be able to use it. + +When we add POD markup to a record type, we rename its *Record.dbd file to +.dbd.pod in the src/std/rec directory; no other changes are needed for the build +system to find it by its new name. The POD content is effectively just a new +kind of comment that appears in .dbd.pod files, which the formatter knows how to +convert into HTML. The build also generates a plain *Record.dbd file from this +same input file by stripping out all of the POD markup. + +Documentation for Perl's POD markup standard can be found online at +L or you may be able to type 'perldoc +perlpod' into a Linux command-line to see the same text. We added a few POD +keywords of our own to handle the table generation, and I'll cover those briefly +below. + +POD text can appear almost anywhere in a dbd.pod file. It always starts with a +line "=[keyword] [additional text...]" where [keyword] is "title", "head1" +through "head4" etc.. The POD text ends with a line "=cut". There must be a +blank line above every POD line, and in many cases below it as well. + +The POD keywords we have added are "title", "recordtype", "menu", "fields", +"type", "read" and "write". The last 3 are less common but are used in some of +the other record types such as the waveform and aSub records. + +The most interesting of our new keywords is "fields", which takes a list of +record field names on the same line after the keyword and generates an HTML +Table describing those fields based on the field description found in the DBD +parts. In the ai documentation the first such table covers the DTYP and INP +fields, so the line + + =fields DTYP, INP + +generates all this in the output: + +

+ + + + + + + + + + + + + + + + + + + + + + + +
FieldSummaryTypeDCTDefaultReadWriteCA PP
DTYPDevice TypeDEVICEYes YesYesNo
INPInput SpecificationINLINKYes YesYesNo
+ +Note that the "=fields" line must appear inside the DBD's declaration of the +record type, i.e. after the line + + recordtype(ai) { + +The "type", "read" and "write" POD keywords are used inside an individual record +field declaration and provide information for the "Type", "Read" and "Write" +columns of the field's table output for fields where this information is +normally supplied by the record support code. Usage examples for these keywords +can be found in the aai and aSub record types. + +If you look at the L file you'll see that the POD there starts +by documenting a record-specific menu definition. The "menu" keyword generates a +table that lists all the choices found in the named menu. + +=cut From f892731b3f8a6d621dee57993a5d4438515e3965 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 29 Jun 2018 15:03:45 -0500 Subject: [PATCH 5/6] Fix epicsCalcTest for gcc 7.1.0 on minGW Another case where the compile-time evaluation returns +1 but at run-time isnan() returns -1. --- src/libCom/test/epicsCalcTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libCom/test/epicsCalcTest.cpp b/src/libCom/test/epicsCalcTest.cpp index 1ebc0c578..2492c95ba 100644 --- a/src/libCom/test/epicsCalcTest.cpp +++ b/src/libCom/test/epicsCalcTest.cpp @@ -391,7 +391,7 @@ MAIN(epicsCalcTest) testExpr(isnan(0.)); testExpr(isnan(Inf)); testExpr(isnan(-Inf)); - testExpr(isnan(NaN)); + testExpr(!!isnan(NaN)); // As above testCalc("isnan(0,1,2)", 0); testCalc("isnan(0,1,NaN)", 1); testCalc("isnan(0,NaN,2)", 1); From 31fc35fbe8a8a81e2c064142c5b22719cefd1915 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 13 Jul 2018 13:05:54 -0500 Subject: [PATCH 6/6] dbCa: Fix for lp: #541221 I'd looked at this a few times since it was reported, but never actually fixed the bug I described in the comments. Apparently the only thing left to do was to store the eventId and use it to clear the subscription when we saw a type-change to a PV. --- src/db/dbCa.c | 21 ++++++++++++++------- src/db/dbCaPvt.h | 2 ++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/db/dbCa.c b/src/db/dbCa.c index aaaaa4b5c..610ce9d89 100644 --- a/src/db/dbCa.c +++ b/src/db/dbCa.c @@ -591,11 +591,16 @@ static void connectionCallback(struct connection_handler_args arg) if (pca->gotFirstConnection) { if (pca->nelements != ca_element_count(arg.chid) || pca->dbrType != ca_field_type(arg.chid)) { - /* BUG: We have no way to clear any old subscription with the - * originally chosen data type/size. That will continue - * to send us data and will result in an assert() fail. - */ - /* Let next dbCaGetLink and/or dbCaPutLink determine options */ + /* Size or type changed, clear everything and let the next call + to dbCaGetLink() and/or dbCaPutLink() reset everything */ + if (pca->evidNative) { + ca_clear_event(pca->evidNative); + pca->evidNative = 0; + } + if (pca->evidString) { + ca_clear_event(pca->evidString); + pca->evidString = 0; + } plink->value.pv_link.pvlMask &= ~(pvlOptInpNative | pvlOptInpString | pvlOptOutNative | pvlOptOutString); @@ -969,7 +974,8 @@ static void dbCaTask(void *arg) status = ca_add_array_event( ca_field_type(pca->chid)+DBR_TIME_STRING, ca_element_count(pca->chid), - pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0); + pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, + &pca->evidNative); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_add_array_event %s\n", ca_message(status)); @@ -981,7 +987,8 @@ static void dbCaTask(void *arg) pca->pgetString = dbCalloc(1, MAX_STRING_SIZE); epicsMutexUnlock(pca->lock); status = ca_add_array_event(DBR_TIME_STRING, 1, - pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0); + pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, + &pca->evidString); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_add_array_event %s\n", ca_message(status)); diff --git a/src/db/dbCaPvt.h b/src/db/dbCaPvt.h index a0a1f65a0..58e9afda1 100644 --- a/src/db/dbCaPvt.h +++ b/src/db/dbCaPvt.h @@ -73,6 +73,8 @@ typedef struct caLink char *pgetString; void *pputNative; char *pputString; + evid evidNative; + evid evidString; char gotInNative; char gotInString; char gotOutNative;