15 #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1 28 #include <rtems/error.h> 61 static struct taskVar *taskVarHead;
62 #define RTEMS_NOTEPAD_TASKVAR 11 67 static volatile int initialized = 0;
87 if (ossPriority < 100) {
90 else if (ossPriority > 199) {
94 return (199u - (
unsigned int)ossPriority);
100 if (osiPriority > 99) {
104 return (199 - (
signed int)osiPriority);
112 (
unsigned int priority,
unsigned *pPriorityJustAbove)
114 unsigned newPriority = priority + 1;
116 newPriority = priority + 1;
117 if (newPriority <= 99) {
118 *pPriorityJustAbove = newPriority;
128 (
unsigned int priority,
unsigned *pPriorityJustBelow)
130 unsigned newPriority = priority - 1;
132 if (newPriority <= 99) {
133 *pPriorityJustBelow = newPriority;
142 unsigned int stackSize = 11000;
148 errlogPrintf(
"epicsThreadGetStackSize illegal argument");
151 if (stackSize < RTEMS_MINIMUM_STACK_SIZE)
152 stackSize = RTEMS_MINIMUM_STACK_SIZE;
162 epicsMutexOsdMustLock (taskVarMutex);
172 void taskUnref(
struct taskVar *v)
192 threadWrapper (rtems_task_argument arg)
203 taskVarHead = v->
forw;
208 rtems_status_code sc = rtems_barrier_wait(v->
join_barrier, RTEMS_NO_TIMEOUT);
209 if(sc!=RTEMS_SUCCESSFUL)
213 rtems_task_delete (RTEMS_SELF);
223 static rtems_status_code
229 rtems_status_code sc = RTEMS_SUCCESSFUL;
237 v->
refcnt = joinable ? 2 : 1;
242 strncpy(c, v->
name, 3);
243 sc = rtems_barrier_create(rtems_build_name(
'~', c[0], c[1], c[2]),
244 RTEMS_BARRIER_AUTOMATIC_RELEASE | RTEMS_LOCAL,
246 if (sc != RTEMS_SUCCESSFUL) {
254 v->
forw = taskVarHead;
261 sc = rtems_task_start (tid, threadWrapper, (rtems_task_argument)v);
263 if (sc != RTEMS_SUCCESSFUL) {
279 epicsThreadInit (
void)
283 rtems_task_priority old;
286 onceMutex = epicsMutexOsdCreate();
287 taskVarMutex = epicsMutexOsdCreate();
288 if (!onceMutex || !taskVarMutex)
289 cantProceed(
"epicsThreadInit() can't create global mutexes\n");
290 rtems_task_ident (RTEMS_SELF, 0, &tid);
291 if(setThreadInfo (tid,
"_main_",
NULL,
NULL, 0) != RTEMS_SUCCESSFUL)
292 cantProceed(
"epicsThreadInit() unable to setup _main_");
312 unsigned int stackSize;
314 rtems_status_code sc;
322 opts = &opts_default;
328 if (stackSize < RTEMS_MINIMUM_STACK_SIZE) {
329 errlogPrintf (
"Warning: epicsThreadCreate %s illegal stackSize %d\n",
331 stackSize = RTEMS_MINIMUM_STACK_SIZE;
333 strncpy (c, name,
sizeof c);
334 sc = rtems_task_create (rtems_build_name (c[0], c[1], c[2], c[3]),
337 RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
338 RTEMS_FLOATING_POINT|RTEMS_LOCAL,
340 if (sc != RTEMS_SUCCESSFUL) {
341 errlogPrintf (
"epicsThreadCreate create failure for %s: %s\n",
342 name, rtems_status_text(sc));
345 sc = setThreadInfo (tid, name, funptr, parm, opts->
joinable);
346 if (sc != RTEMS_SUCCESSFUL) {
347 errlogPrintf (
"epicsThreadCreate create failure during setup for %s: %s\n",
348 name, rtems_status_text(sc));
349 rtems_task_delete(tid);
357 unsigned int priority,
unsigned int stackSize,
369 rtems_id target_tid = (rtems_id)
id, self_tid;
372 rtems_task_ident (RTEMS_SELF, 0, &self_tid);
383 errlogPrintf(
"Warning: %s thread self-join of unjoinable\n", v ? v->
name :
"non-EPICS thread");
394 }
else if(target_tid!=self_tid) {
396 rtems_status_code sc = rtems_barrier_wait(v->
join_barrier, RTEMS_NO_TIMEOUT);
397 if(sc!=RTEMS_SUCCESSFUL)
400 if(sc != RTEMS_SUCCESSFUL) {
401 errlogPrintf(
"epicsThreadMustJoin('%s') -> %s\n", v->
name, rtems_status_text(sc));
415 rtems_status_code sc;
417 sc = rtems_task_suspend (RTEMS_SELF);
418 if (sc != RTEMS_SUCCESSFUL)
420 rtems_status_text(sc));
425 rtems_id tid = (rtems_id)
id;
426 rtems_status_code sc;
428 sc = rtems_task_resume (tid);
429 if (sc != RTEMS_SUCCESSFUL)
431 rtems_status_text (sc));
436 rtems_id tid = (rtems_id)
id;
437 rtems_status_code sc;
438 rtems_task_priority pri;
440 sc = rtems_task_set_priority (tid, RTEMS_CURRENT_PRIORITY, &pri);
441 if (sc != RTEMS_SUCCESSFUL)
443 rtems_status_text(sc));
455 rtems_id tid = (rtems_id)
id;
456 rtems_status_code sc;
459 sc = rtems_task_set_priority (tid, pri, &pri);
460 if (sc != RTEMS_SUCCESSFUL)
462 rtems_status_text(sc));
474 rtems_id tid = (rtems_id)
id;
475 rtems_status_code sc;
477 switch (sc = rtems_task_is_suspended (tid)) {
478 case RTEMS_SUCCESSFUL:
481 case RTEMS_ALREADY_SUSPENDED:
492 rtems_status_code sc;
493 rtems_interval delay;
498 seconds += 0.99999999;
499 delay = (seconds >= INT_MAX) ? INT_MAX : (
int) seconds;
504 sc = rtems_task_wake_after (delay);
505 if(sc != RTEMS_SUCCESSFUL)
506 errlogPrintf(
"epicsThreadSleep: %s\n", rtems_status_text(sc));
514 rtems_task_ident (RTEMS_SELF, 0, &tid);
530 rtems_id tid = (rtems_id)
id;
535 for (v=taskVarHead ; v !=
NULL ; v=v->
forw) {
537 strncpy(name, v->
name, size);
544 #if (__RTEMS_MAJOR__>4 || \ 545 (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__>8) || \ 546 (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__==8 && __RTEMS_REVISION__>=99)) 547 if (_Objects_Get_name_as_string((rtems_id)
id, size, name) !=
NULL)
555 if ((thr=_Thread_Get(tid, &l)) !=
NULL) {
556 if (OBJECTS_LOCAL == l) {
558 Objects_Information *oi = _Objects_Get_information(tid);
559 if (oi->name_length >= size)
562 length = oi->name_length;
564 strncpy(name, thr->Object.name, length);
566 _Objects_Copy_name_raw( &thr->Object.name, name, length);
570 _Thread_Enable_dispatch();
575 snprintf(name, size,
"0x%lx", (
long)tid);
589 for (v = taskVarHead ; v !=
NULL ; v = v->
forw) {
590 if (strcmp (name, v->
name) == 0) {
604 #define EPICS_THREAD_ONCE_DONE (epicsThreadId) 1 606 if (!initialized) epicsThreadInit();
607 epicsMutexOsdMustLock(onceMutex);
613 epicsMutexOsdMustLock(onceMutex);
617 cantProceed(
"Recursive epicsThreadOnce() initialization\n");
623 epicsMutexOsdMustLock(onceMutex);
635 unsigned int taskVarIndex;
636 static volatile unsigned int threadVariableCount = 0;
638 if (!initialized) epicsThreadInit ();
640 taskVarIndex = ++threadVariableCount;
652 unsigned int varIndex = (
unsigned int)
id;
661 (varIndex + 1) *
sizeof(
void *));
663 cantProceed(
"epicsThreadPrivateSet realloc failed\n");
673 unsigned int varIndex = (
unsigned int)
id;
694 showBitmap (
char *cbuf,
unsigned long bits,
const struct bitmap *bp)
696 for ( ; bp->
msg !=
NULL ; bp++) {
698 strcpy (cbuf, bp->
msg);
699 cbuf += strlen (bp->
msg);
705 showInternalTaskInfo (rtems_id tid)
707 #ifdef __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 709 Thread_Control *the_thread;
710 Objects_Locations location;
711 static Thread_Control thread;
712 static char bitbuf[120];
713 static const struct bitmap taskState[] = {
714 {
"RUN", STATES_ALL_SET, STATES_READY },
715 {
"DORM", STATES_DORMANT, STATES_DORMANT },
716 {
"SUSP", STATES_SUSPENDED, STATES_SUSPENDED },
717 {
"TRANS", STATES_TRANSIENT, STATES_TRANSIENT },
718 {
"Delay", STATES_DELAYING, STATES_DELAYING },
719 {
"Wtime", STATES_WAITING_FOR_TIME, STATES_WAITING_FOR_TIME },
720 {
"Wbuf", STATES_WAITING_FOR_BUFFER, STATES_WAITING_FOR_BUFFER },
721 {
"Wseg", STATES_WAITING_FOR_SEGMENT, STATES_WAITING_FOR_SEGMENT },
722 {
"Wmsg" , STATES_WAITING_FOR_MESSAGE, STATES_WAITING_FOR_MESSAGE },
723 {
"Wevnt", STATES_WAITING_FOR_EVENT, STATES_WAITING_FOR_EVENT },
724 {
"Wsem", STATES_WAITING_FOR_SEMAPHORE,STATES_WAITING_FOR_SEMAPHORE },
725 {
"Wmtx", STATES_WAITING_FOR_MUTEX, STATES_WAITING_FOR_MUTEX },
726 {
"Wjoin", STATES_WAITING_FOR_JOIN_AT_EXIT,STATES_WAITING_FOR_JOIN_AT_EXIT },
727 {
"Wrpc", STATES_WAITING_FOR_RPC_REPLY,STATES_WAITING_FOR_RPC_REPLY },
728 {
"Wrate", STATES_WAITING_FOR_PERIOD, STATES_WAITING_FOR_PERIOD },
729 {
"Wsig", STATES_WAITING_FOR_SIGNAL, STATES_WAITING_FOR_SIGNAL },
733 the_thread = _Thread_Get (tid, &location);
734 if (location != OBJECTS_LOCAL) {
738 thread = *the_thread;
739 _Thread_Enable_dispatch();
745 struct sched_param sp;
746 rtems_task_priority real_priority, current_priority;
747 rtems_status_code sc = pthread_getschedparam(tid, &policy, &sp);
748 if (sc == RTEMS_SUCCESSFUL) {
749 real_priority = sp.sched_priority;
750 sc = rtems_task_set_priority(tid, RTEMS_CURRENT_PRIORITY, ¤t_priority);
752 if (sc != RTEMS_SUCCESSFUL) {
764 epicsPri = 199-real_priority;
767 else if (epicsPri > 99)
771 if (current_priority == real_priority)
774 fprintf(
epicsGetStdout(),
"%4d/%-3d", (
int)real_priority, (
int)current_priority);
775 showBitmap (bitbuf, thread.current_state, taskState);
777 if (thread.current_state & (STATES_WAITING_FOR_SEMAPHORE |
778 STATES_WAITING_FOR_MUTEX |
779 STATES_WAITING_FOR_MESSAGE))
792 fprintf(
epicsGetStdout(),
"+--------+-----------+--------+--------+---------------------+\n");
795 showInternalTaskInfo (v->
id);
809 for (v = taskVarHead ; v !=
NULL ; v = v->
forw) {
810 if ((rtems_id)
id == v->
id) {
817 fprintf(
epicsGetStdout(),
"*** Thread %x does not exist.\n", (
unsigned int)
id);
864 #if defined(RTEMS_SMP) 865 return rtems_smp_get_number_of_processors();
LIBCOM_API unsigned int epicsStdCall epicsThreadGetStackSize(epicsThreadStackSizeClass stackSizeClass)
LIBCOM_API epicsThreadBooleanStatus epicsStdCall epicsThreadHighestPriorityLevelBelow(unsigned int priority, unsigned *pPriorityJustBelow)
LIBCOM_API int epicsThreadGetCPUs(void)
LIBCOM_API epicsThreadPrivateId epicsStdCall epicsThreadPrivateCreate(void)
LIBCOM_API void epicsStdCall epicsThreadSleep(double seconds)
Block the calling thread for at least the specified time.
epicsThreadId threadMustCreate(const char *name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr, void *parm)
LIBCOM_API void epicsStdCall epicsThreadExitMain(void)
int epicsThreadGetOsiPriorityValue(int ossPriority)
#define assert(exp)
Declare that a condition should be true.
#define RTEMS_NOTEPAD_TASKVAR
LIBCOM_API void epicsExitCallAtThreadExits(void)
Internal routine that runs the registered thread exit routines.
void InterruptContextMessageDaemon(void *unused)
LIBCOM_API void epicsThreadRealtimeLock(void)
LIBCOM_API double epicsStdCall epicsThreadSleepQuantum()
Query a value approximating the OS timer/scheduler resolution.
void(* EPICS_THREAD_HOOK_ROUTINE)(epicsThreadId id)
LIBCOM_API epicsThreadBooleanStatus epicsStdCall epicsThreadLowestPriorityLevelAbove(unsigned int priority, unsigned *pPriorityJustAbove)
LIBCOM_API void epicsStdCall epicsThreadPrivateSet(epicsThreadPrivateId id, void *value)
LIBCOM_API void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
LIBCOM_API void epicsStdCall epicsThreadOnce(epicsThreadOnceId *id, void(*func)(void *), void *arg)
epicsThreadId epicsStdCall epicsThreadCreate(const char *name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr, void *parm)
double rtemsTicksPerSecond_double
FILE *epicsStdCall epicsGetStdout(void)
#define EPICS_THREAD_ONCE_INIT
epicsThreadStackSizeClass
int epicsThreadGetOssPriorityValue(unsigned int osiPriority)
#define epicsThreadPriorityMax
APIs for the epicsMutex mutual exclusion semaphore.
LIBCOM_API void epicsStdCall * epicsThreadPrivateGet(epicsThreadPrivateId id)
epicsThreadId epicsThreadCreateOpt(const char *name, EPICSTHREADFUNC funptr, void *parm, const epicsThreadOpts *opts)
Allocate and start a new OS thread.
LIBCOM_API unsigned int epicsStdCall epicsThreadGetPrioritySelf(void)
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetId(const char *name)
Extended replacement for the Posix exit and atexit routines.
LIBCOM_API void epicsStdCall epicsThreadSuspendSelf(void)
LIBCOM_API void epicsStdCall epicsThreadShow(epicsThreadId showThread, unsigned int level)
LIBCOM_API int epicsStdCall epicsThreadIsSuspended(epicsThreadId pthreadInfo)
int errlogPrintf(const char *pFormat,...)
LIBCOM_API void epicsStdCall epicsThreadResume(epicsThreadOSD *pthreadInfo)
char * epicsStrDup(const char *s)
LIBCOM_API void epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func)
EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT(int *pTarget)
LIBCOM_API void osdThreadHooksRunMain(epicsThreadId id)
LIBCOM_API void * mallocMustSucceed(size_t size, const char *msg)
A malloc() that never returns NULL.
int snprintf(char *str, size_t size, const char *format,...)
LIBCOM_API void epicsStdCall epicsThreadShowAll(unsigned int level)
#define EPICS_THREAD_OPTS_INIT
#define EPICS_THREAD_ONCE_DONE
LIBCOM_API void cantProceed(const char *msg,...)
#define epicsMutexOsdUnlock(ID)
LIBCOM_API unsigned int epicsStdCall epicsThreadGetPriority(epicsThreadId pthreadInfo)
void epicsThreadMustJoin(epicsThreadId id)
#define epicsMutexOsdLock(ID)
Routines for code that can't continue or return after an error.
LIBCOM_API void osdThreadHooksRun(epicsThreadId id)
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf(void)
LIBCOM_API void epicsStdCall epicsThreadSetPriority(epicsThreadId pthreadInfo, unsigned int priority)
unsigned int threadVariableCapacity
C++ and C descriptions for a thread.
LIBCOM_API void epicsStdCall epicsThreadPrivateDelete(epicsThreadPrivateId id)
#define epicsThreadPriorityMin
void(* EPICSTHREADFUNC)(void *parm)
LIBCOM_API const char epicsStdCall * epicsThreadGetNameSelf()
LIBCOM_API int epicsStdCall epicsThreadIsEqual(epicsThreadId p1, epicsThreadId p2)
LIBCOM_API void epicsStdCall epicsThreadGetName(epicsThreadId pthreadInfo, char *name, size_t size)