epicsShareFunc void taskwdShow(int level) { struct tNode *pt; int mCount, fCount, tCount; char tName[40]; epicsMutexMustLock(mLock); mCount = ellCount(&mList); epicsMutexUnlock(mLock); epicsMutexMustLock(fLock); fCount = ellCount(&fList); epicsMutexUnlock(fLock); epicsMutexMustLock(tLock); tCount = ellCount(&tList); printf("%d monitors, %d threads registered, %d free nodes\n", mCount, tCount, fCount); if (level) { printf("%16.16s %9s %12s %12s %12s\n", "THREAD NAME", "STATE", "EPICS TID", "CALLBACK", "USR ARG"); pt = (struct tNode *)ellFirst(&tList); while (pt != NULL) { epicsThreadGetName(pt->tid, tName, sizeof(tName)); printf("%16.16s %9s %12p %12p %12p\n", tName, pt->suspended ? "Suspended" : "Ok ", (void *)pt->tid, (void *)pt->callback, pt->usr); pt = (struct tNode *)ellNext(&pt->node); } } epicsMutexUnlock(tLock); }
void ThreadList::dump() const { char name[100]; epicsThreadGetName(thread, name, sizeof(name)); fprintf(stderr, "Thread '%s': ", name); bool first = true; stdList<const OrderedMutex *>::const_iterator i; for (i = locks.begin(); i != locks.end(); ++i) { const OrderedMutex *l = *i; if (first) first = false; else fprintf(stderr, ", "); fprintf(stderr, "'%s' (%zu)", l->getName().c_str(), l->getOrder()); } printf("\n"); }
static void twdTask(void *arg) { struct tNode *pt; struct mNode *pm; while (twdCtl != twdctlExit) { if (twdCtl == twdctlRun) { epicsMutexMustLock(tLock); pt = (struct tNode *)ellFirst(&tList); while (pt) { int susp = epicsThreadIsSuspended(pt->tid); if (susp != pt->suspended) { epicsMutexMustLock(mLock); pm = (struct mNode *)ellFirst(&mList); while (pm) { if (pm->funcs->notify) { pm->funcs->notify(pm->usr, pt->tid, susp); } pm = (struct mNode *)ellNext(&pm->node); } epicsMutexUnlock(mLock); if (susp) { char tName[40]; epicsThreadGetName(pt->tid, tName, sizeof(tName)); errlogPrintf("Thread %s (%p) suspended\n", tName, (void *)pt->tid); if (pt->callback) { pt->callback(pt->usr); } } pt->suspended = susp; } pt = (struct tNode *)ellNext(&pt->node); } epicsMutexUnlock(tLock); } epicsEventWaitWithTimeout(loopEvent, TASKWD_DELAY); } epicsEventSignal(exitEvent); }
void epicsEventShow(epicsEventId id, unsigned int level) { #if __RTEMS_VIOLATE_KERNEL_VISIBILITY__ rtems_id sid = (rtems_id)id; Semaphore_Control *the_semaphore; Semaphore_Control semaphore; Objects_Locations location; the_semaphore = _Semaphore_Get (sid, &location); if (location != OBJECTS_LOCAL) return; /* * Yes, there's a race condition here since an interrupt might * change things while the copy is in progress, but the information * is only for display, so it's not that critical. */ semaphore = *the_semaphore; _Thread_Enable_dispatch(); printf (" %8.8x ", (int)sid); if (_Attributes_Is_counting_semaphore (semaphore.attribute_set)) { printf ("Count: %d", (int)semaphore.Core_control.semaphore.count); } else { if (_CORE_mutex_Is_locked(&semaphore.Core_control.mutex)) { char name[30]; epicsThreadGetName ((epicsThreadId)semaphore.Core_control.mutex.holder_id, name, sizeof name); printf ("Held by:%8.8x (%s) Nest count:%d", (unsigned int)semaphore.Core_control.mutex.holder_id, name, (int)semaphore.Core_control.mutex.nest_count); } else { printf ("Not Held"); } } printf ("\n"); #endif }
void taskwdRemove(epicsThreadId tid) { struct tNode *pt; struct mNode *pm; char tName[40]; taskwdInit(); if (tid == 0) tid = epicsThreadGetIdSelf(); epicsMutexMustLock(tLock); pt = (struct tNode *)ellFirst(&tList); while (pt != NULL) { if (tid == pt->tid) { ellDelete(&tList, (void *)pt); epicsMutexUnlock(tLock); freeNode((union twdNode *)pt); epicsMutexMustLock(mLock); pm = (struct mNode *)ellFirst(&mList); while (pm) { if (pm->funcs->remove) { pm->funcs->remove(pm->usr, tid); } pm = (struct mNode *)ellNext(&pm->node); } epicsMutexUnlock(mLock); return; } pt = (struct tNode *)ellNext(&pt->node); } epicsMutexUnlock(tLock); epicsThreadGetName(tid, tName, sizeof(tName)); errlogPrintf("taskwdRemove: Thread %s (%p) not registered!\n", tName, (void *)tid); }
/* * sequencer() - Sequencer main thread entry point. */ void sequencer (void *arg) /* ptr to original (global) state program table */ { PROG *sp = (PROG *)arg; unsigned nss; size_t threadLen; char threadName[THREAD_NAME_SIZE+10]; /* Get this thread's id */ sp->ss->threadId = epicsThreadGetIdSelf(); /* Add the program to the program list */ seqAddProg(sp); createOrAttachPvSystem(sp); if (!pvSysIsDefined(sp->pvSys)) { sp->die = TRUE; goto exit; } /* Call sequencer init function to initialize variables. */ sp->initFunc(sp); /* Initialize state set variables. In safe mode, copy variable block to state set buffers. Must do all this before connecting. */ if (optTest(sp, OPT_SAFE)) { for (nss = 0; nss < sp->numSS; nss++) { SSCB *ss = sp->ss + nss; memcpy(ss->var, sp->var, sp->varSize); } } /* Attach to PV system */ pvSysAttach(sp->pvSys); /* Initiate connect & monitor requests to database channels, waiting for all connections to be established if the option is set. */ if (seq_connect(sp, optTest(sp, OPT_CONN) != pvStatOK)) goto exit; /* Emulate the 'first monitor event' for anonymous PVs */ if (optTest(sp, OPT_SAFE)) { unsigned nch; for (nch=0; nch<sp->numChans; nch++) if (sp->chan[nch].syncedTo && !sp->chan[nch].dbch) seq_efSet(sp->ss, sp->chan[nch].syncedTo); } /* Call program entry function if defined. Treat as if called from 1st state set. */ if (sp->entryFunc) sp->entryFunc(sp->ss); /* Create each additional state set task (additional state set thread names are derived from the first ss) */ epicsThreadGetName(sp->ss->threadId, threadName, sizeof(threadName)); threadLen = strlen(threadName); for (nss = 1; nss < sp->numSS; nss++) { SSCB *ss = sp->ss + nss; epicsThreadId tid; /* Form thread name from program name + state set number */ sprintf(threadName+threadLen, "_%d", nss); /* Spawn the task */ tid = epicsThreadCreate( threadName, /* thread name */ sp->threadPriority, /* priority */ sp->stackSize, /* stack size */ ss_entry, /* entry point */ ss); /* parameter */ DEBUG("Spawning additional state set thread %p: \"%s\"\n", tid, threadName); } /* First state set jumps directly to entry point */ ss_entry(sp->ss); DEBUG(" Wait for other state sets to exit\n"); for (nss = 1; nss < sp->numSS; nss++) { SSCB *ss = sp->ss + nss; epicsEventMustWait(ss->dead); } /* Call program exit function if defined. Treat as if called from 1st state set. */ if (sp->exitFunc) sp->exitFunc(sp->ss); exit: DEBUG(" Disconnect all channels\n"); seq_disconnect(sp); DEBUG(" Remove program instance from list\n"); seqDelProg(sp); errlogSevPrintf(errlogInfo, "Instance %d of sequencer program \"%s\" terminated\n", sp->instance, sp->progName); /* Free all allocated memory */ seq_free(sp); }