From 7c63c82474b658d4093938b41300e0395be5ef6b Mon Sep 17 00:00:00 2001 From: zimoch Date: Wed, 27 Nov 2013 13:37:10 +0000 Subject: [PATCH] merge with 3.14.12-pre1 but keep our named events --- src/db/dbScan.c | 79 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 13 deletions(-) diff --git a/src/db/dbScan.c b/src/db/dbScan.c index 1720a5d85..085f66f9d 100644 --- a/src/db/dbScan.c +++ b/src/db/dbScan.c @@ -50,12 +50,12 @@ /* Task Control */ -enum ctl {ctlRun, ctlPause, ctlExit}; +enum ctl {ctlInit, ctlRun, ctlPause, ctlExit}; /* Task Startup/Shutdown Synchronization */ static epicsEventId startStopEvent; -volatile enum ctl scanCtl; +static volatile enum ctl scanCtl; /* SCAN ONCE */ @@ -82,9 +82,13 @@ typedef struct scan_element{ /* PERIODIC */ +#define OVERRUN_REPORT_DELAY 10.0 /* Time between initial reports */ +#define OVERRUN_REPORT_MAX 3600.0 /* Maximum time between reports */ typedef struct periodic_scan_list { scan_list scan_list; double period; + const char *name; + unsigned long overruns; volatile enum ctl scanCtl; epicsEventId loopEvent; } periodic_scan_list; @@ -350,7 +354,8 @@ int scanppl(double period) /* print periodic list */ ppsl = papPeriodic[i]; if (ppsl == NULL) continue; if (period > 0.0 && (fabs(period - ppsl->period) >.05)) continue; - sprintf(message, "Scan Period = %g seconds ", ppsl->period); + sprintf(message, "Records with SCAN = '%s' (%lu over-runs):", + ppsl->name, ppsl->overruns); printList(&ppsl->scan_list, message); } return 0; @@ -560,19 +565,67 @@ static void initOnce(void) static void periodicTask(void *arg) { periodic_scan_list *ppsl = (periodic_scan_list *)arg; - - epicsTimeStamp start_time, end_time; - double delay; + epicsTimeStamp next, reported; + unsigned int overruns = 0; + double report_delay = OVERRUN_REPORT_DELAY; + double overtime = 0.0; + double over_min = 0.0; + double over_max = 0.0; + const double penalty = (ppsl->period >= 2) ? 1 : (ppsl->period / 2); taskwdInsert(0, NULL, NULL); epicsEventSignal(startStopEvent); + epicsTimeGetCurrent(&next); + reported = next; + while (ppsl->scanCtl != ctlExit) { - epicsTimeGetCurrent(&start_time); - if (ppsl->scanCtl == ctlRun) scanList(&ppsl->scan_list); - epicsTimeGetCurrent(&end_time); - delay = ppsl->period - epicsTimeDiffInSeconds(&end_time, &start_time); - if (delay <= 0.0) delay = 0.1; + double delay; + epicsTimeStamp now; + + if (ppsl->scanCtl == ctlRun) + scanList(&ppsl->scan_list); + + epicsTimeAddSeconds(&next, ppsl->period); + epicsTimeGetCurrent(&now); + delay = epicsTimeDiffInSeconds(&next, &now); + if (delay <= 0.0) { + if (overtime == 0.0) { + overtime = over_min = over_max = -delay; + } + else { + overtime -= delay; + if (over_min + delay > 0) + over_min = -delay; + if (over_max + delay < 0) + over_max = -delay; + } + delay = penalty; + ppsl->overruns++; + next = now; + epicsTimeAddSeconds(&next, delay); + if (++overruns >= 10 && + epicsTimeDiffInSeconds(&now, &reported) > report_delay) { + errlogPrintf("\ndbScan warning from '%s' scan thread:\n" + "\tScan processing averages %.2f seconds (%.2f .. %.2f).\n" + "\tOver-runs have now happened %u times in a row.\n" + "\tTo fix this, move some records to a slower scan rate.\n", + ppsl->name, ppsl->period + overtime / overruns, + ppsl->period + over_min, ppsl->period + over_max, overruns); + + reported = now; + if (report_delay < (OVERRUN_REPORT_MAX / 2)) + report_delay *= 2; + else + report_delay = OVERRUN_REPORT_MAX; + } + } + else { + overruns = 0; + report_delay = OVERRUN_REPORT_DELAY; + overtime = 0.0; + } + epicsEventWaitWithTimeout(ppsl->loopEvent, delay); } @@ -600,8 +653,8 @@ static void initPeriodic(void) ppsl->scan_list.lock = epicsMutexMustCreate(); ellInit(&ppsl->scan_list.list); - epicsScanDouble(pmenu->papChoiceValue[i + SCAN_1ST_PERIODIC], - &ppsl->period); + ppsl->name = pmenu->papChoiceValue[i + SCAN_1ST_PERIODIC]; + epicsScanDouble(ppsl->name, &ppsl->period); ppsl->scanCtl = ctlPause; ppsl->loopEvent = epicsEventMustCreate(epicsEventEmpty);