diff --git a/modules/libcom/src/osi/os/posix/osdThread.c b/modules/libcom/src/osi/os/posix/osdThread.c index c08dea40e..854441898 100644 --- a/modules/libcom/src/osi/os/posix/osdThread.c +++ b/modules/libcom/src/osi/os/posix/osdThread.c @@ -567,14 +567,13 @@ static epicsThreadOSD *createImplicit(void) pthreadInfo->osiPriority = 0; #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 - { - struct sched_param param; - int policy; - if(pthread_getschedparam(tid,&policy,¶m) == 0) - pthreadInfo->osiPriority = - (param.sched_priority - pcommonAttr->minPriority) * 100.0 / + if(pthread_getschedparam(tid,&pthreadInfo->schedPolicy,&pthreadInfo->schedParam) == 0) { + if ( pcommonAttr->usePolicy && pthreadInfo->schedPolicy == pcommonAttr->schedPolicy ) { + pthreadInfo->osiPriority = + (pthreadInfo->schedParam.sched_priority - pcommonAttr->minPriority) * 100.0 / (pcommonAttr->maxPriority - pcommonAttr->minPriority + 1); - } + } + } #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ status = pthread_setspecific(getpthreadInfo,(void *)pthreadInfo); diff --git a/modules/libcom/test/Makefile b/modules/libcom/test/Makefile index 1c26c44b7..130c23512 100755 --- a/modules/libcom/test/Makefile +++ b/modules/libcom/test/Makefile @@ -288,4 +288,15 @@ TESTPROD_HOST += cvtFastPerform cvtFastPerform_SRCS += cvtFastPerform.cpp testHarness_SRCS += cvtFastPerform.cpp +ifeq ($(POSIX),YES) +ifeq ($(USE_POSIX_THREAD_PRIORITY_SCHEDULING),YES) +TESTPROD_HOST += nonEpicsThreadPriorityTest +nonEpicsThreadPriorityTest_SRCS += nonEpicsThreadPriorityTest.cpp +nonEpicsThreadPriorityTest_SYS_LIBS += $(POSIX_LDLIBS:-l%=%) +testHarness_SRCS += nonEpicsThreadPriorityTest.cpp +epicsRunLibComTests_CFLAGS += -DHAVE_PTHREAD_PRIORITY_SCHEDULING +TESTS += nonEpicsThreadPriorityTest +endif +endif + include $(TOP)/configure/RULES diff --git a/modules/libcom/test/nonEpicsThreadPriorityTest.cpp b/modules/libcom/test/nonEpicsThreadPriorityTest.cpp new file mode 100644 index 000000000..088f0fca7 --- /dev/null +++ b/modules/libcom/test/nonEpicsThreadPriorityTest.cpp @@ -0,0 +1,100 @@ +#include +#include "epicsUnitTest.h" +#include "testMain.h" +#include +#include + +#ifdef __rtems__ + +/* RTEMS is posix but currently does not use the pthread API */ +MAIN(nonEpicsThreadPriorityTest) +{ + testPlan(1); + testSkip(1, "Platform does not use pthread API"); + return testDone(); +} + +#else + +static void *nonEpicsTestFunc(void *arg) +{ + unsigned int pri; + // epicsThreadGetIdSelf() creates an EPICS context + // verify that the priority computed by epics context + // is OK + pri = epicsThreadGetPriority( epicsThreadGetIdSelf() ); + if ( ! testOk( 0 == pri, "'createImplicit' assigned correct priority (%d) to non-EPICS thread", pri) ) { + return 0; + } + + return (void*)1; +} + + +static void testFunc(void *arg) +{ + epicsEventId ev = (epicsEventId)arg; + int policy; + struct sched_param param; + int status; + pthread_t tid; + void *rval; + pthread_attr_t attr; + + status = pthread_getschedparam(pthread_self(), &policy,¶m); + if ( status ) { + testSkip(1, "pthread_getschedparam failed"); + goto done; + } + + if ( SCHED_FIFO != policy ) { + testSkip(1, "nonEpicsThreadPriorityTest must be executed with privileges to use SCHED_FIFO"); + goto done; + } + + if ( pthread_attr_init( &attr ) ) { + testSkip(1, "pthread_attr_init failed"); + goto done; + } + if ( pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ) ) { + testSkip(1, "pthread_attr_setinheritsched failed"); + goto done; + } + if ( pthread_attr_setschedpolicy ( &attr, SCHED_OTHER ) ) { + testSkip(1, "pthread_attr_setschedpolicy failed"); + goto done; + } + param.sched_priority = 0; + if ( pthread_attr_setschedparam ( &attr, ¶m ) ) { + testSkip(1, "pthread_attr_setschedparam failed"); + goto done; + } + + if ( pthread_create( &tid, &attr, nonEpicsTestFunc, 0 ) ) { + testSkip(1, "pthread_create failed"); + goto done; + } + + if ( pthread_join( tid, &rval ) ) { + testSkip(1, "pthread_join failed"); + goto done; + } + +done: + + epicsEventSignal( ev ); +} + +MAIN(nonEpicsThreadPriorityTest) +{ + testPlan(2); + epicsEventId testComplete = epicsEventMustCreate(epicsEventEmpty); + epicsThreadMustCreate("nonEpicsThreadPriorityTest", epicsThreadPriorityLow, + epicsThreadGetStackSize(epicsThreadStackMedium), + testFunc, testComplete); + epicsEventWaitStatus status = epicsEventWait(testComplete); + testOk(status == epicsEventWaitOK, + "epicsEventWait returned %d", status); + return testDone(); +} +#endif