static void callbackTask(void *arg) { int prio = *(int*)arg; cbQueueSet *mySet = &callbackQueue[prio]; taskwdInsert(0, NULL, NULL); epicsEventSignal(startStopEvent); while(!mySet->shutdown) { void *ptr; if (epicsRingPointerIsEmpty(mySet->queue)) epicsEventMustWait(mySet->semWakeUp); while ((ptr = epicsRingPointerPop(mySet->queue))) { CALLBACK *pcallback = (CALLBACK *)ptr; if(!epicsRingPointerIsEmpty(mySet->queue)) epicsEventMustTrigger(mySet->semWakeUp); mySet->queueOverflow = FALSE; (*pcallback->callback)(pcallback); } } if(!epicsAtomicDecrIntT(&mySet->threadsRunning)) epicsEventSignal(startStopEvent); taskwdRemove(0); }
void testTask2(void *arg) { taskwdInsert(0, taskNotify, NULL); testDiag("Task suspending"); epicsThreadSuspendSelf(); epicsThreadSleep(1.0); testDiag("Alive again"); epicsThreadSleep(10.0); taskwdRemove(0); }
static void asInitTask(ASDBCALLBACK *pcallback) { long status; taskwdInsert(epicsThreadGetIdSelf(), wdCallback, (void *)pcallback); status = asInitCommon(); taskwdRemove(epicsThreadGetIdSelf()); asInitTheadId = 0; if(pcallback) { pcallback->status = status; callbackRequest(&pcallback->callback); } }
static void onceTask(void *arg) { taskwdInsert(0, NULL, NULL); epicsEventSignal(startStopEvent); while (TRUE) { void *precord; epicsEventMustWait(onceSem); while ((precord = epicsRingPointerPop(onceQ))) { if (precord == &exitOnce) goto shutdown; dbScanLock(precord); dbProcess(precord); dbScanUnlock(precord); } } shutdown: taskwdRemove(0); epicsEventSignal(startStopEvent); }
static void ClockTimeSync(void *dummy) { taskwdInsert(0, NULL, NULL); for (epicsEventWaitWithTimeout(ClockTimePvt.loopEvent, ClockTimeSyncInterval); ClockTimePvt.synchronize == CLOCKTIME_SYNC; epicsEventWaitWithTimeout(ClockTimePvt.loopEvent, ClockTimeSyncInterval)) { epicsTimeStamp timeNow; int priority; if (generalTimeGetExceptPriority(&timeNow, &priority, LAST_RESORT_PRIORITY) == epicsTimeOK) { struct timespec clockNow; epicsTimeToTimespec(&clockNow, &timeNow); if (clock_settime(CLOCK_REALTIME, &clockNow)) { errlogPrintf("ClockTimeSync: clock_settime failed\n"); continue; } epicsMutexMustLock(ClockTimePvt.lock); if (!ClockTimePvt.synchronized) { ClockTimePvt.startTime = timeNow; ClockTimePvt.synchronized = 1; } ClockTimePvt.syncFromPriority = priority; ClockTimePvt.syncTime = timeNow; epicsMutexUnlock(ClockTimePvt.lock); } } ClockTimePvt.synchronized = 0; taskwdRemove(0); }
/* * destroy_client () */ void destroy_client ( struct client *client ) { if ( ! client ) { return; } if ( client->tid != 0 ) { taskwdRemove ( client->tid ); } if ( client->sock != INVALID_SOCKET ) { epicsSocketDestroy ( client->sock ); } if ( client->proto == IPPROTO_TCP ) { if ( client->send.buf ) { if ( client->send.type == mbtSmallTCP ) { freeListFree ( rsrvSmallBufFreeListTCP, client->send.buf ); } else if ( client->send.type == mbtLargeTCP ) { freeListFree ( rsrvLargeBufFreeListTCP, client->send.buf ); } else { errlogPrintf ( "CAS: Corrupt send buffer free list type code=%u during client cleanup?\n", client->send.type ); } } if ( client->recv.buf ) { if ( client->recv.type == mbtSmallTCP ) { freeListFree ( rsrvSmallBufFreeListTCP, client->recv.buf ); } else if ( client->recv.type == mbtLargeTCP ) { freeListFree ( rsrvLargeBufFreeListTCP, client->recv.buf ); } else { errlogPrintf ( "CAS: Corrupt recv buffer free list type code=%u during client cleanup?\n", client->send.type ); } } } else if ( client->proto == IPPROTO_UDP ) { if ( client->send.buf ) { free ( client->send.buf ); } if ( client->recv.buf ) { free ( client->recv.buf ); } } if ( client->eventqLock ) { epicsMutexDestroy ( client->eventqLock ); } if ( client->chanListLock ) { epicsMutexDestroy ( client->chanListLock ); } if ( client->putNotifyLock ) { epicsMutexDestroy ( client->putNotifyLock ); } if ( client->lock ) { epicsMutexDestroy ( client->lock ); } if ( client->blockSem ) { epicsEventDestroy ( client->blockSem ); } if ( client->pUserName ) { free ( client->pUserName ); } if ( client->pHostName ) { free ( client->pHostName ); } freeListFree ( rsrvClientFreeList, client ); }
void testTask1(void *arg) { taskwdInsert(0, taskNotify, NULL); epicsThreadSleep(10.0); taskwdRemove(0); }
static void NTPTimeSync(void *dummy) { taskwdInsert(0, NULL, NULL); for (epicsEventWaitWithTimeout(NTPTimePvt.loopEvent, NTPTimeSyncInterval); NTPTimePvt.synchronize; epicsEventWaitWithTimeout(NTPTimePvt.loopEvent, NTPTimeSyncInterval)) { int status; struct timespec timespecNow; epicsTimeStamp timeNow; epicsUInt32 tickNow; double diff; double ntpDelta; status = osdNTPGet(×pecNow); tickNow = osdTickGet(); if (status) { if (++NTPTimePvt.syncsFailed > NTPTimeSyncRetries && NTPTimePvt.synchronized) { errlogPrintf("NTPTimeSync: NTP requests failing - %s\n", strerror(errno)); NTPTimePvt.synchronized = 0; } continue; } if (timespecNow.tv_sec <= POSIX_TIME_AT_EPICS_EPOCH || epicsTimeFromTimespec(&timeNow, ×pecNow) == epicsTimeERROR) { errlogPrintf("NTPTimeSync: Bad time received from NTP server\n"); NTPTimePvt.synchronized = 0; continue; } ntpDelta = epicsTimeDiffInSeconds(&timeNow, &NTPTimePvt.syncTime); if (ntpDelta <= 0.0 && NTPTimePvt.synchronized) { errlogPrintf("NTPTimeSync: NTP time not increasing, delta = %g\n", ntpDelta); NTPTimePvt.synchronized = 0; continue; } NTPTimePvt.syncsFailed = 0; if (!NTPTimePvt.synchronized) { errlogPrintf("NTPTimeSync: Sync recovered.\n"); } epicsMutexMustLock(NTPTimePvt.lock); diff = epicsTimeDiffInSeconds(&timeNow, &NTPTimePvt.clockTime); if (diff >= 0.0) { NTPTimePvt.ticksToSkip = 0; } else { /* dont go back in time */ NTPTimePvt.ticksToSkip = -diff * osdTickRateGet(); } NTPTimePvt.clockTick = tickNow; NTPTimePvt.clockTime = timeNow; NTPTimePvt.synchronized = 1; epicsMutexUnlock(NTPTimePvt.lock); NTPTimePvt.tickRate = (tickNow - NTPTimePvt.syncTick) / ntpDelta; NTPTimePvt.syncTick = tickNow; NTPTimePvt.syncTime = timeNow; } NTPTimePvt.synchronized = 0; taskwdRemove(0); }
/* * ss_entry() - Thread entry point for all state sets. * Provides the main loop for state set processing. */ static void ss_entry(void *arg) { SSCB *ss = (SSCB *)arg; PROG *sp = ss->prog; /* Attach to PV system; was already done for the first state set */ if (ss != sp->ss) { ss->threadId = epicsThreadGetIdSelf(); createOrAttachPvSystem(sp); } /* Register this thread with the EPICS watchdog (no callback func) */ taskwdInsert(ss->threadId, 0, 0); /* In safe mode, update local var buffer with global one before entering the event loop. Must do this using ss_read_all_buffer since CA and other state sets could already post events resp. pvPut. */ if (optTest(sp, OPT_SAFE)) ss_read_all_buffer(sp, ss); /* Initial state is the first one */ ss->currentState = 0; ss->nextState = -1; ss->prevState = -1; DEBUG("ss %s: entering main loop\n", ss->ssName); /* * ============= Main loop ============== */ while (TRUE) { boolean ev_trig; int transNum = 0; /* highest prio trans. # triggered */ STATE *st = ss->states + ss->currentState; double now; /* Set state to current state */ assert(ss->currentState >= 0); /* Set state set event mask to this state's event mask */ ss->mask = st->eventMask; /* If we've changed state, do any entry actions. Also do these * even if it's the same state if option to do so is enabled. */ if (st->entryFunc && (ss->prevState != ss->currentState || optTest(st, OPT_DOENTRYFROMSELF))) { st->entryFunc(ss); } /* Flush any outstanding DB requests */ pvSysFlush(sp->pvSys); /* Setting this semaphore here guarantees that a when() is * always executed at least once when a state is first entered. */ epicsEventSignal(ss->syncSem); pvTimeGetCurrentDouble(&now); /* Set time we entered this state if transition from a different * state or else if option not to do so is off for this state. */ if ((ss->currentState != ss->prevState) || !optTest(st, OPT_NORESETTIMERS)) { ss->timeEntered = now; } ss->wakeupTime = epicsINF; /* Loop until an event is triggered, i.e. when() returns TRUE */ do { /* Wake up on PV event, event flag, or expired delay */ DEBUG("before epicsEventWaitWithTimeout(ss=%d,timeout=%f)\n", ss - sp->ss, ss->wakeupTime - now); epicsEventWaitWithTimeout(ss->syncSem, ss->wakeupTime - now); DEBUG("after epicsEventWaitWithTimeout()\n"); /* Check whether we have been asked to exit */ if (sp->die) goto exit; /* Copy dirty variable values from CA buffer * to user (safe mode only). */ if (optTest(sp, OPT_SAFE)) ss_read_all_buffer(sp, ss); ss->wakeupTime = epicsINF; /* Check state change conditions */ ev_trig = st->eventFunc(ss, &transNum, &ss->nextState); /* Clear all event flags (old ef mode only) */ if (ev_trig && !optTest(sp, OPT_NEWEF)) { unsigned i; for (i = 0; i < NWORDS(sp->numEvFlags); i++) { sp->evFlags[i] &= ~ss->mask[i]; } } if (!ev_trig) pvTimeGetCurrentDouble(&now); } while (!ev_trig); /* Execute the state change action */ st->actionFunc(ss, transNum, &ss->nextState); /* Check whether we have been asked to exit */ if (sp->die) goto exit; /* If changing state, do exit actions */ if (st->exitFunc && (ss->currentState != ss->nextState || optTest(st, OPT_DOEXITTOSELF))) { st->exitFunc(ss); } /* Change to next state */ ss->prevState = ss->currentState; ss->currentState = ss->nextState; } /* Thread exit has been requested */ exit: taskwdRemove(ss->threadId); /* Declare ourselves dead */ if (ss != sp->ss) epicsEventSignal(ss->dead); }
static void periodicTask(void *arg) { periodic_scan_list *ppsl = (periodic_scan_list *)arg; 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) { 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); } taskwdRemove(0); epicsEventSignal(startStopEvent); }
static void dbCaTask(void *arg) { taskwdInsert(0, NULL, NULL); SEVCHK(ca_context_create(ca_enable_preemptive_callback), "dbCaTask calling ca_context_create"); dbCaClientContext = ca_current_context (); SEVCHK(ca_add_exception_event(exceptionCallback,NULL), "ca_add_exception_event"); epicsEventSignal(startStopEvent); /* channel access event loop */ while (TRUE){ do { epicsEventMustWait(workListEvent); } while (dbCaCtl == ctlPause); while (TRUE) { /* process all requests in workList*/ caLink *pca; short link_action; int status; epicsMutexMustLock(workListLock); if (!(pca = (caLink *)ellGet(&workList))){ /* Take off list head */ epicsMutexUnlock(workListLock); if (dbCaCtl == ctlExit) goto shutdown; break; /* workList is empty */ } link_action = pca->link_action; pca->link_action = 0; if (link_action & CA_CLEAR_CHANNEL) --removesOutstanding; epicsMutexUnlock(workListLock); /* Give back immediately */ if (link_action & CA_CLEAR_CHANNEL) { /* This must be first */ dbCaLinkFree(pca); /* No alarm is raised. Since link is changing so what? */ continue; /* No other link_action makes sense */ } if (link_action & CA_CONNECT) { status = ca_create_channel( pca->pvname,connectionCallback,(void *)pca, CA_PRIORITY_DB_LINKS, &(pca->chid)); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_create_channel %s\n", ca_message(status)); printLinks(pca); continue; } dbca_chan_count++; status = ca_replace_access_rights_event(pca->chid, accessRightsCallback); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask replace_access_rights_event %s\n", ca_message(status)); printLinks(pca); } continue; /*Other options must wait until connect*/ } if (ca_state(pca->chid) != cs_conn) continue; if (link_action & CA_WRITE_NATIVE) { assert(pca->pputNative); if (pca->putType == CA_PUT) { status = ca_array_put( pca->dbrType, pca->nelements, pca->chid, pca->pputNative); } else if (pca->putType==CA_PUT_CALLBACK) { status = ca_array_put_callback( pca->dbrType, pca->nelements, pca->chid, pca->pputNative, putCallback, pca); } else { status = ECA_PUTFAIL; } if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_array_put %s\n", ca_message(status)); printLinks(pca); } epicsMutexMustLock(pca->lock); if (status == ECA_NORMAL) pca->newOutNative = FALSE; epicsMutexUnlock(pca->lock); } if (link_action & CA_WRITE_STRING) { assert(pca->pputString); if (pca->putType == CA_PUT) { status = ca_array_put( DBR_STRING, 1, pca->chid, pca->pputString); } else if (pca->putType==CA_PUT_CALLBACK) { status = ca_array_put_callback( DBR_STRING, 1, pca->chid, pca->pputString, putCallback, pca); } else { status = ECA_PUTFAIL; } if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_array_put %s\n", ca_message(status)); printLinks(pca); } epicsMutexMustLock(pca->lock); if (status == ECA_NORMAL) pca->newOutString = FALSE; epicsMutexUnlock(pca->lock); } /*CA_GET_ATTRIBUTES before CA_MONITOR so that attributes available * before the first monitor callback */ if (link_action & CA_GET_ATTRIBUTES) { status = ca_get_callback(DBR_CTRL_DOUBLE, pca->chid, getAttribEventCallback, pca); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_get_callback %s\n", ca_message(status)); printLinks(pca); } } if (link_action & CA_MONITOR_NATIVE) { size_t element_size; element_size = dbr_value_size[ca_field_type(pca->chid)]; epicsMutexMustLock(pca->lock); pca->pgetNative = dbCalloc(pca->nelements, element_size); epicsMutexUnlock(pca->lock); 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); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_add_array_event %s\n", ca_message(status)); printLinks(pca); } } if (link_action & CA_MONITOR_STRING) { epicsMutexMustLock(pca->lock); 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); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_add_array_event %s\n", ca_message(status)); printLinks(pca); } } } SEVCHK(ca_flush_io(), "dbCaTask"); } shutdown: taskwdRemove(0); if (dbca_chan_count == 0) ca_context_destroy(); else fprintf(stderr, "dbCa: chan_count = %d at shutdown\n", dbca_chan_count); epicsEventSignal(startStopEvent); }