From 5fe0429c48ed9661bce361fc9a01cc00868aee2a Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Thu, 29 Mar 2018 11:48:55 +0200 Subject: [PATCH 1/8] undo change of ROFF from LONG to ULONG in commit f498b36438703eb941eaac15c87f94b8d679def6 --- src/rec/aiRecord.dbd | 2 +- src/rec/aoRecord.dbd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rec/aiRecord.dbd b/src/rec/aiRecord.dbd index 69a9f396c..e1b8c687a 100644 --- a/src/rec/aiRecord.dbd +++ b/src/rec/aiRecord.dbd @@ -176,7 +176,7 @@ recordtype(ai) { pp(TRUE) interest(2) } - field(ROFF,DBF_ULONG) { + field(ROFF,DBF_LONG) { prompt("Raw Offset") pp(TRUE) interest(2) diff --git a/src/rec/aoRecord.dbd b/src/rec/aoRecord.dbd index 3c2d8cf9c..c81bcd887 100644 --- a/src/rec/aoRecord.dbd +++ b/src/rec/aoRecord.dbd @@ -82,7 +82,7 @@ recordtype(ao) { interest(1) size(16) } - field(ROFF,DBF_ULONG) { + field(ROFF,DBF_LONG) { prompt("Raw Offset") pp(TRUE) interest(2) From afcb81927e773c6a44d038352f1592a54b7d4101 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Thu, 29 Mar 2018 13:32:27 +0200 Subject: [PATCH 2/8] catch tNTP time jumps in vxWorks --- src/libCom/osi/osiNTPTime.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libCom/osi/osiNTPTime.c b/src/libCom/osi/osiNTPTime.c index 909e6f121..0997cc42e 100644 --- a/src/libCom/osi/osiNTPTime.c +++ b/src/libCom/osi/osiNTPTime.c @@ -177,6 +177,19 @@ static void NTPTimeSync(void *dummy) continue; } + if (ntpDelta > 3600 && NTPTimePvt.synchronized) { + char nowTimeText[32]; + char ntpTimeText[32]; + epicsTimeToStrftime(ntpTimeText,sizeof(nowTimeText),"%Y-%m-%d %H:%M:%S.%09f", + &NTPTimePvt.syncTime); + epicsTimeToStrftime(ntpTimeText,sizeof(ntpTimeText),"%Y-%m-%d %H:%M:%S.%09f", + &timeNow); + errlogPrintf("NTPTimeSync: refuse to jump from %s to future %s (timespec: %li.%09li)\n", + nowTimeText, ntpTimeText, timespecNow.tv_sec, timespecNow.tv_nsec); + NTPTimePvt.synchronized = 0; + continue; + } + NTPTimePvt.syncsFailed = 0; if (!NTPTimePvt.synchronized) { errlogPrintf("NTPTimeSync: Sync recovered.\n"); @@ -274,6 +287,8 @@ int NTPTime_Report(int level) osdTickRateGet()); printf("Measured tick rate = %.3f Hz\n", NTPTimePvt.tickRate); + printf("Ticks to skip = %d ticks\n", + NTPTimePvt.ticksToSkip); osdNTPReport(); } } else { From ec3b7c364b39be035f3410fc2b88723c6c252a6a Mon Sep 17 00:00:00 2001 From: zimoch Date: Thu, 5 Dec 2013 12:33:34 +0000 Subject: [PATCH 3/8] Put thread names in ps -L output and thread ids in epicsThreadShowAll output --- src/libCom/osi/os/Linux/osdThread.c | 872 ++++++++++++++++++++++++++++ 1 file changed, 872 insertions(+) create mode 100644 src/libCom/osi/os/Linux/osdThread.c diff --git a/src/libCom/osi/os/Linux/osdThread.c b/src/libCom/osi/os/Linux/osdThread.c new file mode 100644 index 000000000..c29e47c05 --- /dev/null +++ b/src/libCom/osi/os/Linux/osdThread.c @@ -0,0 +1,872 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* epicsThread.c */ + +/* Author: Marty Kraimer Date: 18JAN2000 */ + +/* This is a posix implementation of epicsThread */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define epicsExportSharedSymbols +#include "epicsStdio.h" +#include "ellLib.h" +#include "epicsEvent.h" +#include "epicsMutex.h" +#include "epicsString.h" +#include "epicsThread.h" +#include "cantProceed.h" +#include "errlog.h" +#include "epicsAssert.h" +#include "epicsExit.h" + +static int mutexLock(pthread_mutex_t *id) +{ + int status; + + while(1) { + status = pthread_mutex_lock(id); + if(status!=EINTR) return status; + fprintf(stderr,"pthread_mutex_lock returned EINTR. Violates SUSv3\n"); + } +} + +#if defined DONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING +#undef _POSIX_THREAD_PRIORITY_SCHEDULING +#endif + +typedef struct commonAttr{ + pthread_attr_t attr; + struct sched_param schedParam; + int maxPriority; + int minPriority; + int schedPolicy; +} commonAttr; + +typedef struct epicsThreadOSD { + ELLNODE node; + pthread_t tid; + pid_t lwpId; + pthread_attr_t attr; + struct sched_param schedParam; + EPICSTHREADFUNC createFunc; + void *createArg; + epicsEventId suspendEvent; + int isSuspended; + int isEpicsThread; + int isFifoScheduled; + int isOnThreadList; + unsigned int osiPriority; + char *name; +} epicsThreadOSD; + +#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING +typedef struct { + int min_pri, max_pri; + int policy; +} priAvailable; +#endif + +static pthread_key_t getpthreadInfo; +static pthread_mutex_t onceLock; +static pthread_mutex_t listLock; +static ELLLIST pthreadList = ELLLIST_INIT; +static commonAttr *pcommonAttr = 0; +static int epicsThreadOnceCalled = 0; + +static epicsThreadOSD *createImplicit(void); + +#define checkStatus(status,message) \ +if((status)) {\ + errlogPrintf("%s error %s\n",(message),strerror((status))); \ +} + +#define checkStatusQuit(status,message,method) \ +if(status) { \ + errlogPrintf("%s error %s\n",(message),strerror((status))); \ + cantProceed((method)); \ +} + +/* The following are for use by once, which is only invoked from epicsThreadInit*/ +/* Until epicsThreadInit completes errlogInit will not work */ +/* It must also be used by init_threadInfo otherwise errlogInit could get */ +/* called recursively */ +#define checkStatusOnce(status,message) \ +if((status)) {\ + fprintf(stderr,"%s error %s\n",(message),strerror((status))); } + +#define checkStatusOnceQuit(status,message,method) \ +if(status) { \ + fprintf(stderr,"%s error %s",(message),strerror((status))); \ + fprintf(stderr," %s\n",method); \ + fprintf(stderr,"epicsThreadInit cant proceed. Program exiting\n"); \ + exit(-1);\ +} + + +#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) +static int getOssPriorityValue(epicsThreadOSD *pthreadInfo) +{ + double maxPriority,minPriority,slope,oss; + + if(pcommonAttr->maxPriority==pcommonAttr->minPriority) + return(pcommonAttr->maxPriority); + maxPriority = (double)pcommonAttr->maxPriority; + minPriority = (double)pcommonAttr->minPriority; + slope = (maxPriority - minPriority)/100.0; + oss = (double)pthreadInfo->osiPriority * slope + minPriority; + return((int)oss); +} +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ +static void setSchedulingPolicy(epicsThreadOSD *pthreadInfo,int policy) +{ +#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) + int status; + + status = pthread_attr_getschedparam( + &pthreadInfo->attr,&pthreadInfo->schedParam); + checkStatusOnce(status,"pthread_attr_getschedparam"); + pthreadInfo->schedParam.sched_priority = getOssPriorityValue(pthreadInfo); + status = pthread_attr_setschedpolicy( + &pthreadInfo->attr,policy); + checkStatusOnce(status,"pthread_attr_setschedpolicy"); + status = pthread_attr_setschedparam( + &pthreadInfo->attr,&pthreadInfo->schedParam); + checkStatusOnce(status,"pthread_attr_setschedparam"); + status = pthread_attr_setinheritsched( + &pthreadInfo->attr,PTHREAD_EXPLICIT_SCHED); + checkStatusOnce(status,"pthread_attr_setinheritsched"); +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ +} + +static epicsThreadOSD * create_threadInfo(const char *name) +{ + epicsThreadOSD *pthreadInfo; + + pthreadInfo = callocMustSucceed(1,sizeof(*pthreadInfo),"create_threadInfo"); + pthreadInfo->suspendEvent = epicsEventMustCreate(epicsEventEmpty); + pthreadInfo->name = epicsStrDup(name); + return pthreadInfo; +} + +static epicsThreadOSD * init_threadInfo(const char *name, + unsigned int priority, unsigned int stackSize, + EPICSTHREADFUNC funptr,void *parm) +{ + epicsThreadOSD *pthreadInfo; + int status; + + pthreadInfo = create_threadInfo(name); + pthreadInfo->createFunc = funptr; + pthreadInfo->createArg = parm; + status = pthread_attr_init(&pthreadInfo->attr); + checkStatusOnce(status,"pthread_attr_init"); + if(status) return 0; + status = pthread_attr_setdetachstate( + &pthreadInfo->attr, PTHREAD_CREATE_DETACHED); + checkStatusOnce(status,"pthread_attr_setdetachstate"); +#if defined (_POSIX_THREAD_ATTR_STACKSIZE) +#if ! defined (OSITHREAD_USE_DEFAULT_STACK) + status = pthread_attr_setstacksize( &pthreadInfo->attr,(size_t)stackSize); + checkStatusOnce(status,"pthread_attr_setstacksize"); +#endif /*OSITHREAD_USE_DEFAULT_STACK*/ +#endif /*_POSIX_THREAD_ATTR_STACKSIZE*/ + status = pthread_attr_setscope(&pthreadInfo->attr,PTHREAD_SCOPE_PROCESS); + if(errVerbose) checkStatusOnce(status,"pthread_attr_setscope"); + pthreadInfo->osiPriority = priority; + return(pthreadInfo); +} + +static void free_threadInfo(epicsThreadOSD *pthreadInfo) +{ + int status; + + status = mutexLock(&listLock); + checkStatusQuit(status,"pthread_mutex_lock","free_threadInfo"); + if(pthreadInfo->isOnThreadList) ellDelete(&pthreadList,&pthreadInfo->node); + status = pthread_mutex_unlock(&listLock); + checkStatusQuit(status,"pthread_mutex_unlock","free_threadInfo"); + epicsEventDestroy(pthreadInfo->suspendEvent); + status = pthread_attr_destroy(&pthreadInfo->attr); + checkStatusQuit(status,"pthread_attr_destroy","free_threadInfo"); + free(pthreadInfo->name); + free(pthreadInfo); +} + +#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) +/* + * The actually available range priority range (at least under linux) + * may be restricted by resource limitations (but that is ignored + * by sched_get_priority_max()). See bug #835138 which is fixed by + * this code. + */ + +static int try_pri(int pri, int policy) +{ +struct sched_param schedp; + + schedp.sched_priority = pri; + return pthread_setschedparam(pthread_self(), policy, &schedp); +} + +static void* +find_pri_range(void *arg) +{ +priAvailable *prm = arg; +int min = sched_get_priority_min(prm->policy); +int max = sched_get_priority_max(prm->policy); +int low, try; + + if ( -1 == min || -1 == max ) { + /* something is very wrong; maintain old behavior + * (warning message if sched_get_priority_xxx() fails + * and use default policy's sched_priority [even if + * that is likely to cause epicsThreadCreate to fail + * because that priority is not suitable for SCHED_FIFO]). + */ + prm->min_pri = prm->max_pri = -1; + return 0; + } + + + if ( try_pri(min, prm->policy) ) { + /* cannot create thread at minimum priority; + * probably no permission to use SCHED_FIFO + * at all. However, we still must return + * a priority range accepted by the SCHED_FIFO + * policy. Otherwise, epicsThreadCreate() cannot + * detect the unsufficient permission (EPERM) + * and fall back to a non-RT thread (because + * pthread_attr_setschedparam would fail with + * EINVAL due to the bad priority). + */ + prm->min_pri = prm->max_pri = min; + return 0; + } + + + /* Binary search through available priorities. + * The actually available range may be restricted + * by resource limitations (but that is ignored + * by sched_get_priority_max() [linux]). + */ + low = min; + + while ( low < max ) { + try = (max+low)/2; + if ( try_pri(try, prm->policy) ) { + max = try; + } else { + low = try + 1; + } + } + + prm->min_pri = min; + prm->max_pri = try_pri(max, prm->policy) ? max-1 : max; + + return 0; +} + +static void findPriorityRange(commonAttr *a_p) +{ +priAvailable arg; +pthread_t id; +void *dummy; +int status; + + arg.policy = a_p->schedPolicy; + + status = pthread_create(&id, 0, find_pri_range, &arg); + checkStatusQuit(status, "pthread_create","epicsThreadInit"); + + status = pthread_join(id, &dummy); + checkStatusQuit(status, "pthread_join","epicsThreadInit"); + + a_p->minPriority = arg.min_pri; + a_p->maxPriority = arg.max_pri; +} +#endif + + +static void once(void) +{ + epicsThreadOSD *pthreadInfo; + int status; + + pthread_key_create(&getpthreadInfo,0); + status = pthread_mutex_init(&onceLock,0); + checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit"); + status = pthread_mutex_init(&listLock,0); + checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit"); + pcommonAttr = calloc(1,sizeof(commonAttr)); + if(!pcommonAttr) checkStatusOnceQuit(errno,"calloc","epicsThreadInit"); + status = pthread_attr_init(&pcommonAttr->attr); + checkStatusOnceQuit(status,"pthread_attr_init","epicsThreadInit"); + status = pthread_attr_setdetachstate( + &pcommonAttr->attr, PTHREAD_CREATE_DETACHED); + checkStatusOnce(status,"pthread_attr_setdetachstate"); + status = pthread_attr_setscope(&pcommonAttr->attr,PTHREAD_SCOPE_PROCESS); + if(errVerbose) checkStatusOnce(status,"pthread_attr_setscope"); +#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) + status = pthread_attr_setschedpolicy( + &pcommonAttr->attr,SCHED_FIFO); + checkStatusOnce(status,"pthread_attr_setschedpolicy"); + status = pthread_attr_getschedpolicy( + &pcommonAttr->attr,&pcommonAttr->schedPolicy); + checkStatusOnce(status,"pthread_attr_getschedpolicy"); + status = pthread_attr_getschedparam( + &pcommonAttr->attr,&pcommonAttr->schedParam); + checkStatusOnce(status,"pthread_attr_getschedparam"); + + findPriorityRange(pcommonAttr); + + if(pcommonAttr->maxPriority == -1) { + pcommonAttr->maxPriority = pcommonAttr->schedParam.sched_priority; + fprintf(stderr,"sched_get_priority_max failed set to %d\n", + pcommonAttr->maxPriority); + } + if(pcommonAttr->minPriority == -1) { + pcommonAttr->minPriority = pcommonAttr->schedParam.sched_priority; + fprintf(stderr,"sched_get_priority_min failed set to %d\n", + pcommonAttr->maxPriority); + } +#else + if(errVerbose) fprintf(stderr,"task priorities are not implemented\n"); +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ + pthreadInfo = init_threadInfo("_main_",0,epicsThreadGetStackSize(epicsThreadStackSmall),0,0); + pthreadInfo->lwpId = syscall(SYS_gettid); + status = pthread_setspecific(getpthreadInfo,(void *)pthreadInfo); + checkStatusOnceQuit(status,"pthread_setspecific","epicsThreadInit"); + status = mutexLock(&listLock); + checkStatusQuit(status,"pthread_mutex_lock","epicsThreadInit"); + ellAdd(&pthreadList,&pthreadInfo->node); + pthreadInfo->isOnThreadList = 1; + status = pthread_mutex_unlock(&listLock); + checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadInit"); + status = atexit(epicsExitCallAtExits); + checkStatusOnce(status,"atexit"); + epicsThreadOnceCalled = 1; +} + +static void * start_routine(void *arg) +{ + epicsThreadOSD *pthreadInfo = (epicsThreadOSD *)arg; + int status; + int oldtype; + sigset_t blockAllSig; + char comm[16]; + + /* Set the name of the thread's process. Limited to 16 characters. */ + snprintf(comm, sizeof(comm), "%s", pthreadInfo->name); + prctl(PR_SET_NAME, comm, 0l, 0l, 0l); + pthreadInfo->lwpId = syscall(SYS_gettid); + + sigfillset(&blockAllSig); + pthread_sigmask(SIG_SETMASK,&blockAllSig,NULL); + status = pthread_setspecific(getpthreadInfo,arg); + checkStatusQuit(status,"pthread_setspecific","start_routine"); + status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&oldtype); + checkStatusQuit(status,"pthread_setcanceltype","start_routine"); + status = mutexLock(&listLock); + checkStatusQuit(status,"pthread_mutex_lock","start_routine"); + ellAdd(&pthreadList,&pthreadInfo->node); + pthreadInfo->isOnThreadList = 1; + status = pthread_mutex_unlock(&listLock); + checkStatusQuit(status,"pthread_mutex_unlock","start_routine"); + + (*pthreadInfo->createFunc)(pthreadInfo->createArg); + + epicsExitCallAtThreadExits (); + + free_threadInfo(pthreadInfo); + return(0); +} + +static void epicsThreadInit(void) +{ + static pthread_once_t once_control = PTHREAD_ONCE_INIT; + int status = pthread_once(&once_control,once); + checkStatusQuit(status,"pthread_once","epicsThreadInit"); +} + + +epicsShareFunc unsigned int epicsShareAPI epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass) +{ +#if ! defined (_POSIX_THREAD_ATTR_STACKSIZE) + return 0; +#elif defined (OSITHREAD_USE_DEFAULT_STACK) + return 0; +#else + #define STACK_SIZE(f) (f * 0x10000 * sizeof(void *)) + static const unsigned stackSizeTable[epicsThreadStackBig+1] = { + STACK_SIZE(1), STACK_SIZE(2), STACK_SIZE(4) + }; + if (stackSizeClassepicsThreadStackBig) { + errlogPrintf("epicsThreadGetStackSize illegal argument (too large)"); + return stackSizeTable[epicsThreadStackBig]; + } + + return stackSizeTable[stackSizeClass]; +#endif /*_POSIX_THREAD_ATTR_STACKSIZE*/ +} + +epicsShareFunc void epicsShareAPI epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg) +{ + static struct epicsThreadOSD threadOnceComplete; + #define EPICS_THREAD_ONCE_DONE &threadOnceComplete + int status; + + epicsThreadInit(); + status = mutexLock(&onceLock); + if(status) { + fprintf(stderr,"epicsThreadOnce: pthread_mutex_lock returned %s.\n", + strerror(status)); + exit(-1); + } + + if (*id != EPICS_THREAD_ONCE_DONE) { + if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */ + *id = epicsThreadGetIdSelf(); /* mark active */ + status = pthread_mutex_unlock(&onceLock); + checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce"); + func(arg); + status = mutexLock(&onceLock); + checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce"); + *id = EPICS_THREAD_ONCE_DONE; /* mark done */ + } else if (*id == epicsThreadGetIdSelf()) { + status = pthread_mutex_unlock(&onceLock); + checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce"); + cantProceed("Recursive epicsThreadOnce() initialization\n"); + } else + while (*id != EPICS_THREAD_ONCE_DONE) { + /* Another thread is in the above func(arg) call. */ + status = pthread_mutex_unlock(&onceLock); + checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce"); + epicsThreadSleep(epicsThreadSleepQuantum()); + status = mutexLock(&onceLock); + checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce"); + } + } + status = pthread_mutex_unlock(&onceLock); + checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadOnce"); +} + +epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate(const char *name, + unsigned int priority, unsigned int stackSize, + EPICSTHREADFUNC funptr,void *parm) +{ + epicsThreadOSD *pthreadInfo; + int status; + sigset_t blockAllSig, oldSig; + + epicsThreadInit(); + assert(pcommonAttr); + sigfillset(&blockAllSig); + pthread_sigmask(SIG_SETMASK,&blockAllSig,&oldSig); + pthreadInfo = init_threadInfo(name,priority,stackSize,funptr,parm); + if(pthreadInfo==0) return 0; + pthreadInfo->isEpicsThread = 1; + setSchedulingPolicy(pthreadInfo,SCHED_FIFO); + pthreadInfo->isFifoScheduled = 1; + status = pthread_create(&pthreadInfo->tid,&pthreadInfo->attr, + start_routine,pthreadInfo); + if(status==EPERM){ + /* Try again without SCHED_FIFO*/ + free_threadInfo(pthreadInfo); + pthreadInfo = init_threadInfo(name,priority,stackSize,funptr,parm); + if(pthreadInfo==0) return 0; + pthreadInfo->isEpicsThread = 1; + status = pthread_create(&pthreadInfo->tid,&pthreadInfo->attr, + start_routine,pthreadInfo); + } + checkStatusOnce(status,"pthread_create"); + if(status) { + free_threadInfo(pthreadInfo); + return 0; + } + status = pthread_sigmask(SIG_SETMASK,&oldSig,NULL); + checkStatusOnce(status,"pthread_sigmask"); + + return(pthreadInfo); +} + +/* + * Cleanup routine for threads not created by epicsThreadCreate(). + */ +/* static void nonEPICSthreadCleanup(void *arg) +{ + epicsThreadOSD *pthreadInfo = (epicsThreadOSD *)arg; + + free(pthreadInfo->name); + free(pthreadInfo); +} */ + +/* + * Create dummy context for threads not created by epicsThreadCreate(). + */ +static epicsThreadOSD *createImplicit(void) +{ + epicsThreadOSD *pthreadInfo; + char name[64]; + pthread_t tid; + int status; + + tid = pthread_self(); + sprintf(name, "non-EPICS_%ld", (long)tid); + pthreadInfo = create_threadInfo(name); + pthreadInfo->tid = tid; + pthreadInfo->osiPriority = 0; +#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) + { + struct sched_param param; + int policy; + if(pthread_getschedparam(tid,&policy,¶m) == 0) + pthreadInfo->osiPriority = + (param.sched_priority - pcommonAttr->minPriority) * 100.0 / + (pcommonAttr->maxPriority - pcommonAttr->minPriority + 1); + } +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ + status = pthread_setspecific(getpthreadInfo,(void *)pthreadInfo); + checkStatusQuit(status,"pthread_setspecific","createImplicit"); +/* pthread_cleanup_push(nonEPICSthreadCleanup, pthreadInfo); */ + return pthreadInfo; +} + +epicsShareFunc void epicsShareAPI epicsThreadSuspendSelf(void) +{ + epicsThreadOSD *pthreadInfo; + + epicsThreadInit(); + pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo); + if(pthreadInfo==NULL) + pthreadInfo = createImplicit(); + pthreadInfo->isSuspended = 1; + epicsEventMustWait(pthreadInfo->suspendEvent); +} + +epicsShareFunc void epicsShareAPI epicsThreadResume(epicsThreadOSD *pthreadInfo) +{ + assert(epicsThreadOnceCalled); + pthreadInfo->isSuspended = 0; + epicsEventSignal(pthreadInfo->suspendEvent); +} + +epicsShareFunc void epicsShareAPI epicsThreadExitMain(void) +{ + epicsThreadOSD *pthreadInfo; + + epicsThreadInit(); + pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo); + if(pthreadInfo==NULL) + pthreadInfo = createImplicit(); + if(pthreadInfo->createFunc) { + errlogPrintf("called from non-main thread\n"); + cantProceed("epicsThreadExitMain"); + } + else { + free_threadInfo(pthreadInfo); + pthread_exit(0); + } +} + +epicsShareFunc unsigned int epicsShareAPI epicsThreadGetPriority(epicsThreadId pthreadInfo) +{ + assert(epicsThreadOnceCalled); + return(pthreadInfo->osiPriority); +} + +epicsShareFunc unsigned int epicsShareAPI epicsThreadGetPrioritySelf(void) +{ + epicsThreadInit(); + return(epicsThreadGetPriority(epicsThreadGetIdSelf())); +} + +epicsShareFunc void epicsShareAPI epicsThreadSetPriority(epicsThreadId pthreadInfo,unsigned int priority) +{ +#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) + int status; +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ + + assert(epicsThreadOnceCalled); + assert(pthreadInfo); + if(!pthreadInfo->isEpicsThread) { + fprintf(stderr,"epicsThreadSetPriority called by non epics thread\n"); + return; + } + pthreadInfo->osiPriority = priority; + if(!pthreadInfo->isFifoScheduled) return; +#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) + pthreadInfo->schedParam.sched_priority = getOssPriorityValue(pthreadInfo); + status = pthread_attr_setschedparam( + &pthreadInfo->attr,&pthreadInfo->schedParam); + if(errVerbose) checkStatus(status,"pthread_attr_setschedparam"); + status = pthread_setschedparam( + pthreadInfo->tid,pcommonAttr->schedPolicy,&pthreadInfo->schedParam); + if(errVerbose) checkStatus(status,"pthread_setschedparam"); +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ +} + +epicsShareFunc epicsThreadBooleanStatus epicsShareAPI epicsThreadHighestPriorityLevelBelow( + unsigned int priority, unsigned *pPriorityJustBelow) +{ + unsigned newPriority = priority - 1; +#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) + int diff; + diff = pcommonAttr->maxPriority - pcommonAttr->minPriority; + if(diff<0) diff = -diff; + if(diff>1 && diff <100) newPriority -= 100/(diff+1); +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ + if (newPriority <= 99) { + *pPriorityJustBelow = newPriority; + return epicsThreadBooleanStatusSuccess; + } + return epicsThreadBooleanStatusFail; +} + +epicsShareFunc epicsThreadBooleanStatus epicsShareAPI epicsThreadLowestPriorityLevelAbove( + unsigned int priority, unsigned *pPriorityJustAbove) +{ + unsigned newPriority = priority + 1; + +#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) + int diff; + diff = pcommonAttr->maxPriority - pcommonAttr->minPriority; + if(diff<0) diff = -diff; + if(diff>1 && diff <100) newPriority += 100/(diff+1); +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ + if (newPriority <= 99) { + *pPriorityJustAbove = newPriority; + return epicsThreadBooleanStatusSuccess; + } + return epicsThreadBooleanStatusFail; +} + +epicsShareFunc int epicsShareAPI epicsThreadIsEqual(epicsThreadId p1, epicsThreadId p2) +{ + assert(epicsThreadOnceCalled); + assert(p1); + assert(p2); + return(pthread_equal(p1->tid,p2->tid)); +} + +epicsShareFunc int epicsShareAPI epicsThreadIsSuspended(epicsThreadId pthreadInfo) { + assert(epicsThreadOnceCalled); + assert(pthreadInfo); + return(pthreadInfo->isSuspended ? 1 : 0); +} + +epicsShareFunc void epicsShareAPI epicsThreadSleep(double seconds) +{ + struct timespec delayTime; + struct timespec remainingTime; + double nanoseconds; + + if (seconds > 0) { + delayTime.tv_sec = seconds; + nanoseconds = (seconds - delayTime.tv_sec) *1e9; + delayTime.tv_nsec = nanoseconds; + } + else { + delayTime.tv_sec = 0; + delayTime.tv_nsec = 0; + } + while (nanosleep(&delayTime, &remainingTime) == -1 && + errno == EINTR) + delayTime = remainingTime; +} + +epicsShareFunc epicsThreadId epicsShareAPI epicsThreadGetIdSelf(void) { + epicsThreadOSD *pthreadInfo; + + epicsThreadInit(); + pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo); + if(pthreadInfo==NULL) + pthreadInfo = createImplicit(); + assert ( pthreadInfo ); + return(pthreadInfo); +} + +epicsShareFunc pthread_t epicsShareAPI epicsThreadGetPosixThreadId ( epicsThreadId threadId ) +{ + return threadId->tid; +} + +epicsShareFunc epicsThreadId epicsShareAPI epicsThreadGetId(const char *name) { + epicsThreadOSD *pthreadInfo; + int status; + + assert(epicsThreadOnceCalled); + status = mutexLock(&listLock); + checkStatusQuit(status,"pthread_mutex_lock","epicsThreadGetId"); + pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList); + while(pthreadInfo) { + if(strcmp(name,pthreadInfo->name) == 0) break; + pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node); + } + status = pthread_mutex_unlock(&listLock); + checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadGetId"); + + return(pthreadInfo); +} + +epicsShareFunc const char epicsShareAPI *epicsThreadGetNameSelf() +{ + epicsThreadOSD *pthreadInfo; + + epicsThreadInit(); + pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo); + if(pthreadInfo==NULL) + pthreadInfo = createImplicit(); + return(pthreadInfo->name); +} + +epicsShareFunc void epicsShareAPI epicsThreadGetName(epicsThreadId pthreadInfo, char *name, size_t size) +{ + assert(epicsThreadOnceCalled); + strncpy(name, pthreadInfo->name, size-1); + name[size-1] = '\0'; +} + +static void showThreadInfo(epicsThreadOSD *pthreadInfo,unsigned int level) +{ + if(!pthreadInfo) { + fprintf(epicsGetStdout()," NAME EPICS ID " + "LWP ID OSIPRI OSSPRI STATE\n"); + } else { + struct sched_param param; + int policy; + int priority = 0; + + if(pthreadInfo->tid) { + int status; + status = pthread_getschedparam(pthreadInfo->tid,&policy,¶m); + if(!status) priority = param.sched_priority; + } + fprintf(epicsGetStdout(),"%16.16s %18p %8lu %3d%8d %8.8s\n", + pthreadInfo->name,(void *) + pthreadInfo,(unsigned long)pthreadInfo->lwpId, + pthreadInfo->osiPriority,priority, + pthreadInfo->isSuspended ? "SUSPEND" : "OK"); + } +} + +epicsShareFunc void epicsShareAPI epicsThreadShowAll(unsigned int level) +{ + epicsThreadOSD *pthreadInfo; + int status; + + epicsThreadInit(); + epicsThreadShow(0,level); + status = mutexLock(&listLock); + checkStatusQuit(status,"pthread_mutex_lock","epicsThreadShowAll"); + pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList); + while(pthreadInfo) { + showThreadInfo(pthreadInfo,level); + pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node); + } + status = pthread_mutex_unlock(&listLock); + checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadShowAll"); +} + +epicsShareFunc void epicsShareAPI epicsThreadShow(epicsThreadId showThread, unsigned int level) +{ + epicsThreadOSD *pthreadInfo; + int status; + int found = 0; + + epicsThreadInit(); + if(!showThread) { + showThreadInfo(0,level); + return; + } + status = mutexLock(&listLock); + checkStatusQuit(status,"pthread_mutex_lock","epicsThreadShowAll"); + pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList); + while(pthreadInfo) { + if (((epicsThreadId)pthreadInfo == showThread) + || ((epicsThreadId)pthreadInfo->tid == showThread)) { + found = 1; + showThreadInfo(pthreadInfo,level); + } + pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node); + } + status = pthread_mutex_unlock(&listLock); + checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadShowAll"); + if (!found) + printf("Thread %#lx (%lu) not found.\n", (unsigned long)showThread, (unsigned long)showThread); +} + + +epicsShareFunc epicsThreadPrivateId epicsShareAPI epicsThreadPrivateCreate(void) +{ + pthread_key_t *key; + int status; + + epicsThreadInit(); + key = callocMustSucceed(1,sizeof(pthread_key_t),"epicsThreadPrivateCreate"); + status = pthread_key_create(key,0); + checkStatusQuit(status,"pthread_key_create","epicsThreadPrivateCreate"); + return((epicsThreadPrivateId)key); +} + +epicsShareFunc void epicsShareAPI epicsThreadPrivateDelete(epicsThreadPrivateId id) +{ + pthread_key_t *key = (pthread_key_t *)id; + int status; + + assert(epicsThreadOnceCalled); + status = pthread_key_delete(*key); + checkStatusQuit(status,"pthread_key_delete","epicsThreadPrivateDelete"); + free((void *)key); +} + +epicsShareFunc void epicsShareAPI epicsThreadPrivateSet (epicsThreadPrivateId id, void *value) +{ + pthread_key_t *key = (pthread_key_t *)id; + int status; + + assert(epicsThreadOnceCalled); + if(errVerbose && !value) + errlogPrintf("epicsThreadPrivateSet: setting value of 0\n"); + status = pthread_setspecific(*key,value); + checkStatusQuit(status,"pthread_setspecific","epicsThreadPrivateSet"); +} + +epicsShareFunc void epicsShareAPI *epicsThreadPrivateGet(epicsThreadPrivateId id) +{ + pthread_key_t *key = (pthread_key_t *)id; + + assert(epicsThreadOnceCalled); + return pthread_getspecific(*key); +} + +epicsShareFunc double epicsShareAPI epicsThreadSleepQuantum () +{ + double hz; + hz = sysconf ( _SC_CLK_TCK ); + return 1.0 / hz; +} + From 9b9daa9a7c433a636ecbe7d38b12d1e6ff4730b1 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Wed, 18 Nov 2015 17:08:37 +0100 Subject: [PATCH 4/8] by Helge --- startup/win64.bat | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 startup/win64.bat diff --git a/startup/win64.bat b/startup/win64.bat new file mode 100644 index 000000000..38344a93f --- /dev/null +++ b/startup/win64.bat @@ -0,0 +1,27 @@ +@ECHO OFF +REM ************************************************************************* +REM Copyright (c) 2002 The University of Chicago, as Operator of Argonne +REM National Laboratory. +REM Copyright (c) 2002 The Regents of the University of California, as +REM Operator of Los Alamos National Laboratory. +REM EPICS BASE Versions 3.13.7 +REM and higher are distributed subject to a Software License Agreement found +REM in file LICENSE that is included with this distribution. + +set PATH=%PATH%;C:\cygwin\bin +REM --------------- Visual c++ ------------------------ +call "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" amd64 + +REM --------------- CUDA ----------------------------- + + +REM --------------- EPICS ----------------------------- +REM -- R3.14 requirements +set EPICS_HOST_ARCH=windows-x64 +set PATH=%PATH%;C:\epics\base-3.14.12.4\bin\%EPICS_HOST_ARCH% +REM =================================================== +REM ====== OPTIONAL ENVIRONMENT VARIABLES FOLLOW ====== + +REM ---------------- EPICS tools ---------------------- +REM -- HOST_ARCH needed for Makefile.Host builds -- +set HOST_ARCH=WIN32 From 394bf30dbf0c384a5038dd6603473a1ac8d71ee0 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Wed, 9 Nov 2016 11:54:52 +0100 Subject: [PATCH 5/8] use dynamic vxWorks BSP function binding because we don't know which functions are implememted in any particular BSP --- src/libCom/osi/os/vxWorks/devLibVMEOSD.c | 66 +++++++++--------------- 1 file changed, 24 insertions(+), 42 deletions(-) diff --git a/src/libCom/osi/os/vxWorks/devLibVMEOSD.c b/src/libCom/osi/os/vxWorks/devLibVMEOSD.c index 82bec603d..46e7a1852 100644 --- a/src/libCom/osi/os/vxWorks/devLibVMEOSD.c +++ b/src/libCom/osi/os/vxWorks/devLibVMEOSD.c @@ -110,7 +110,22 @@ static long vxDevWriteProbe (unsigned wordSize, volatile void *ptr, const void * static void *devA24Malloc(size_t size); static void devA24Free(void *pBlock); -static long devInit(void) { return 0;} + + +static int (*sysIntEnableFunc)(int) = NULL; +static int (*sysIntDisableFunc)(int) = NULL; +static int (*sysIntEnablePICFunc)(int) = NULL; +static int (*sysIntDisablePICFunc)(int) = NULL; + +static long devInit(void) +{ + /* We don't know which functions are implemented in the BSP */ + sysIntEnableFunc = epicsFindSymbol ("sysIntEnable"); + sysIntDisableFunc = epicsFindSymbol ("sysIntDisable"); + sysIntDisablePICFunc = epicsFindSymbol ("sysIntDisablePIC"); + sysIntEnablePICFunc = epicsFindSymbol ("sysIntEnablePIC"); + return 0; +} static long vxDevConnectInterruptVME ( unsigned vectorNumber, @@ -214,16 +229,8 @@ static long vxDevDisconnectInterruptVME ( */ static long vxDevEnableInterruptLevelVME (unsigned level) { -# if CPU_FAMILY != I80X86 - int s; - s = sysIntEnable (level); - if (s!=OK) { - return S_dev_intEnFail; - } - return 0; -# else - return S_dev_intEnFail; -# endif + if (!sysIntEnableFunc) return S_dev_intEnFail; + return sysIntEnableFunc (level) == OK ? 0 : S_dev_intEnFail; } /* @@ -231,16 +238,8 @@ static long vxDevEnableInterruptLevelVME (unsigned level) */ long devEnableInterruptLevelISA (unsigned level) { -# if CPU_FAMILY == I80X86 - int s; - s = sysIntEnablePIC (level); - if (s!=OK) { - return S_dev_intEnFail; - } - return 0; -# else - return S_dev_intEnFail; -# endif + if (!sysIntEnablePICFunc) return S_dev_intEnFail; + return sysIntEnablePICFunc (level) == OK ? 0 : S_dev_intEnFail; } /* @@ -248,17 +247,8 @@ long devEnableInterruptLevelISA (unsigned level) */ long devDisableInterruptLevelISA (unsigned level) { -# if CPU_FAMILY == I80X86 - int s; - s = sysIntDisablePIC (level); - if (s!=OK) { - return S_dev_intEnFail; - } -# else - return S_dev_intEnFail; -# endif - - return 0; + if (!sysIntDisablePICFunc) return S_dev_intDissFail; + return sysIntDisablePICFunc (level) == OK ? 0 : S_dev_intDissFail; } /* @@ -266,16 +256,8 @@ long devDisableInterruptLevelISA (unsigned level) */ static long vxDevDisableInterruptLevelVME (unsigned level) { -# if CPU_FAMILY != I80X86 - int s; - s = sysIntDisable (level); - if (s!=OK) { - return S_dev_intDissFail; - } - return 0; -# else - return S_dev_intEnFail; -# endif + if (!sysIntDisableFunc) return S_dev_intDissFail; + return sysIntDisableFunc (level) == OK ? 0 : S_dev_intDissFail; } /* From 44d4e47ec2af3bd459b4f078402776f34498fd2f Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Wed, 9 Nov 2016 12:03:34 +0100 Subject: [PATCH 6/8] add simple calculations to macros --- src/libCom/macLib/macCore.c | 185 ++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) diff --git a/src/libCom/macLib/macCore.c b/src/libCom/macLib/macCore.c index ba1c84fa4..f2a5cadaf 100644 --- a/src/libCom/macLib/macCore.c +++ b/src/libCom/macLib/macCore.c @@ -558,6 +558,186 @@ static MAC_ENTRY *create( MAC_HANDLE *handle, const char *name, int special ) return entry; } +#define SUCCESS 0 +#define NOVALUE 1 +#define UNTERMINATED 2 +#define DIVZERO 3 + +static int parseExpr( const char** pp, int* v, int level ); + +/* Value is a number or an expression in () */ +static int parseValue( const char** pp, int* v ) +{ + int status; + int val; + const char *p = *pp; + int neg = 0; + + while (isspace((unsigned char)*p)) p++; + if (*p == '+' || *p == '-') neg = *p++ == '-'; + while (isspace((unsigned char)*p)) p++; + if (*p == '(') + { + p++; + if ((status = parseExpr(&p, &val, 0)) != SUCCESS) return status; + if (*p++ != ')') + { + printf("macLib: missing ) after '%s'\n", *pp); + return UNTERMINATED; + } + } + else + { + char* e; + val = strtol(p, &e, 0); + if (e == p) return NOVALUE; + p = e; + } + if (neg) val = -val; + *pp = p; + *v = val; + return SUCCESS; +} + +/* Expr is a sum or product of Values or a conditional */ +static int parseExpr( const char** pp, int* v, int level ) +{ + const char *p = *pp; + int o = 0; + int val0, val1, val2; + int status = SUCCESS; + int stat1, stat2; + + val0 = 0; + /* handle sums and differences */ + do { + if ((stat1 = parseValue(&p, &val1)) != SUCCESS) + { + if (o && stat1 == NOVALUE) + printf ("macLib: missing operand after '%c'\n", o); + return stat1; + } + while (isspace((unsigned char)*p)) p++; + o = *p; + /* handle products and quotients */ + while (o == '*' || o == '/' || o == '%') + { + p++; + if ((stat2 = parseValue(&p, &val2)) != SUCCESS) + { + if (stat2 == NOVALUE) + printf ("macLib: missing operand after '%c'\n", o); + return stat2; + } + if (o == '*') val1 *= val2; + else if (val2 == 0) + { + status = DIVZERO; + val1 = 1; + } + else if (o == '/') val1 /= val2; + else val1 %= val2; + while (isspace((unsigned char)*p)) p++; + o = *p; + } + val0 += val1; + } while (o == '+' || o == '-'); + + /* handle comparisons */ + o = *p; + if (o == '<' || o == '>') + { + p++; + if ((stat1 = parseExpr(&p, &val1, 1)) != SUCCESS) + { + if (stat1 == NOVALUE) + printf ("macLib: missing expression after '%c'\n", o); + return stat1; + } + if (o == '<') + val0 = (val0 < val1); + else + val0 = (val0 > val1); + } + + /* handle conditionals */ + if (*p == '?' && level == 0) + { + p++; + while (isspace((unsigned char)*p)) p++; + if (*p != ':') + { + stat1 = parseExpr(&p, &val1, 0); + } + else + { + val1 = val0; + stat1 = status; + } + if (*p != ':') + { + printf("macLib: missing : after '%s'\n", *pp); + return UNTERMINATED; + } + p++; + stat2 = parseExpr(&p, &val2, 0); + status = val0 ? stat1 : stat2; + val0 = val0 ? val1 : val2; + } + + *v = val0; + *pp = p; + return status; +} + +static MAC_ENTRY *evalExpr( MAC_HANDLE *handle, const char *expr ) +{ + MAC_ENTRY *entry = NULL; + int status; + const char* p = expr; + int value; + char valuestr[40]; + char format[20] = "%d"; + + while (isspace((unsigned char)*p)) p++; + if (*p == '%') + { + int i = 1; + p++; + while (i < sizeof(format) && strchr(" #-+0", *p)) + format[i++] = *p++; + while (i < sizeof(format) && strchr("0123456789", *p)) + format[i++] = *p++; + if (i < sizeof(format) && strchr("diouxXc", *p)) + { + format[i++] = *p++; + format[i] = 0; + } + else + return NULL; + } + status = parseExpr(&p, &value, 0); + if (status == DIVZERO) + printf ("macLib: division by zero\n"); + if (status != SUCCESS) + return NULL; + while (isspace((unsigned char)*p)) p++; + if (*p) + { + printf("macLib: rubbish at end of expression: %s\n", p); + return NULL; + } + sprintf(valuestr, format, value); + entry = create( handle, expr, TRUE ); + if ( entry ) + { + entry->type = "calculation"; + if ( rawval( handle, entry, valuestr ) == NULL ) + return NULL; + } + return entry; +} + /* * Look up macro entry with matching "special" attribute by name */ @@ -569,6 +749,10 @@ static MAC_ENTRY *lookup( MAC_HANDLE *handle, const char *name, int special ) printf( "lookup-> level = %d, name = %s, special = %d\n", handle->level, name, special ); + if ( (special == FALSE) ) { + entry = evalExpr( handle, name ); + if (entry) return entry; + } /* search backwards so scoping works */ for ( entry = last( handle ); entry != NULL; entry = previous( entry ) ) { if ( entry->special != special ) @@ -688,6 +872,7 @@ static void trans( MAC_HANDLE *handle, MAC_ENTRY *entry, int level, /* return immediately if raw value is NULL */ if ( *rawval == NULL ) return; + /* discard quotes and escapes if level is > 0 (i.e. if these aren't the user's quotes and escapes) */ discard = ( level > 0 ); From 871e5c496e56b871ea10b9f74bcd80ec2dfb0cfd Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Wed, 6 Sep 2017 15:42:20 +0200 Subject: [PATCH 7/8] for easier debugging: overwrite destroyed event mutex --- src/db/dbEvent.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/db/dbEvent.c b/src/db/dbEvent.c index ee1673547..80a28add9 100644 --- a/src/db/dbEvent.c +++ b/src/db/dbEvent.c @@ -964,6 +964,7 @@ static void event_task (void *pParm) } while( ! pendexit ); epicsMutexDestroy(evUser->firstque.writelock); + evUser->firstque.writelock = (epicsMutexId)0xdeadbeef; { struct event_que *nextque; @@ -972,6 +973,7 @@ static void event_task (void *pParm) while(ev_que){ nextque = ev_que->nextque; epicsMutexDestroy(ev_que->writelock); + ev_que->writelock = (epicsMutexId)0xdeadbeef; freeListFree(dbevEventQueueFreeList, ev_que); ev_que = nextque; } @@ -980,6 +982,7 @@ static void event_task (void *pParm) epicsEventDestroy(evUser->ppendsem); epicsEventDestroy(evUser->pflush_sem); epicsMutexDestroy(evUser->lock); + evUser->lock = (epicsMutexId)0xdeadbeef; freeListFree(dbevEventUserFreeList, evUser); From 6f3e74095c1d013b698484d350485efc774a6019 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Wed, 4 Apr 2018 11:46:30 +0200 Subject: [PATCH 8/8] update osdThread.c from ../posix while keeping thread name and LWP ID --- src/libCom/osi/os/Linux/osdThread.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/libCom/osi/os/Linux/osdThread.c b/src/libCom/osi/os/Linux/osdThread.c index c29e47c05..bf7e6c7e3 100644 --- a/src/libCom/osi/os/Linux/osdThread.c +++ b/src/libCom/osi/os/Linux/osdThread.c @@ -59,6 +59,7 @@ typedef struct commonAttr{ int maxPriority; int minPriority; int schedPolicy; + int usePolicy; } commonAttr; typedef struct epicsThreadOSD { @@ -82,6 +83,7 @@ typedef struct epicsThreadOSD { typedef struct { int min_pri, max_pri; int policy; + int ok; } priAvailable; #endif @@ -141,6 +143,8 @@ static void setSchedulingPolicy(epicsThreadOSD *pthreadInfo,int policy) #if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) int status; + if(!pcommonAttr->usePolicy) return; + status = pthread_attr_getschedparam( &pthreadInfo->attr,&pthreadInfo->schedParam); checkStatusOnce(status,"pthread_attr_getschedparam"); @@ -281,6 +285,7 @@ int low, try; prm->min_pri = min; prm->max_pri = try_pri(max, prm->policy) ? max-1 : max; + prm->ok = 1; return 0; } @@ -293,6 +298,7 @@ void *dummy; int status; arg.policy = a_p->schedPolicy; + arg.ok = 0; status = pthread_create(&id, 0, find_pri_range, &arg); checkStatusQuit(status, "pthread_create","epicsThreadInit"); @@ -302,6 +308,7 @@ int status; a_p->minPriority = arg.min_pri; a_p->maxPriority = arg.max_pri; + a_p->usePolicy = arg.ok; } #endif @@ -365,12 +372,11 @@ static void once(void) checkStatusOnce(status,"atexit"); epicsThreadOnceCalled = 1; } - + static void * start_routine(void *arg) { epicsThreadOSD *pthreadInfo = (epicsThreadOSD *)arg; int status; - int oldtype; sigset_t blockAllSig; char comm[16]; @@ -378,13 +384,11 @@ static void * start_routine(void *arg) snprintf(comm, sizeof(comm), "%s", pthreadInfo->name); prctl(PR_SET_NAME, comm, 0l, 0l, 0l); pthreadInfo->lwpId = syscall(SYS_gettid); - + sigfillset(&blockAllSig); pthread_sigmask(SIG_SETMASK,&blockAllSig,NULL); status = pthread_setspecific(getpthreadInfo,arg); checkStatusQuit(status,"pthread_setspecific","start_routine"); - status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&oldtype); - checkStatusQuit(status,"pthread_setcanceltype","start_routine"); status = mutexLock(&listLock); checkStatusQuit(status,"pthread_mutex_lock","start_routine"); ellAdd(&pthreadList,&pthreadInfo->node); @@ -509,7 +513,6 @@ epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate(const char *name, } status = pthread_sigmask(SIG_SETMASK,&oldSig,NULL); checkStatusOnce(status,"pthread_sigmask"); - return(pthreadInfo); } @@ -619,6 +622,7 @@ epicsShareFunc void epicsShareAPI epicsThreadSetPriority(epicsThreadId pthreadIn pthreadInfo->osiPriority = priority; if(!pthreadInfo->isFifoScheduled) return; #if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) + if(!pcommonAttr->usePolicy) return; pthreadInfo->schedParam.sched_priority = getOssPriorityValue(pthreadInfo); status = pthread_attr_setschedparam( &pthreadInfo->attr,&pthreadInfo->schedParam); @@ -769,7 +773,7 @@ static void showThreadInfo(epicsThreadOSD *pthreadInfo,unsigned int level) pthreadInfo->name,(void *) pthreadInfo,(unsigned long)pthreadInfo->lwpId, pthreadInfo->osiPriority,priority, - pthreadInfo->isSuspended ? "SUSPEND" : "OK"); + pthreadInfo->isSuspended?"SUSPEND":"OK"); } }